QSize QgsSymbolV2LegendNode::minimumIconSize() const
{
    QSize minSz( 16, 16 );
    if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbolV2::Marker )
    {
        QScopedPointer<QgsRenderContext> context( createTemporaryRenderContext() );
        minSz = QgsImageOperation::nonTransparentImageRect(
                    QgsSymbolLayerV2Utils::symbolPreviewPixmap( mItem.symbol(), QSize( 512, 512 ),
                            context.data() ).toImage(),
                    minSz,
                    true ).size();
    }
    else if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbolV2::Line )
    {
        QScopedPointer<QgsRenderContext> context( createTemporaryRenderContext() );
        minSz = QgsImageOperation::nonTransparentImageRect(
                    QgsSymbolLayerV2Utils::symbolPreviewPixmap( mItem.symbol(), QSize( minSz.width(), 512 ),
                            context.data() ).toImage(),
                    minSz,
                    true ).size();
    }

    if ( mItem.level() != 0 && !( model() && model()->testFlag( QgsLayerTreeModel::ShowLegendAsTree ) ) )
        minSz.setWidth( mItem.level() * indentSize + minSz.width() );

    return minSz;
}
void QgsDataDefinedSizeLegendNode::cacheImage() const
{
  if ( mImage.isNull() )
  {
    std::unique_ptr<QgsRenderContext> context( createTemporaryRenderContext() );
    if ( !context )
    {
      context.reset( new QgsRenderContext );
      context->setScaleFactor( 96 / 25.4 );
    }
    mImage = mSettings->collapsedLegendImage( *context );
  }
}
QVariant QgsSymbolV2LegendNode::data( int role ) const
{
    if ( role == Qt::DisplayRole )
    {
        return mLabel;
    }
    else if ( role == Qt::EditRole )
    {
        return mUserLabel.isEmpty() ? mItem.label() : mUserLabel;
    }
    else if ( role == Qt::DecorationRole )
    {
        if ( mPixmap.isNull() || mPixmap.size() != mIconSize )
        {
            QPixmap pix;
            if ( mItem.symbol() )
            {
                QScopedPointer<QgsRenderContext> context( createTemporaryRenderContext() );
                pix = QgsSymbolLayerV2Utils::symbolPreviewPixmap( mItem.symbol(), mIconSize, context.data() );
            }
            else
            {
                pix = QPixmap( mIconSize );
                pix.fill( Qt::transparent );
            }

            if ( mItem.level() == 0 || ( model() && model()->testFlag( QgsLayerTreeModel::ShowLegendAsTree ) ) )
                mPixmap = pix;
            else
            {
                // ident the symbol icon to make it look like a tree structure
                QPixmap pix2( pix.width() + mItem.level() * indentSize, pix.height() );
                pix2.fill( Qt::transparent );
                QPainter p( &pix2 );
                p.drawPixmap( mItem.level() * indentSize, 0, pix );
                p.end();
                mPixmap = pix2;
            }
        }
        return mPixmap;
    }
    else if ( role == Qt::CheckStateRole )
    {
        if ( !mItem.isCheckable() )
            return QVariant();

        QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( mLayerNode->layer() );
        if ( !vlayer || !vlayer->rendererV2() )
            return QVariant();

        return vlayer->rendererV2()->legendSymbolItemChecked( mItem.ruleKey() ) ? Qt::Checked : Qt::Unchecked;
    }
    else if ( role == RuleKeyRole )
    {
        return mItem.ruleKey();
    }
    else if ( role == SymbolV2LegacyRuleKeyRole )
    {
        return QVariant::fromValue<void*>( mItem.legacyRuleKey() );
    }
    else if ( role == ParentRuleKeyRole )
    {
        return mItem.parentRuleKey();
    }

    return QVariant();
}
QVariant QgsSymbolLegendNode::data( int role ) const
{
  if ( role == Qt::DisplayRole )
  {
    return mLabel;
  }
  else if ( role == Qt::EditRole )
  {
    return mUserLabel.isEmpty() ? mItem.label() : mUserLabel;
  }
  else if ( role == Qt::DecorationRole )
  {
    if ( mPixmap.isNull() || mPixmap.size() != mIconSize )
    {
      QPixmap pix;
      if ( mItem.symbol() )
      {
        std::unique_ptr<QgsRenderContext> context( createTemporaryRenderContext() );
        pix = QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), mIconSize, 0, context.get() );

        if ( !mTextOnSymbolLabel.isEmpty() && context )
        {
          QPainter painter( &pix );
          painter.setRenderHint( QPainter::Antialiasing );
          context->setPainter( &painter );
          QFontMetricsF fm( mTextOnSymbolTextFormat.scaledFont( *context ) );
          qreal yBaselineVCenter = ( mIconSize.height() + fm.ascent() - fm.descent() ) / 2;
          QgsTextRenderer::drawText( QPointF( mIconSize.width() / 2, yBaselineVCenter ), 0, QgsTextRenderer::AlignCenter,
                                     QStringList() << mTextOnSymbolLabel, *context, mTextOnSymbolTextFormat );
        }
      }
      else
      {
        pix = QPixmap( mIconSize );
        pix.fill( Qt::transparent );
      }

      if ( mItem.level() == 0 || ( model() && model()->testFlag( QgsLayerTreeModel::ShowLegendAsTree ) ) )
        mPixmap = pix;
      else
      {
        // ident the symbol icon to make it look like a tree structure
        QPixmap pix2( pix.width() + mItem.level() * INDENT_SIZE, pix.height() );
        pix2.fill( Qt::transparent );
        QPainter p( &pix2 );
        p.drawPixmap( mItem.level() * INDENT_SIZE, 0, pix );
        p.end();
        mPixmap = pix2;
      }
    }
    return mPixmap;
  }
  else if ( role == Qt::CheckStateRole )
  {
    if ( !mItem.isCheckable() )
      return QVariant();

    QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mLayerNode->layer() );
    if ( !vlayer || !vlayer->renderer() )
      return QVariant();

    return vlayer->renderer()->legendSymbolItemChecked( mItem.ruleKey() ) ? Qt::Checked : Qt::Unchecked;
  }
  else if ( role == RuleKeyRole )
  {
    return mItem.ruleKey();
  }
  else if ( role == ParentRuleKeyRole )
  {
    return mItem.parentRuleKey();
  }

  return QVariant();
}
QSize QgsSymbolLegendNode::minimumIconSize() const
{
  std::unique_ptr<QgsRenderContext> context( createTemporaryRenderContext() );
  return minimumIconSize( context.get() );
}
QSize QgsSymbolLegendNode::minimumIconSize() const
{
  QScopedPointer<QgsRenderContext> context( createTemporaryRenderContext() );
  return minimumIconSize( context.data() );
}