示例#1
0
void QgsMapLayer::exportNamedStyle( QDomDocument &doc, QString &errorMsg )
{
  QDomImplementation DomImplementation;
  QDomDocumentType documentType = DomImplementation.createDocumentType( "qgis", "http://mrcc.com/qgis.dtd", "SYSTEM" );
  QDomDocument myDocument( documentType );

  QDomElement myRootNode = myDocument.createElement( "qgis" );
  myRootNode.setAttribute( "version", QString( "%1" ).arg( QGis::QGIS_VERSION ) );
  myDocument.appendChild( myRootNode );

  myRootNode.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
  myRootNode.setAttribute( "minimumScale", QString::number( minimumScale() ) );
  myRootNode.setAttribute( "maximumScale", QString::number( maximumScale() ) );

#if 0
  // <transparencyLevelInt>
  QDomElement transparencyLevelIntElement = myDocument.createElement( "transparencyLevelInt" );
  QDomText    transparencyLevelIntText    = myDocument.createTextNode( QString::number( getTransparency() ) );
  transparencyLevelIntElement.appendChild( transparencyLevelIntText );
  myRootNode.appendChild( transparencyLevelIntElement );
#endif

  if ( !writeSymbology( myRootNode, myDocument, errorMsg ) )
  {
    errorMsg = QObject::tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
    return;
  }
  doc = myDocument;
}
示例#2
0
bool QgsMapLayer::writeLayerXML( QDomElement& layerElement, QDomDocument& document )
{
  // use scale dependent visibility flag
  layerElement.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
  layerElement.setAttribute( "minimumScale", QString::number( minimumScale() ) );
  layerElement.setAttribute( "maximumScale", QString::number( maximumScale() ) );

  // ID
  QDomElement layerId = document.createElement( "id" );
  QDomText layerIdText = document.createTextNode( id() );
  layerId.appendChild( layerIdText );

  layerElement.appendChild( layerId );

  // data source
  QDomElement dataSource = document.createElement( "datasource" );

  QString src = source();

  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
  // TODO: what about postgres, mysql and others, they should not go through writePath()
  if ( vlayer && vlayer->providerType() == "spatialite" )
  {
    QgsDataSourceURI uri( src );
    QString database = QgsProject::instance()->writePath( uri.database() );
    uri.setConnection( uri.host(), uri.port(), database, uri.username(), uri.password() );
    src = uri.uri();
  }
  else if ( vlayer && vlayer->providerType() == "ogr" )
  {
    QStringList theURIParts = src.split( "|" );
    theURIParts[0] = QgsProject::instance()->writePath( theURIParts[0] );
    src = theURIParts.join( "|" );
  }
  else if ( vlayer && vlayer->providerType() == "delimitedtext" )
  {
    QUrl urlSource = QUrl::fromEncoded( src.toAscii() );
    QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->writePath( urlSource.toLocalFile() ) );
    urlDest.setQueryItems( urlSource.queryItems() );
    src = QString::fromAscii( urlDest.toEncoded() );
  }
  else
  {
    src = QgsProject::instance()->writePath( src );
  }

  QDomText dataSourceText = document.createTextNode( src );
  dataSource.appendChild( dataSourceText );

  layerElement.appendChild( dataSource );


  // layer name
  QDomElement layerName = document.createElement( "layername" );
  QDomText layerNameText = document.createTextNode( originalName() );
  layerName.appendChild( layerNameText );

  // layer title
  QDomElement layerTitle = document.createElement( "title" ) ;
  QDomText layerTitleText = document.createTextNode( title() );
  layerTitle.appendChild( layerTitleText );

  // layer abstract
  QDomElement layerAbstract = document.createElement( "abstract" );
  QDomText layerAbstractText = document.createTextNode( abstract() );
  layerAbstract.appendChild( layerAbstractText );

  layerElement.appendChild( layerName );
  layerElement.appendChild( layerTitle );
  layerElement.appendChild( layerAbstract );

  // layer keyword list
  QStringList keywordStringList = keywordList().split( "," );
  if ( keywordStringList.size() > 0 )
  {
    QDomElement layerKeywordList = document.createElement( "keywordList" );
    for ( int i = 0; i < keywordStringList.size(); ++i )
    {
      QDomElement layerKeywordValue = document.createElement( "value" );
      QDomText layerKeywordText = document.createTextNode( keywordStringList.at( i ).trimmed() );
      layerKeywordValue.appendChild( layerKeywordText );
      layerKeywordList.appendChild( layerKeywordValue );
    }
    layerElement.appendChild( layerKeywordList );
  }

  // layer metadataUrl
  QString aDataUrl = dataUrl();
  if ( !aDataUrl.isEmpty() )
  {
    QDomElement layerDataUrl = document.createElement( "dataUrl" ) ;
    QDomText layerDataUrlText = document.createTextNode( aDataUrl );
    layerDataUrl.appendChild( layerDataUrlText );
    layerDataUrl.setAttribute( "format", dataUrlFormat() );
    layerElement.appendChild( layerDataUrl );
  }

  // layer attribution
  QString aAttribution = attribution();
  if ( !aAttribution.isEmpty() )
  {
    QDomElement layerAttribution = document.createElement( "attribution" ) ;
    QDomText layerAttributionText = document.createTextNode( aAttribution );
    layerAttribution.appendChild( layerAttributionText );
    layerAttribution.setAttribute( "href", attributionUrl() );
    layerElement.appendChild( layerAttribution );
  }

  // layer metadataUrl
  QString aMetadataUrl = metadataUrl();
  if ( !aMetadataUrl.isEmpty() )
  {
    QDomElement layerMetadataUrl = document.createElement( "metadataUrl" ) ;
    QDomText layerMetadataUrlText = document.createTextNode( aMetadataUrl );
    layerMetadataUrl.appendChild( layerMetadataUrlText );
    layerMetadataUrl.setAttribute( "type", metadataUrlType() );
    layerMetadataUrl.setAttribute( "format", metadataUrlFormat() );
    layerElement.appendChild( layerMetadataUrl );
  }

  // timestamp if supported
  if ( timestamp() > QDateTime() )
  {
    QDomElement stamp = document.createElement( "timestamp" );
    QDomText stampText = document.createTextNode( timestamp().toString( Qt::ISODate ) );
    stamp.appendChild( stampText );
    layerElement.appendChild( stamp );
  }

  layerElement.appendChild( layerName );

  // zorder
  // This is no longer stored in the project file. It is superfluous since the layers
  // are written and read in the proper order.

  // spatial reference system id
  QDomElement mySrsElement = document.createElement( "srs" );
  mCRS->writeXML( mySrsElement, document );
  layerElement.appendChild( mySrsElement );

