diff --git a/python/core/auto_generated/symbology/qgssymbollayerutils.sip.in b/python/core/auto_generated/symbology/qgssymbollayerutils.sip.in index 17ceae770711..38d6c7923ef3 100644 --- a/python/core/auto_generated/symbology/qgssymbollayerutils.sip.in +++ b/python/core/auto_generated/symbology/qgssymbollayerutils.sip.in @@ -286,13 +286,19 @@ Returns an icon preview for a color ramp. .. seealso:: :py:func:`colorRampPreviewPixmap` %End - static QPixmap colorRampPreviewPixmap( QgsColorRamp *ramp, QSize size, int padding = 0 ); + static QPixmap colorRampPreviewPixmap( QgsColorRamp *ramp, QSize size, int padding = 0, Qt::Orientation direction = Qt::Horizontal, + bool flipDirection = false, bool drawTransparentBackground = true ); %Docstring Returns a pixmap preview for a color ramp. :param ramp: color ramp :param size: target pixmap size :param padding: space between icon edge and color ramp +:param direction: direction to render pixmap (since QGIS 3.18) +:param flipDirection: set to ``True`` to flip the direction of the ramp. For horizontal ``directions``, ramps will be + rendered left to right by default. For vertical ``directions``, ramps will be rendered top to bottom by default. Setting + this flag to ``True`` will reverse these default directions. +:param drawTransparentBackground: set to ``False`` to disable the checkerboard effect drawn below transparent colors in the ramp .. seealso:: :py:func:`colorRampPreviewIcon` %End diff --git a/src/core/symbology/qgssymbollayerutils.cpp b/src/core/symbology/qgssymbollayerutils.cpp index 36aec7b6b0f0..9305854fe7e3 100644 --- a/src/core/symbology/qgssymbollayerutils.cpp +++ b/src/core/symbology/qgssymbollayerutils.cpp @@ -874,7 +874,7 @@ QIcon QgsSymbolLayerUtils::colorRampPreviewIcon( QgsColorRamp *ramp, QSize size, return QIcon( colorRampPreviewPixmap( ramp, size, padding ) ); } -QPixmap QgsSymbolLayerUtils::colorRampPreviewPixmap( QgsColorRamp *ramp, QSize size, int padding ) +QPixmap QgsSymbolLayerUtils::colorRampPreviewPixmap( QgsColorRamp *ramp, QSize size, int padding, Qt::Orientation direction, bool flipDirection, bool drawTransparentBackground ) { QPixmap pixmap( size ); pixmap.fill( Qt::transparent ); @@ -883,16 +883,38 @@ QPixmap QgsSymbolLayerUtils::colorRampPreviewPixmap( QgsColorRamp *ramp, QSize s painter.begin( &pixmap ); //draw stippled background, for transparent images - drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) ); + if ( drawTransparentBackground ) + drawStippledBackground( &painter, QRect( padding, padding, size.width() - padding * 2, size.height() - padding * 2 ) ); // antialiasing makes the colors duller, and no point in antialiasing a color ramp // painter.setRenderHint( QPainter::Antialiasing ); - for ( int i = 0; i < size.width(); i++ ) + switch ( direction ) { - QPen pen( ramp->color( static_cast< double >( i ) / size.width() ) ); - painter.setPen( pen ); - painter.drawLine( i, 0 + padding, i, size.height() - 1 - padding ); + case Qt::Horizontal: + { + for ( int i = 0; i < size.width(); i++ ) + { + QPen pen( ramp->color( static_cast< double >( i ) / size.width() ) ); + painter.setPen( pen ); + const int x = flipDirection ? size.width() - i - 1 : i; + painter.drawLine( x, 0 + padding, x, size.height() - 1 - padding ); + } + break; + } + + case Qt::Vertical: + { + for ( int i = 0; i < size.height(); i++ ) + { + QPen pen( ramp->color( static_cast< double >( i ) / size.height() ) ); + painter.setPen( pen ); + const int y = flipDirection ? size.height() - i - 1 : i; + painter.drawLine( 0 + padding, y, size.width() - 1 - padding, y ); + } + break; + } } + painter.end(); return pixmap; } diff --git a/src/core/symbology/qgssymbollayerutils.h b/src/core/symbology/qgssymbollayerutils.h index 98598ebc22a0..8665b6231d0b 100644 --- a/src/core/symbology/qgssymbollayerutils.h +++ b/src/core/symbology/qgssymbollayerutils.h @@ -273,9 +273,15 @@ class CORE_EXPORT QgsSymbolLayerUtils * \param ramp color ramp * \param size target pixmap size * \param padding space between icon edge and color ramp + * \param direction direction to render pixmap (since QGIS 3.18) + * \param flipDirection set to TRUE to flip the direction of the ramp. For horizontal \a directions, ramps will be + * rendered left to right by default. For vertical \a directions, ramps will be rendered top to bottom by default. Setting + * this flag to TRUE will reverse these default directions. + * \param drawTransparentBackground set to FALSE to disable the checkerboard effect drawn below transparent colors in the ramp * \see colorRampPreviewIcon() */ - static QPixmap colorRampPreviewPixmap( QgsColorRamp *ramp, QSize size, int padding = 0 ); + static QPixmap colorRampPreviewPixmap( QgsColorRamp *ramp, QSize size, int padding = 0, Qt::Orientation direction = Qt::Horizontal, + bool flipDirection = false, bool drawTransparentBackground = true ); static void drawStippledBackground( QPainter *painter, QRect rect ); diff --git a/tests/src/python/test_qgssymbollayerutils.py b/tests/src/python/test_qgssymbollayerutils.py index 5aa42d7ab31f..fb8ef086cd9e 100644 --- a/tests/src/python/test_qgssymbollayerutils.py +++ b/tests/src/python/test_qgssymbollayerutils.py @@ -11,20 +11,26 @@ __copyright__ = 'Copyright 2016, The QGIS Project' import qgis # NOQA - -from qgis.core import (QgsSymbolLayerUtils, - QgsMarkerSymbol, - QgsArrowSymbolLayer, - QgsUnitTypes) +from qgis.PyQt.QtCore import ( + QSizeF, + QPointF, + QMimeData, + QDir, + QSize, + Qt +) from qgis.PyQt.QtGui import ( QColor, QPolygonF, QImage ) -from qgis.PyQt.QtCore import ( - QSizeF, - QPointF, - QMimeData +from qgis.core import ( + QgsSymbolLayerUtils, + QgsMarkerSymbol, + QgsArrowSymbolLayer, + QgsUnitTypes, + QgsRenderChecker, + QgsGradientColorRamp ) from qgis.testing import unittest, start_app @@ -33,6 +39,16 @@ class PyQgsSymbolLayerUtils(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.report = "

Python QgsPointCloudRgbRenderer Tests

\n" + + @classmethod + def tearDownClass(cls): + report_file_path = "%s/qgistest.html" % QDir.tempPath() + with open(report_file_path, 'a') as report_file: + report_file.write(cls.report) + def testEncodeDecodeSize(self): s = QSizeF() string = QgsSymbolLayerUtils.encodeSize(s) @@ -408,6 +424,55 @@ def testColorFromMimeData(self): color, has_alpha = QgsSymbolLayerUtils.colorFromMimeData(data) self.assertFalse(color.isValid()) + def testPreviewColorRampHorizontal(self): + r = QgsGradientColorRamp(QColor(200, 0, 0, 200), QColor(0, 200, 0, 255)) + + pix = QgsSymbolLayerUtils.colorRampPreviewPixmap(r, QSize(200, 100)) + img = QImage(pix) + self.assertTrue(self.imageCheck('color_ramp_horizontal', 'color_ramp_horizontal', img)) + + def testPreviewColorRampHorizontalNoCheckboard(self): + r = QgsGradientColorRamp(QColor(200, 0, 0, 200), QColor(0, 200, 0, 255)) + + pix = QgsSymbolLayerUtils.colorRampPreviewPixmap(r, QSize(200, 100), drawTransparentBackground=False) + img = QImage(pix) + self.assertTrue(self.imageCheck('color_ramp_no_check', 'color_ramp_no_check', img)) + + def testPreviewColorRampHorizontalFlipped(self): + r = QgsGradientColorRamp(QColor(200, 0, 0, 200), QColor(0, 200, 0, 255)) + + pix = QgsSymbolLayerUtils.colorRampPreviewPixmap(r, QSize(200, 100), flipDirection=True) + img = QImage(pix) + self.assertTrue(self.imageCheck('color_ramp_horizontal_flipped', 'color_ramp_horizontal_flipped', img)) + + def testPreviewColorRampVertical(self): + r = QgsGradientColorRamp(QColor(200, 0, 0, 200), QColor(0, 200, 0, 255)) + + pix = QgsSymbolLayerUtils.colorRampPreviewPixmap(r, QSize(100, 200), direction=Qt.Vertical) + img = QImage(pix) + self.assertTrue(self.imageCheck('color_ramp_vertical', 'color_ramp_vertical', img)) + + def testPreviewColorRampVerticalFlipped(self): + r = QgsGradientColorRamp(QColor(200, 0, 0, 200), QColor(0, 200, 0, 255)) + + pix = QgsSymbolLayerUtils.colorRampPreviewPixmap(r, QSize(100, 200), direction=Qt.Vertical, flipDirection=True) + img = QImage(pix) + self.assertTrue(self.imageCheck('color_ramp_vertical_flipped', 'color_ramp_vertical_flipped', img)) + + def imageCheck(self, name, reference_image, image): + self.report += "

Render {}

\n".format(name) + temp_dir = QDir.tempPath() + '/' + file_name = temp_dir + name + ".png" + image.save(file_name, "PNG") + checker = QgsRenderChecker() + checker.setControlPathPrefix("symbol_layer_utils") + checker.setControlName("expected_" + reference_image) + checker.setRenderedImage(file_name) + checker.setColorTolerance(2) + result = checker.compareImages(name, 20) + PyQgsSymbolLayerUtils.report += checker.report() + return result + if __name__ == '__main__': unittest.main() diff --git a/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_horizontal/expected_color_ramp_horizontal.png b/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_horizontal/expected_color_ramp_horizontal.png new file mode 100644 index 000000000000..e39858e9d095 Binary files /dev/null and b/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_horizontal/expected_color_ramp_horizontal.png differ diff --git a/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_horizontal_flipped/expected_color_ramp_horizontal_flipped.png b/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_horizontal_flipped/expected_color_ramp_horizontal_flipped.png new file mode 100644 index 000000000000..5013f679e7b0 Binary files /dev/null and b/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_horizontal_flipped/expected_color_ramp_horizontal_flipped.png differ diff --git a/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_no_check/expected_color_ramp_no_check.png b/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_no_check/expected_color_ramp_no_check.png new file mode 100644 index 000000000000..cbab5ba694de Binary files /dev/null and b/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_no_check/expected_color_ramp_no_check.png differ diff --git a/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_vertical/expected_color_ramp_vertical.png b/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_vertical/expected_color_ramp_vertical.png new file mode 100644 index 000000000000..f1f0f2bd9c78 Binary files /dev/null and b/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_vertical/expected_color_ramp_vertical.png differ diff --git a/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_vertical_flipped/expected_color_ramp_vertical_flipped.png b/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_vertical_flipped/expected_color_ramp_vertical_flipped.png new file mode 100644 index 000000000000..e72f80a1e8a5 Binary files /dev/null and b/tests/testdata/control_images/symbol_layer_utils/expected_color_ramp_vertical_flipped/expected_color_ramp_vertical_flipped.png differ