QgsDiagramFactory* QgsSVGDiagramFactoryWidget::createFactory()
{
  QString filePath = mPictureLineEdit->text();
  if ( filePath.isEmpty() )
  {
    return 0;
  }

  QFile svgFile( filePath );
  if ( !svgFile.exists() )
  {
    return 0;
  }

  //open file and read binary array
  if ( !svgFile.open( QIODevice::ReadOnly ) )
  {
    return 0;
  }

  QByteArray svgData = svgFile.readAll();

  QgsSVGDiagramFactory* factory = new QgsSVGDiagramFactory();
  if ( !factory->setSVGData( svgData, filePath ) )
  {
    delete factory; return 0;
  }

  return factory;
}
Пример #2
0
void QgsSvgCache::replaceParamsAndCacheSvg( QgsSvgCacheEntry* entry )
{
  if ( !entry )
  {
    return;
  }

  QFile svgFile( entry->file );
  if ( !svgFile.open( QIODevice::ReadOnly ) )
  {
    return;
  }

  QDomDocument svgDoc;
  if ( !svgDoc.setContent( &svgFile ) )
  {
    return;
  }

  //replace fill color, outline color, outline with in all nodes
  QDomElement docElem = svgDoc.documentElement();
  replaceElemParams( docElem, entry->fill, entry->outline, entry->outlineWidth );

  entry->svgContent = svgDoc.toByteArray();
  mTotalSize += entry->svgContent.size();
}
Пример #3
0
QIcon IconProducer::buildIcon(QString pathToSvgFile)
{
    QFile svgFile(pathToSvgFile);
    svgFile.open(QIODevice::ReadOnly);
    QByteArray svg = svgFile.readAll();

    QSvgRenderer render(svg);
    QPixmap pixmap(render.defaultSize());
    pixmap.fill(QColor(0,0,0,0));
    QPainter painter(&pixmap);
    render.render(&painter);
    return QIcon(pixmap);
}
Пример #4
0
void QgsSvgCache::containsParams( const QString& path, bool& hasFillParam, QColor& defaultFillColor, bool& hasOutlineParam, QColor& defaultOutlineColor,
                                  bool& hasOutlineWidthParam, double& defaultOutlineWidth ) const
{
  defaultFillColor = QColor( Qt::black );
  defaultOutlineColor = QColor( Qt::black );
  defaultOutlineWidth = 1.0;

  QFile svgFile( path );
  if ( !svgFile.open( QIODevice::ReadOnly ) )
  {
    return;
  }

  QDomDocument svgDoc;
  if ( !svgDoc.setContent( &svgFile ) )
  {
    return;
  }

  QDomElement docElem = svgDoc.documentElement();
  containsElemParams( docElem, hasFillParam, defaultFillColor, hasOutlineParam, defaultOutlineColor, hasOutlineWidthParam, defaultOutlineWidth );
}
Пример #5
0
QByteArray QgsSvgCache::getImageData( const QString &path ) const
{
  // is it a path to local file?
  QFile svgFile( path );
  if ( svgFile.exists() )
  {
    if ( svgFile.open( QIODevice::ReadOnly ) )
    {
      return svgFile.readAll();
    }
    else
    {
      return QByteArray();
    }
  }

  // maybe it's a url...
  if ( !path.contains( "://" ) ) // otherwise short, relative SVG paths might be considered URLs
  {
    return QByteArray();
  }

  QUrl svgUrl( path );
  if ( !svgUrl.isValid() )
  {
    return QByteArray();
  }

  // check whether it's a url pointing to a local file
  if ( svgUrl.scheme().compare( "file", Qt::CaseInsensitive ) == 0 )
  {
    svgFile.setFileName( svgUrl.toLocalFile() );
    if ( svgFile.exists() )
    {
      if ( svgFile.open( QIODevice::ReadOnly ) )
      {
        return svgFile.readAll();
      }
    }

    // not found...
    return QByteArray();
  }

  // the url points to a remote resource, download it!
  QNetworkReply *reply = 0;

  // The following code blocks until the file is downloaded...
  // TODO: use signals to get reply finished notification, in this moment
  // it's executed while rendering.
  while ( 1 )
  {
    QgsDebugMsg( QString( "get svg: %1" ).arg( svgUrl.toString() ) );
    QNetworkRequest request( svgUrl );
    request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
    request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );

    reply = QgsNetworkAccessManager::instance()->get( request );
    connect( reply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( downloadProgress( qint64, qint64 ) ) );

    //emit statusChanged( tr( "Downloading svg." ) );

    // wait until the image download finished
    // TODO: connect to the reply->finished() signal
    while ( !reply->isFinished() )
    {
      QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents, 500 );
    }

    if ( reply->error() != QNetworkReply::NoError )
    {
      QgsMessageLog::logMessage( tr( "SVG request failed [error: %1 - url: %2]" ).arg( reply->errorString() ).arg( reply->url().toString() ), tr( "SVG" ) );

      reply->deleteLater();
      return QByteArray();
    }

    QVariant redirect = reply->attribute( QNetworkRequest::RedirectionTargetAttribute );
    if ( redirect.isNull() )
    {
      // neither network error nor redirection
      // TODO: cache the image
      break;
    }

    // do a new request to the redirect url
    svgUrl = redirect.toUrl();
    reply->deleteLater();
  }

  QVariant status = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute );
  if ( !status.isNull() && status.toInt() >= 400 )
  {
    QVariant phrase = reply->attribute( QNetworkRequest::HttpReasonPhraseAttribute );
    QgsMessageLog::logMessage( tr( "SVG request error [status: %1 - reason phrase: %2]" ).arg( status.toInt() ).arg( phrase.toString() ), tr( "SVG" ) );

    reply->deleteLater();
    return QByteArray();
  }

  QString contentType = reply->header( QNetworkRequest::ContentTypeHeader ).toString();
  QgsDebugMsg( "contentType: " + contentType );
  if ( !contentType.startsWith( "image/svg+xml", Qt::CaseInsensitive ) )
  {
    reply->deleteLater();
    return QByteArray();
  }

  // read the image data
  QByteArray ba = reply->readAll();
  reply->deleteLater();

  return ba;
}
Пример #6
0
void TestQgsProject::testPathResolverSvg()
{
  QString dataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
  QString layerPath = dataDir + "/points.shp";

  QVERIFY( QgsSymbolLayerUtils::svgSymbolNameToPath( QString(), QgsPathResolver() ).isEmpty() );
  QVERIFY( QgsSymbolLayerUtils::svgSymbolPathToName( QString(), QgsPathResolver() ).isEmpty() );

  // build a project with 3 layers, each having a simple renderer with SVG marker
  // - existing SVG file in project dir
  // - existing SVG file in QGIS dir
  // - non-exsiting SVG file

  QTemporaryDir dir;
  QVERIFY( dir.isValid() );
  // on mac the returned path was not canonical and the resolver failed to convert paths properly
  QString dirPath = QFileInfo( dir.path() ).canonicalFilePath();

  QString projectFilename = dirPath + "/project.qgs";
  QString ourSvgPath = dirPath + "/valid.svg";
  QString invalidSvgPath = dirPath + "/invalid.svg";

  QFile svgFile( ourSvgPath );
  QVERIFY( svgFile.open( QIODevice::WriteOnly ) );
  svgFile.write( "<svg/>" );   // not a proper SVG, but good enough for this case
  svgFile.close();

  QVERIFY( QFileInfo::exists( ourSvgPath ) );  // should exist now

  QString librarySvgPath = QgsSymbolLayerUtils::svgSymbolNameToPath( QStringLiteral( "transport/transport_airport.svg" ), QgsPathResolver() );
  QCOMPARE( QgsSymbolLayerUtils::svgSymbolPathToName( librarySvgPath, QgsPathResolver() ), QStringLiteral( "transport/transport_airport.svg" ) );

  QgsVectorLayer *layer1 = new QgsVectorLayer( layerPath, QStringLiteral( "points 1" ), QStringLiteral( "ogr" ) );
  _useRendererWithSvgSymbol( layer1, ourSvgPath );

  QgsVectorLayer *layer2 = new QgsVectorLayer( layerPath, QStringLiteral( "points 2" ), QStringLiteral( "ogr" ) );
  _useRendererWithSvgSymbol( layer2, invalidSvgPath );

  QgsVectorLayer *layer3 = new QgsVectorLayer( layerPath, QStringLiteral( "points 3" ), QStringLiteral( "ogr" ) );
  _useRendererWithSvgSymbol( layer3, librarySvgPath );

  QVERIFY( layer1->isValid() );

  QgsProject project;
  project.addMapLayers( QList<QgsMapLayer *>() << layer1 << layer2 << layer3 );
  project.write( projectFilename );

  // make sure the path resolver works with relative paths (enabled by default)
  QCOMPARE( project.pathResolver().readPath( "./a.txt" ), dirPath + "/a.txt" );
  QCOMPARE( project.pathResolver().writePath( dirPath + "/a.txt" ), QString( "./a.txt" ) );

  // check that the saved paths are relative

  // key = layer name, value = svg path
  QHash<QString, QString> projectFileSvgPaths = _parseSvgPathsForLayers( projectFilename );

  QCOMPARE( projectFileSvgPaths.count(), 3 );
  QCOMPARE( projectFileSvgPaths["points 1"], QString( "./valid.svg" ) ); // relative path to project
  QCOMPARE( projectFileSvgPaths["points 2"], invalidSvgPath );  // full path to non-existent file (not sure why - but that's how it works now)
  QCOMPARE( projectFileSvgPaths["points 3"], QString( "transport/transport_airport.svg" ) );  // relative path to library

  // load project again, check that the paths are absolute
  QgsProject projectLoaded;
  projectLoaded.read( projectFilename );
  QString svg1 = _getLayerSvgMarkerPath( projectLoaded, QStringLiteral( "points 1" ) );
  QString svg2 = _getLayerSvgMarkerPath( projectLoaded, QStringLiteral( "points 2" ) );
  QString svg3 = _getLayerSvgMarkerPath( projectLoaded, QStringLiteral( "points 3" ) );
  QCOMPARE( svg1, ourSvgPath );
  QCOMPARE( svg2, invalidSvgPath );
  QCOMPARE( svg3, librarySvgPath );

  //
  // now let's use these layers in embedded in another project...
  //

  QList<QDomNode> brokenNodes;
  QgsProject projectMaster;
  QVERIFY( projectMaster.createEmbeddedLayer( layer1->id(), projectFilename, brokenNodes ) );
  QVERIFY( projectMaster.createEmbeddedLayer( layer2->id(), projectFilename, brokenNodes ) );
  QVERIFY( projectMaster.createEmbeddedLayer( layer3->id(), projectFilename, brokenNodes ) );

  QString svg1x = _getLayerSvgMarkerPath( projectMaster, QStringLiteral( "points 1" ) );
  QString svg2x = _getLayerSvgMarkerPath( projectLoaded, QStringLiteral( "points 2" ) );
  QString svg3x = _getLayerSvgMarkerPath( projectLoaded, QStringLiteral( "points 3" ) );
  QCOMPARE( svg1x, ourSvgPath );
  QCOMPARE( svg2x, invalidSvgPath );
  QCOMPARE( svg3x, librarySvgPath );

}
Пример #7
0
bool KGameTheme::load(const QString &fileName)
{
    if (fileName.isEmpty()) {
        qDebug() << "Refusing to load theme with no name";
        return false;
    }
    QString filePath = QStandardPaths::locate(
        QStandardPaths::DataLocation, fileName, QStandardPaths::LocateFile );
    qDebug() << "Attempting to load .desktop at" << filePath;
    if (filePath.isEmpty()) {
        return false;
    }

    // verify if it is a valid file first and if we can open it
    QFile themefile(filePath);
    if (!themefile.open(QIODevice::ReadOnly)) {
        qDebug() << "Could not open .desktop theme file" << filePath;
        return false;
    }
    d->prefix = QFileInfo(themefile).absolutePath() + '/';
    themefile.close();

    KConfig themeconfig(filePath, KConfig::SimpleConfig);
    if (!themeconfig.hasGroup(d->themeGroup)) {
        qDebug() << "Config group" << d->themeGroup << "does not exist in" << filePath;
        return false;
    }
    KConfigGroup group = themeconfig.group(d->themeGroup);

    //Copy the whole entryMap, so we can inherit generic properties as well, reducing the need to subclass for simple implementations
    d->themeproperties = group.entryMap();

    //Version control
    int themeversion = group.readEntry("VersionFormat", 0);
    //Format is increased when we have incompatible changes, meaning that older clients are not able to use the remaining information safely
    if (themeversion > kThemeVersionFormat) {
        return false;
    }

    QString graphName = group.readEntry("FileName");
    //d->graphics = KStandardDirs::locate("appdata", graphName);
    d->graphics = d->prefix + graphName;
    if (d->graphics.isEmpty()) return false;

    // let's see if svg file exists and can be opened
    QFile svgFile(d->graphics);
    if (!svgFile.open(QIODevice::ReadOnly)) {
        qDebug() << "Could not open file" << d->graphics;
        return false;
    }

    QString previewName = group.readEntry("Preview");
    //QString graphicsPath = KStandardDirs::locate("appdata", previewName);
    QString graphicsPath = d->prefix + previewName;
    d->preview = QPixmap(graphicsPath);

    d->fileName = fileName;
    d->fullPath = filePath;
    d->loaded = true;
    return true;
}
Пример #8
0
QByteArray QgsSvgCache::getImageData( const QString &path ) const
{
  // is it a path to local file?
  QFile svgFile( path );
  if ( svgFile.exists() )
  {
    if ( svgFile.open( QIODevice::ReadOnly ) )
    {
      return svgFile.readAll();
    }
    else
    {
      return mMissingSvg;
    }
  }

  // maybe it's an embedded base64 string
  if ( path.startsWith( QLatin1String( "base64:" ), Qt::CaseInsensitive ) )
  {
    QByteArray base64 = path.mid( 7 ).toLocal8Bit(); // strip 'base64:' prefix
    return QByteArray::fromBase64( base64, QByteArray::OmitTrailingEquals );
  }

  // maybe it's a url...
  if ( !path.contains( QLatin1String( "://" ) ) ) // otherwise short, relative SVG paths might be considered URLs
  {
    return mMissingSvg;
  }

  QUrl svgUrl( path );
  if ( !svgUrl.isValid() )
  {
    return mMissingSvg;
  }

  // check whether it's a url pointing to a local file
  if ( svgUrl.scheme().compare( QLatin1String( "file" ), Qt::CaseInsensitive ) == 0 )
  {
    svgFile.setFileName( svgUrl.toLocalFile() );
    if ( svgFile.exists() )
    {
      if ( svgFile.open( QIODevice::ReadOnly ) )
      {
        return svgFile.readAll();
      }
    }

    // not found...
    return mMissingSvg;
  }

  QMutexLocker locker( &mMutex );

  // already a request in progress for this url
  if ( mPendingRemoteUrls.contains( path ) )
    return mFetchingSvg;

  if ( mRemoteContentCache.contains( path ) )
  {
    // already fetched this content - phew. Just return what we already got.
    return *mRemoteContentCache[ path ];
  }

  mPendingRemoteUrls.insert( path );
  //fire up task to fetch image in background
  QNetworkRequest request( svgUrl );
  request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
  request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );

  QgsNetworkContentFetcherTask *task = new QgsNetworkContentFetcherTask( request );
  connect( task, &QgsNetworkContentFetcherTask::fetched, this, [this, task, path]
  {
    QMutexLocker locker( &mMutex );

    QNetworkReply *reply = task->reply();
    if ( !reply )
    {
      // canceled
      QMetaObject::invokeMethod( const_cast< QgsSvgCache * >( this ), "onRemoteSvgFetched", Qt::QueuedConnection, Q_ARG( QString, path ), Q_ARG( bool, false ) );
      return;
    }

    if ( reply->error() != QNetworkReply::NoError )
    {
      QgsMessageLog::logMessage( tr( "SVG request failed [error: %1 - url: %2]" ).arg( reply->errorString(), path ), tr( "SVG" ) );
      return;
    }

    bool ok = true;

    QVariant status = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute );
    if ( !status.isNull() && status.toInt() >= 400 )
    {
      QVariant phrase = reply->attribute( QNetworkRequest::HttpReasonPhraseAttribute );
      QgsMessageLog::logMessage( tr( "SVG request error [status: %1 - reason phrase: %2] for %3" ).arg( status.toInt() ).arg( phrase.toString(), path ), tr( "SVG" ) );
      mRemoteContentCache.insert( path, new QByteArray( mMissingSvg ) );
      ok = false;
    }

    // we accept both real SVG mime types AND plain text types - because some sites
    // (notably github) serve up svgs as raw text
    QString contentType = reply->header( QNetworkRequest::ContentTypeHeader ).toString();
    if ( !contentType.startsWith( QLatin1String( "image/svg+xml" ), Qt::CaseInsensitive )
         && !contentType.startsWith( QLatin1String( "text/plain" ), Qt::CaseInsensitive ) )
    {
      QgsMessageLog::logMessage( tr( "Unexpected MIME type %1 received for %2" ).arg( contentType, path ), tr( "SVG" ) );
      mRemoteContentCache.insert( path, new QByteArray( mMissingSvg ) );
      ok = false;
    }

    if ( ok )
    {
      // read the image data
      mRemoteContentCache.insert( path, new QByteArray( reply->readAll() ) );
    }
    QMetaObject::invokeMethod( const_cast< QgsSvgCache * >( this ), "onRemoteSvgFetched", Qt::QueuedConnection, Q_ARG( QString, path ), Q_ARG( bool, true ) );
  } );