#if 0
  // <transparencyLevelInt>
  QDomElement transparencyLevelIntElement = document.createElement( "transparencyLevelInt" );
  QDomText    transparencyLevelIntText    = document.createTextNode( QString::number( getTransparency() ) );
  transparencyLevelIntElement.appendChild( transparencyLevelIntText );
  maplayer.appendChild( transparencyLevelIntElement );
#endif

  // now append layer node to map layer node

  writeCustomProperties( layerElement, document );

  return writeXml( layerElement, document );

} // bool QgsMapLayer::writeXML
示例#3
0
double QgsScaleRangeWidget::minimumScaleDenom()
{
  return qRound( 1.0 / maximumScale() );
}
示例#4
0
QString QgsMapLayer::saveNamedStyle( const QString theURI, bool & theResultFlag )
{
  QString myErrorMessage;

  QDomImplementation DomImplementation;
  QDomDocumentType documentType =
    DomImplementation.createDocumentType(
      "qgis", "http://mrcc.com/qgis.dtd", "SYSTEM" );
  QDomDocument myDocument( documentType );
  QDomElement myRootNode = myDocument.createElement( "qgis" );
  myRootNode.setAttribute( "version", QString( "%1" ).arg( QGis::QGIS_VERSION ) );
  myDocument.appendChild( myRootNode );

  // use scale dependent visibility flag
  myRootNode.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
  myRootNode.setAttribute( "minimumScale", minimumScale() );
  myRootNode.setAttribute( "maximumScale", maximumScale() );

  // <transparencyLevelInt>
  QDomElement transparencyLevelIntElement = myDocument.createElement( "transparencyLevelInt" );
  QDomText    transparencyLevelIntText    = myDocument.createTextNode( QString::number( getTransparency() ) );
  transparencyLevelIntElement.appendChild( transparencyLevelIntText );
  myRootNode.appendChild( transparencyLevelIntElement );
  // now append layer node to map layer node

  QString errorMsg;
  if ( !writeSymbology( myRootNode, myDocument, errorMsg ) )
  {
    return tr( "Could not save symbology because:\n%1" ).arg( errorMsg );
  }

  // check if the uri is a file or ends with .qml,
  // which indicates that it should become one
  // everything else goes to the database
  QString filename;

  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
  if ( vlayer && vlayer->providerType() == "ogr" )
  {
    QStringList theURIParts = theURI.split( "|" );
    filename = theURIParts[0];
  }
  else if ( vlayer && vlayer->providerType() == "delimitedtext" )
  {
    filename = QUrl::fromEncoded( theURI.toAscii() ).toLocalFile();
  }
  else
  {
    filename = theURI;
  }

  QFileInfo myFileInfo( filename );
  if ( myFileInfo.exists() || filename.endsWith( ".qml", Qt::CaseInsensitive ) )
  {
    QFileInfo myDirInfo( myFileInfo.path() );  //excludes file name
    if ( !myDirInfo.isWritable() )
    {
      return tr( "The directory containing your dataset needs to be writable!" );
    }

    // now construct the file name for our .qml style file
    QString myFileName = myFileInfo.path() + QDir::separator() + myFileInfo.completeBaseName() + ".qml";

    QFile myFile( myFileName );
    if ( myFile.open( QFile::WriteOnly | QFile::Truncate ) )
    {
      QTextStream myFileStream( &myFile );
      // save as utf-8 with 2 spaces for indents
      myDocument.save( myFileStream, 2 );
      myFile.close();
      theResultFlag = true;
      return tr( "Created default style file as %1" ).arg( myFileName );
    }
    else
    {
      theResultFlag = false;
      return tr( "ERROR: Failed to created default style file as %1. Check file permissions and retry." ).arg( myFileName );
    }
  }
  else
  {
    QString qml = myDocument.toString();

    // read from database
    sqlite3 *myDatabase;
    sqlite3_stmt *myPreparedStatement;
    const char *myTail;
    int myResult;

    myResult = sqlite3_open( QDir( QgsApplication::qgisSettingsDirPath() ).absoluteFilePath( "qgis.qmldb" ).toUtf8().data(), &myDatabase );
    if ( myResult != SQLITE_OK )
    {
      return tr( "User database could not be opened." );
    }

    QByteArray param0 = theURI.toUtf8();
    QByteArray param1 = qml.toUtf8();

    QString mySql = "create table if not exists tbl_styles(style varchar primary key,qml varchar)";
    myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
    if ( myResult == SQLITE_OK )
    {
      if ( sqlite3_step( myPreparedStatement ) != SQLITE_DONE )
      {
        sqlite3_finalize( myPreparedStatement );
        sqlite3_close( myDatabase );
        theResultFlag = false;
        return tr( "The style table could not be created." );
      }
    }

    sqlite3_finalize( myPreparedStatement );

    mySql = "insert into tbl_styles(style,qml) values (?,?)";
    myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
    if ( myResult == SQLITE_OK )
    {
      if ( sqlite3_bind_text( myPreparedStatement, 1, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
           sqlite3_bind_text( myPreparedStatement, 2, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
           sqlite3_step( myPreparedStatement ) == SQLITE_DONE )
      {
        theResultFlag = true;
        myErrorMessage = tr( "The style %1 was saved to database" ).arg( theURI );
      }
    }

    sqlite3_finalize( myPreparedStatement );

    if ( !theResultFlag )
    {
      QString mySql = "update tbl_styles set qml=? where style=?";
      myResult = sqlite3_prepare( myDatabase, mySql.toUtf8().data(), mySql.toUtf8().length(), &myPreparedStatement, &myTail );
      if ( myResult == SQLITE_OK )
      {
        if ( sqlite3_bind_text( myPreparedStatement, 2, param0.data(), param0.length(), SQLITE_STATIC ) == SQLITE_OK &&
             sqlite3_bind_text( myPreparedStatement, 1, param1.data(), param1.length(), SQLITE_STATIC ) == SQLITE_OK &&
             sqlite3_step( myPreparedStatement ) == SQLITE_DONE )
        {
          theResultFlag = true;
          myErrorMessage = tr( "The style %1 was updated in the database." ).arg( theURI );
        }
        else
        {
          theResultFlag = false;
          myErrorMessage = tr( "The style %1 could not be updated in the database." ).arg( theURI );
        }
      }
      else
      {
        theResultFlag = false;
        myErrorMessage = tr( "The style %1 could not be inserted into database." ).arg( theURI );
      }

      sqlite3_finalize( myPreparedStatement );
    }

    sqlite3_close( myDatabase );
  }

  return myErrorMessage;
}
示例#5
0
bool QgsMapLayer::writeXML( QDomNode & layer_node, QDomDocument & document )
{
  // general layer metadata
  QDomElement maplayer = document.createElement( "maplayer" );

  // use scale dependent visibility flag
  maplayer.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
  maplayer.setAttribute( "minimumScale", minimumScale() );
  maplayer.setAttribute( "maximumScale", maximumScale() );

  // ID
  QDomElement layerId = document.createElement( "id" );
  QDomText layerIdText = document.createTextNode( id() );
  layerId.appendChild( layerIdText );

  maplayer.appendChild( layerId );

  // data source
  QDomElement dataSource = document.createElement( "datasource" );

  QString src = source();

  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
  if ( vlayer && vlayer->providerType() == "spatialite" )
  {
    QgsDataSourceURI uri( src );
    QString database = QgsProject::instance()->writePath( uri.database() );
    uri.setConnection( uri.host(), uri.port(), database, uri.username(), uri.password() );
    src = uri.uri();
  }
  else if ( vlayer && vlayer->providerType() == "ogr" )
  {
    QStringList theURIParts = src.split( "|" );
    theURIParts[0] = QgsProject::instance()->writePath( theURIParts[0] );
    src = theURIParts.join( "|" );
  }
  else if ( vlayer && vlayer->providerType() == "delimitedtext" )
  {
    QUrl urlSource = QUrl::fromEncoded( src.toAscii() );
    QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->writePath( urlSource.toLocalFile() ) );
    urlDest.setQueryItems( urlSource.queryItems() );
    src = QString::fromAscii( urlDest.toEncoded() );
  }
  else
  {
    src = QgsProject::instance()->writePath( src );
  }

  QDomText dataSourceText = document.createTextNode( src );
  dataSource.appendChild( dataSourceText );

  maplayer.appendChild( dataSource );


  // layer name
  QDomElement layerName = document.createElement( "layername" );
  QDomText layerNameText = document.createTextNode( name() );
  layerName.appendChild( layerNameText );

  // layer title
  QDomElement layerTitle = document.createElement( "title" ) ;
  QDomText layerTitleText = document.createTextNode( title() );
  layerTitle.appendChild( layerTitleText );

  // layer abstract
  QDomElement layerAbstract = document.createElement( "abstract" );
  QDomText layerAbstractText = document.createTextNode( abstract() );
  layerAbstract.appendChild( layerAbstractText );

  maplayer.appendChild( layerName );
  maplayer.appendChild( layerTitle );
  maplayer.appendChild( layerAbstract );

  // timestamp if supported
  if ( timestamp() > QDateTime() )
  {
    QDomElement stamp = document.createElement( "timestamp" );
    QDomText stampText = document.createTextNode( timestamp().toString( Qt::ISODate ) );
    stamp.appendChild( stampText );
    maplayer.appendChild( stamp );
  }

  maplayer.appendChild( layerName );

  // zorder
  // This is no longer stored in the project file. It is superfluous since the layers
  // are written and read in the proper order.

  // spatial reference system id
  QDomElement mySrsElement = document.createElement( "srs" );
  mCRS->writeXML( mySrsElement, document );
  maplayer.appendChild( mySrsElement );

  // <transparencyLevelInt>
  QDomElement transparencyLevelIntElement = document.createElement( "transparencyLevelInt" );
  QDomText    transparencyLevelIntText    = document.createTextNode( QString::number( getTransparency() ) );
  transparencyLevelIntElement.appendChild( transparencyLevelIntText );
  maplayer.appendChild( transparencyLevelIntElement );
  // now append layer node to map layer node

  layer_node.appendChild( maplayer );

  writeCustomProperties( maplayer, document );

  return writeXml( maplayer, document );

} // bool QgsMapLayer::writeXML
示例#6
0
int QDeclarativePinch::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QObject::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    if (_c == QMetaObject::InvokeMetaMethod) {
        if (_id < 11)
            qt_static_metacall(this, _c, _id, _a);
        _id -= 11;
    }
#ifndef QT_NO_PROPERTIES
      else if (_c == QMetaObject::ReadProperty) {
        void *_v = _a[0];
        switch (_id) {
        case 0: *reinterpret_cast< QGraphicsObject**>(_v) = target(); break;
        case 1: *reinterpret_cast< qreal*>(_v) = minimumScale(); break;
        case 2: *reinterpret_cast< qreal*>(_v) = maximumScale(); break;
        case 3: *reinterpret_cast< qreal*>(_v) = minimumRotation(); break;
        case 4: *reinterpret_cast< qreal*>(_v) = maximumRotation(); break;
        case 5: *reinterpret_cast< Axis*>(_v) = axis(); break;
        case 6: *reinterpret_cast< qreal*>(_v) = xmin(); break;
        case 7: *reinterpret_cast< qreal*>(_v) = xmax(); break;
        case 8: *reinterpret_cast< qreal*>(_v) = ymin(); break;
        case 9: *reinterpret_cast< qreal*>(_v) = ymax(); break;
        case 10: *reinterpret_cast< bool*>(_v) = active(); break;
        }
        _id -= 11;
    } else if (_c == QMetaObject::WriteProperty) {
        void *_v = _a[0];
        switch (_id) {
        case 0: setTarget(*reinterpret_cast< QGraphicsObject**>(_v)); break;
        case 1: setMinimumScale(*reinterpret_cast< qreal*>(_v)); break;
        case 2: setMaximumScale(*reinterpret_cast< qreal*>(_v)); break;
        case 3: setMinimumRotation(*reinterpret_cast< qreal*>(_v)); break;
        case 4: setMaximumRotation(*reinterpret_cast< qreal*>(_v)); break;
        case 5: setAxis(*reinterpret_cast< Axis*>(_v)); break;
        case 6: setXmin(*reinterpret_cast< qreal*>(_v)); break;
        case 7: setXmax(*reinterpret_cast< qreal*>(_v)); break;
        case 8: setYmin(*reinterpret_cast< qreal*>(_v)); break;
        case 9: setYmax(*reinterpret_cast< qreal*>(_v)); break;
        }
        _id -= 11;
    } else if (_c == QMetaObject::ResetProperty) {
        switch (_id) {
        case 0: resetTarget(); break;
        }
        _id -= 11;
    } else if (_c == QMetaObject::QueryPropertyDesignable) {
        _id -= 11;
    } else if (_c == QMetaObject::QueryPropertyScriptable) {
        _id -= 11;
    } else if (_c == QMetaObject::QueryPropertyStored) {
        _id -= 11;
    } else if (_c == QMetaObject::QueryPropertyEditable) {
        _id -= 11;
    } else if (_c == QMetaObject::QueryPropertyUser) {
        _id -= 11;
    }
#endif // QT_NO_PROPERTIES
    return _id;
}
示例#7
0
bool QgsMapLayer::writeLayerXML( QDomElement& layerElement, QDomDocument& document, const QString& relativeBasePath )
{
  // use scale dependent visibility flag
  layerElement.setAttribute( "hasScaleBasedVisibilityFlag", hasScaleBasedVisibility() ? 1 : 0 );
  layerElement.setAttribute( "minimumScale", QString::number( minimumScale() ) );
  layerElement.setAttribute( "maximumScale", QString::number( maximumScale() ) );

  // ID
  QDomElement layerId = document.createElement( "id" );
  QDomText layerIdText = document.createTextNode( id() );
  layerId.appendChild( layerIdText );

  layerElement.appendChild( layerId );

  // data source
  QDomElement dataSource = document.createElement( "datasource" );

  QString src = source();

  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( this );
  // TODO: what about postgres, mysql and others, they should not go through writePath()
  if ( vlayer && vlayer->providerType() == "spatialite" )
  {
    QgsDataSourceURI uri( src );
    QString database = QgsProject::instance()->writePath( uri.database(), relativeBasePath );
    uri.setConnection( uri.host(), uri.port(), database, uri.username(), uri.password() );
    src = uri.uri();
  }
  else if ( vlayer && vlayer->providerType() == "ogr" )
  {
    QStringList theURIParts = src.split( "|" );
    theURIParts[0] = QgsProject::instance()->writePath( theURIParts[0], relativeBasePath );
    src = theURIParts.join( "|" );
  }
  else if ( vlayer && vlayer->providerType() == "gpx" )
  {
    QStringList theURIParts = src.split( "?" );
    theURIParts[0] = QgsProject::instance()->writePath( theURIParts[0], relativeBasePath );
    src = theURIParts.join( "?" );
  }
  else if ( vlayer && vlayer->providerType() == "delimitedtext" )
  {
    QUrl urlSource = QUrl::fromEncoded( src.toAscii() );
    QUrl urlDest = QUrl::fromLocalFile( QgsProject::instance()->writePath( urlSource.toLocalFile(), relativeBasePath ) );
    urlDest.setQueryItems( urlSource.queryItems() );
    src = QString::fromAscii( urlDest.toEncoded() );
  }
  else
  {
    bool handled = false;

    if ( !vlayer )
    {
      QgsRasterLayer *rlayer = qobject_cast<QgsRasterLayer *>( this );
      // Update path for subdataset
      if ( rlayer && rlayer->providerType() == "gdal" )
      {
        if ( src.startsWith( "NETCDF:" ) )
        {
          // NETCDF:filename:variable
          // filename can be quoted with " as it can contain colons
          QRegExp r( "NETCDF:(.+):([^:]+)" );
          if ( r.exactMatch( src ) )
          {
            QString filename = r.cap( 1 );
            if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
              filename = filename.mid( 1, filename.length() - 2 );
            src = "NETCDF:\"" + QgsProject::instance()->writePath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
            handled = true;
          }
        }
        else if ( src.startsWith( "HDF4_SDS:" ) )
        {
          // HDF4_SDS:subdataset_type:file_name:subdataset_index
          // filename can be quoted with " as it can contain colons
          QRegExp r( "HDF4_SDS:([^:]+):(.+):([^:]+)" );
          if ( r.exactMatch( src ) )
          {
            QString filename = r.cap( 2 );
            if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
              filename = filename.mid( 1, filename.length() - 2 );
            src = "HDF4_SDS:" + r.cap( 1 ) + ":\"" + QgsProject::instance()->writePath( filename, relativeBasePath ) + "\":" + r.cap( 3 );
            handled = true;
          }
        }
        else if ( src.startsWith( "HDF5:" ) )
        {
          // HDF5:file_name:subdataset
          // filename can be quoted with " as it can contain colons
          QRegExp r( "HDF5:(.+):([^:]+)" );
          if ( r.exactMatch( src ) )
          {
            QString filename = r.cap( 1 );
            if ( filename.startsWith( '"' ) && filename.endsWith( '"' ) )
              filename = filename.mid( 1, filename.length() - 2 );
            src = "HDF5:\"" + QgsProject::instance()->writePath( filename, relativeBasePath ) + "\":" + r.cap( 2 );
            handled = true;
          }
        }
        else if ( src.contains( QRegExp( "^(NITF_IM|RADARSAT_2_CALIB):" ) ) )
        {
          // NITF_IM:0:filename
          // RADARSAT_2_CALIB:?:filename
          QRegExp r( "([^:]+):([^:]+):(.+)" );
          if ( r.exactMatch( src ) )
          {
            src = r.cap( 1 ) + ":" + r.cap( 2 ) + ":" + QgsProject::instance()->writePath( r.cap( 3 ), relativeBasePath );
            handled = true;
          }
        }
      }
    }

    if ( !handled )
      src = QgsProject::instance()->writePath( src, relativeBasePath );
  }

  QDomText dataSourceText = document.createTextNode( src );
  dataSource.appendChild( dataSourceText );

  layerElement.appendChild( dataSource );


  // layer name
  QDomElement layerName = document.createElement( "layername" );
  QDomText layerNameText = document.createTextNode( originalName() );
  layerName.appendChild( layerNameText );

  // layer title
  QDomElement layerTitle = document.createElement( "title" );
  QDomText layerTitleText = document.createTextNode( title() );
  layerTitle.appendChild( layerTitleText );

  // layer abstract
  QDomElement layerAbstract = document.createElement( "abstract" );
  QDomText layerAbstractText = document.createTextNode( abstract() );
  layerAbstract.appendChild( layerAbstractText );

  layerElement.appendChild( layerName );
  layerElement.appendChild( layerTitle );
  layerElement.appendChild( layerAbstract );

  // layer keyword list
  QStringList keywordStringList = keywordList().split( "," );
  if ( keywordStringList.size() > 0 )
  {
    QDomElement layerKeywordList = document.createElement( "keywordList" );
    for ( int i = 0; i < keywordStringList.size(); ++i )
    {
      QDomElement layerKeywordValue = document.createElement( "value" );
      QDomText layerKeywordText = document.createTextNode( keywordStringList.at( i ).trimmed() );
      layerKeywordValue.appendChild( layerKeywordText );
      layerKeywordList.appendChild( layerKeywordValue );
    }
    layerElement.appendChild( layerKeywordList );
  }

  // layer metadataUrl
  QString aDataUrl = dataUrl();
  if ( !aDataUrl.isEmpty() )
  {
    QDomElement layerDataUrl = document.createElement( "dataUrl" );
    QDomText layerDataUrlText = document.createTextNode( aDataUrl );
    layerDataUrl.appendChild( layerDataUrlText );
    layerDataUrl.setAttribute( "format", dataUrlFormat() );
    layerElement.appendChild( layerDataUrl );
  }

  // layer legendUrl
  QString aLegendUrl = legendUrl();
  if ( !aLegendUrl.isEmpty() )
  {
    QDomElement layerLegendUrl = document.createElement( "legendUrl" );
    QDomText layerLegendUrlText = document.createTextNode( aLegendUrl );
    layerLegendUrl.appendChild( layerLegendUrlText );
    layerLegendUrl.setAttribute( "format", legendUrlFormat() );
    layerElement.appendChild( layerLegendUrl );
  }

  // layer attribution
  QString aAttribution = attribution();
  if ( !aAttribution.isEmpty() )
  {
    QDomElement layerAttribution = document.createElement( "attribution" );
    QDomText layerAttributionText = document.createTextNode( aAttribution );
    layerAttribution.appendChild( layerAttributionText );
    layerAttribution.setAttribute( "href", attributionUrl() );
    layerElement.appendChild( layerAttribution );
  }

  // layer metadataUrl
  QString aMetadataUrl = metadataUrl();
  if ( !aMetadataUrl.isEmpty() )
  {
    QDomElement layerMetadataUrl = document.createElement( "metadataUrl" );
    QDomText layerMetadataUrlText = document.createTextNode( aMetadataUrl );
    layerMetadataUrl.appendChild( layerMetadataUrlText );
    layerMetadataUrl.setAttribute( "type", metadataUrlType() );
    layerMetadataUrl.setAttribute( "format", metadataUrlFormat() );
    layerElement.appendChild( layerMetadataUrl );
  }

  // timestamp if supported
  if ( timestamp() > QDateTime() )
  {
    QDomElement stamp = document.createElement( "timestamp" );
    QDomText stampText = document.createTextNode( timestamp().toString( Qt::ISODate ) );
    stamp.appendChild( stampText );
    layerElement.appendChild( stamp );
  }

  layerElement.appendChild( layerName );

  // zorder
  // This is no longer stored in the project file. It is superfluous since the layers
  // are written and read in the proper order.

  // spatial reference system id
  QDomElement mySrsElement = document.createElement( "srs" );
  mCRS->writeXML( mySrsElement, document );
  layerElement.appendChild( mySrsElement );

#if 0
  // <transparencyLevelInt>
  QDomElement transparencyLevelIntElement = document.createElement( "transparencyLevelInt" );
  QDomText    transparencyLevelIntText    = document.createTextNode( QString::number( getTransparency() ) );
  transparencyLevelIntElement.appendChild( transparencyLevelIntText );
  maplayer.appendChild( transparencyLevelIntElement );
#endif

  // now append layer node to map layer node

  writeCustomProperties( layerElement, document );

  return writeXml( layerElement, document );

} // bool QgsMapLayer::writeXML