Skip to content

Commit

Permalink
take into account group opacity for printing
Browse files Browse the repository at this point in the history
  • Loading branch information
mind84 authored and github-actions[bot] committed Mar 6, 2025
1 parent cbac3e1 commit 4e874cc
Show file tree
Hide file tree
Showing 8 changed files with 2,807 additions and 3 deletions.
6 changes: 3 additions & 3 deletions assets/src/components/Print.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ export default class Print extends HTMLElement {

// Add visible layers in defined order
const orderedVisibleLayers = {};
mainLizmap.state.rootMapGroup.findMapLayers().forEach(layer => {
mainLizmap.state.rootMapGroup.findExplodedMapLayers().forEach(layer => {
if (layer.visibility) {
orderedVisibleLayers[layer.layerOrder] = layer;
}
Expand All @@ -267,9 +267,9 @@ export default class Print extends HTMLElement {

// Handle qgis layer opacity otherwise client value override it
if (layer.layerConfig?.opacity) {
opacityLayers.push(parseInt(255 * layer.opacity * layer.layerConfig.opacity));
opacityLayers.push(parseInt(255 * layer.calculateTotalOpacity() * layer.layerConfig.opacity));
} else {
opacityLayers.push(parseInt(255 * layer.opacity));
opacityLayers.push(parseInt(255 * layer.calculateTotalOpacity()));
}
if ('FILTERTOKEN' in layerWmsParams) {
filter.push(layerWmsParams['FILTERTOKEN']);
Expand Down
13 changes: 13 additions & 0 deletions assets/src/modules/state/Layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,19 @@ export class LayerItemState extends EventDispatcher {
}
return this._visibility;
}

/**
* Calculate total opacity by including also all parent groups opacity values
* @returns {number} the total opacity
*/
calculateTotalOpacity(){
let opacity = this.opacity;
if(this._parentGroup !== null){
opacity = opacity*this._parentGroup.calculateTotalOpacity();
}

return Math.round(opacity * 100) / 100;
}
}

/**
Expand Down
24 changes: 24 additions & 0 deletions assets/src/modules/state/MapLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,30 @@ export class MapGroupState extends MapItemState {
return layersCount;
}

/**
* Find all layers by exploding the layers within every "group as layer" groups
* @returns {LayerLayerState[]} The layer states of listed layers
*/
findExplodedMapLayers(){
let layers = [];
for(const item of this.getChildren()) {
if (item instanceof MapLayerState) {
const itemState = item.itemState;
if(itemState instanceof LayerGroupState && itemState.groupAsLayer){
//count the layers inside the group
layers = layers.concat(itemState.findLayers());
}
else if(itemState instanceof LayerLayerState){
layers.push(item.itemState);
}
} else if (item instanceof MapGroupState) {
layers = layers.concat(item.findExplodedMapLayers());
}
}

return layers;
}

/**
* Find layer items
* @returns {MapLayerState[]} The layer names of all map layers
Expand Down
83 changes: 83 additions & 0 deletions tests/end2end/playwright/pages/printpage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// @ts-check
import { expect } from '@playwright/test';
import { ProjectPage } from './project';

/**
* Playwright Page
* @typedef {import('@playwright/test').Page} Page
*/

/**
* Playwright Page
* @typedef {import('@playwright/test').Locator} Locator
*/

export class PrintPage extends ProjectPage {
// Metadata
/**
* The print panel
* @type {Locator}
*/
printPanel;

/**
* The print button on menu
* @type {Locator}
*/
printSwitcherButton;

/**
* The print scale combobox
* @type {Locator}
*/
printScale;

/**
* The launch print button on print panel
* @type {Locator}
*/
launchPrintButton;

/**
* Constructor for a QGIS project page
* @param {Page} page The playwright page
* @param {string} project The project name
* @param {string} repository The repository name, default to testsrepository
*/
constructor(page, project, repository = 'testsrepository') {
super(page, project, repository);

this.printPanel = page.locator('#print');
this.printSwitcherButton = page.locator('#button-print');
this.launchPrintButton = page.locator('#print-launch');
this.printScaleCombobox = page.locator('#print-scale');
}

/**
* openPrintPanel function
* opens the print mini-dock panel
*/
async openPrintPanel() {
await this.page.locator('#button-print').click();
}

/**
* setPrintScale function
* Set the print scale
* @param {string} scale The scale
*/
async setPrintScale(scale) {
await this.printScaleCombobox.selectOption(scale);
}

/**
* launchPrint function
* Launch print
*/
async launchPrint() {
// Launch print
await this.launchPrintButton.click();
// check message
await expect(this.page.locator('div.alert')).toHaveCount(1);
}
}
21 changes: 21 additions & 0 deletions tests/end2end/playwright/pages/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,27 @@ export class ProjectPage extends BasePage {
await this.page.locator('#attribute-layer-list-table').locator(`button[value=${layer}]`).click();
}

/**
* openLayerInfo function
* Open the info layer panel for the given layer
* @param {string} layer Name of the layer
*/
async openLayerInfo(layer) {
await this.page.getByTestId(layer).locator('.node').first().hover();
await this.page.getByTestId(layer).locator('.layer-actions').first().locator('i.icon-info-sign').click();
}

/**
* setLayerOpacity function
* Open the info layer panel for the given layer
* @param {string} layer Name of the layer
* @param {string} opacity Layer opacity, possible values '0','20','40','60','80','100'
*/
async setLayerOpacity(layer, opacity = '100') {
await this.openLayerInfo(layer);
await this.page.getByRole('link', { name: opacity }).click();
}

/**
* editingSubmitForm function
* Submit the form
Expand Down
148 changes: 148 additions & 0 deletions tests/end2end/playwright/print.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @ts-check

Check failure on line 1 in tests/end2end/playwright/print.spec.js

View workflow job for this annotation

GitHub Actions / E2E QGIS 3.40 PG 17-3 PHP 8.3

Failed Test: Print requests

Print requests: Error: Print requests → wrong length list : Got : 14 items With : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, simple_label To have: 15 items Debug : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, simple_label Debug count : 14 items expect(received).toHaveLength(expected) Expected length: 15 Received length: 14 Received array: ["SERVICE", "REQUEST", "VERSION", "FORMAT", "TRANSPARENT", "CRS", "DPI", "TEMPLATE", "map0:EXTENT", "map0:SCALE", …] - Error: Print requests → wrong length list : Got : 14 items With : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, simple_label To have: 15 items Debug : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, simple_label Debug count : 14 items expect(received).toHaveLength(expected) Expected length: 15 Received length: 14 Received array: ["SERVICE", "REQUEST", "VERSION", "FORMAT", "TRANSPARENT", "CRS", "DPI", "TEMPLATE", "map0:EXTENT", "map0:SCALE", …] at expectToHaveLengthCompare (/home/runner/work/lizmap-web-client/lizmap-web-client/tests/end2end/playwright/globals.js:238:7) at /home/runner/work/lizmap-web-client/lizmap-web-client/tests/end2end/playwright/print.spec.js:89:15

Check failure on line 1 in tests/end2end/playwright/print.spec.js

View workflow job for this annotation

GitHub Actions / E2E QGIS 3.40 PG 17-3 PHP 8.3

Failed Test: Print requests with selection

Print requests with selection: Error: Print requests with selection → wrong length list : Got : 15 items With : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, SELECTIONTOKEN, simple_label To have: 16 items Debug : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, simple_label, SELECTIONTOKEN Debug count : 15 items expect(received).toHaveLength(expected) Expected length: 16 Received length: 15 Received array: ["SERVICE", "REQUEST", "VERSION", "FORMAT", "TRANSPARENT", "CRS", "DPI", "TEMPLATE", "map0:EXTENT", "map0:SCALE", …] - Error: Print requests with selection → wrong length list : Got : 15 items With : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, SELECTIONTOKEN, simple_label To have: 16 items Debug : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, simple_label, SELECTIONTOKEN Debug count : 15 items expect(received).toHaveLength(expected) Expected length: 16 Received length: 15 Received array: ["SERVICE", "REQUEST", "VERSION", "FORMAT", "TRANSPARENT", "CRS", "DPI", "TEMPLATE", "map0:EXTENT", "map0:SCALE", …] at expectToHaveLengthCompare (/home/runner/work/lizmap-web-client/lizmap-web-client/tests/end2end/playwright/globals.js:238:7) at /home/runner/work/lizmap-web-client/lizmap-web-client/tests/end2end/playwright/print.spec.js:284:15

Check failure on line 1 in tests/end2end/playwright/print.spec.js

View workflow job for this annotation

GitHub Actions / E2E QGIS 3.40 PG 17-3 PHP 8.3

Failed Test: Print requests with filter

Print requests with filter: Error: Print requests with filter → wrong length list : Got : 15 items With : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, FILTERTOKEN, simple_label To have: 16 items Debug : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, simple_label, FILTERTOKEN Debug count : 15 items expect(received).toHaveLength(expected) Expected length: 16 Received length: 15 Received array: ["SERVICE", "REQUEST", "VERSION", "FORMAT", "TRANSPARENT", "CRS", "DPI", "TEMPLATE", "map0:EXTENT", "map0:SCALE", …] - Error: Print requests with filter → wrong length list : Got : 15 items With : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, FILTERTOKEN, simple_label To have: 16 items Debug : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, simple_label, FILTERTOKEN Debug count : 15 items expect(received).toHaveLength(expected) Expected length: 16 Received length: 15 Received array: ["SERVICE", "REQUEST", "VERSION", "FORMAT", "TRANSPARENT", "CRS", "DPI", "TEMPLATE", "map0:EXTENT", "map0:SCALE", …] at expectToHaveLengthCompare (/home/runner/work/lizmap-web-client/lizmap-web-client/tests/end2end/playwright/globals.js:238:7) at /home/runner/work/lizmap-web-client/lizmap-web-client/tests/end2end/playwright/print.spec.js:335:15

Check failure on line 1 in tests/end2end/playwright/print.spec.js

View workflow job for this annotation

GitHub Actions / E2E QGIS 3.40 PG 17-3 PHP 8.3

Failed Test: Print requests

Print requests: Error: Print requests 1 → wrong length list : Got : 14 items With : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, simple_label To have: 15 items Debug : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, simple_label Debug count : 14 items expect(received).toHaveLength(expected) Expected length: 15 Received length: 14 Received array: ["SERVICE", "REQUEST", "VERSION", "FORMAT", "TRANSPARENT", "CRS", "DPI", "TEMPLATE", "map0:EXTENT", "map0:SCALE", …] - Error: Print requests 1 → wrong length list : Got : 14 items With : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, simple_label To have: 15 items Debug : SERVICE, REQUEST, VERSION, FORMAT, TRANSPARENT, CRS, DPI, TEMPLATE, map0:EXTENT, map0:SCALE, map0:LAYERS, map0:STYLES, map0:OPACITIES, simple_label Debug count : 14 items expect(received).toHaveLength(expected) Expected length: 15 Received length: 14 Received array: ["SERVICE", "REQUEST", "VERSION", "FORMAT", "TRANSPARENT", "CRS", "DPI", "TEMPLATE", "map0:EXTENT", "map0:SCALE", …] at expectToHaveLengthCompare (/home/runner/work/lizmap-web-client/lizmap-web-client/tests/end2end/playwright/globals.js:238:7) at /home/runner/work/lizmap-web-client/lizmap-web-client/tests/end2end/playwright/print.spec.js:726:15
import { test, expect } from '@playwright/test';
import {PrintPage} from "./pages/printpage";
import { gotoMap, expectParametersToContain, getAuthStorageStatePath, expectToHaveLengthCompare } from './globals';

test.describe('Print', () => {
Expand Down Expand Up @@ -335,6 +336,153 @@ test.describe('Print', () => {
});
});

test.describe(
'Print opacities',
{
tag: ['@readonly'],
},() =>
{

test('Group as layer', async ({ page }) => {

const printPage = new PrintPage(page, 'group_as_layer_opacity');
await printPage.open();
await printPage.openPrintPanel();
await printPage.setPrintScale('50000');

// set opacity of `Group_opacity` (group as layer) layer to 60%
await printPage.setLayerOpacity('Group_opacity','60');

// opacity notes:
// the `raster` layer already has 80% opacity (inherited from QGIS project)
// setting the opacity to 60% on the `Group_opacity` causes:
// - `raster` layer to have a final total opacity of 48% (0.8*0.6)
// -> OPACITIES PARAM = 255*0.48 ~= 122
// - `single_wms_polygons` layer to have a final total opacity of 60% (1*0.6)
// -> OPACITIES PARAM = 255*0.6 = 153
// other layers have opacity 100% (255)

const mapLayers = [
'OpenStreetMap',
'raster',
'single_wms_polygons',
'single_wms_polygons_group_as_layer',
'single_wms_points_group',
]

const expectedParameters = {
'SERVICE': 'WMS',
'REQUEST': 'GetPrint',
'VERSION': '1.3.0',
'FORMAT': 'pdf',
'TRANSPARENT': 'true',
'CRS': 'EPSG:3857',
'DPI': '100',
'TEMPLATE': 'test',
'map0:EXTENT': /425189.\d+,5401412.\d+,439539.\d+,5411262.\d+/,
'map0:SCALE': '50000',
'map0:LAYERS': mapLayers.join(','),
'map0:STYLES': 'default,default,default,default,default',
'map0:OPACITIES': '255,122,153,255,255',
}
// Test `test` template
let getPrintPromise = page.waitForRequest(
request =>
request.method() === 'POST' &&
request.postData()?.includes('GetPrint') === true
);

// Launch print
await printPage.launchPrint();

// check request
let getPrintRequest = await getPrintPromise;

// check response parameters
let name = "Group as layer opacity requests";
let getPrintParams = await expectParametersToContain(
name, getPrintRequest.postData() ?? '', expectedParameters);

await expectToHaveLengthCompare(
name,
Array.from(getPrintParams.keys()),
13,
Object.keys(expectedParameters)
);
})

test('Layers in group with opacity', async ({ page }) => {
const printPage = new PrintPage(page, 'group_as_layer_opacity');
await printPage.open();
await printPage.openPrintPanel();
await printPage.setPrintScale('50000');

// set opacity of `Group_a` group opacity to 60%
await printPage.setLayerOpacity('Group_a','60');
// set opacity of `single_wms_points_group` (belonging to `Group_a`) layer to 40%
await printPage.setLayerOpacity('single_wms_points_group','40');
// set opacity of `single_wms_polygons_group_as_layer` (belonging to `Group_a`) layer to 80%
await printPage.setLayerOpacity('single_wms_polygons_group_as_layer','80');

// opacity notes:
// setting the opacity to 60% on `Group_a` causes:
// - `single_wms_points_group` layer to have a final total opacity of 24% (0.4*0.6)
// -> OPACITIES PARAM = 255*0.24 ~= 61
// - `single_wms_polygons_group_as_layer` layer to have a final total opacity of 48% (0.8*0.6)
// -> OPACITIES PARAM = 255*0.48 ~= 122
// other layers have opacity 100%, except for `raster` layer which has a 80% opacity by default,
// resulting in a OPACITIES PARAM = 255*0.8 = 204

const mapLayers = [
'OpenStreetMap',
'raster',
'single_wms_polygons',
'single_wms_polygons_group_as_layer',
'single_wms_points_group',
]

const expectedParameters = {
'SERVICE': 'WMS',
'REQUEST': 'GetPrint',
'VERSION': '1.3.0',
'FORMAT': 'pdf',
'TRANSPARENT': 'true',
'CRS': 'EPSG:3857',
'DPI': '100',
'TEMPLATE': 'test',
'map0:EXTENT': /425189.\d+,5401412.\d+,439539.\d+,5411262.\d+/,
'map0:SCALE': '50000',
'map0:LAYERS': mapLayers.join(','),
'map0:STYLES': 'default,default,default,default,default',
'map0:OPACITIES': '255,204,255,122,61',
}
// Test `test` template
let getPrintPromise = page.waitForRequest(
request =>
request.method() === 'POST' &&
request.postData()?.includes('GetPrint') === true
);

// Launch print
await printPage.launchPrint();

// check request
let getPrintRequest = await getPrintPromise;

// check response parameters
let name = "Layers in group with opacity request";
let getPrintParams = await expectParametersToContain(
name, getPrintRequest.postData() ?? '', expectedParameters);
await expectToHaveLengthCompare(
name,
Array.from(getPrintParams.keys()),
13,
Object.keys(expectedParameters)
);
})
}
);

test.describe('Print in popup', () => {
test.beforeEach(async ({ page }) => {
const url = '/index.php/view/map/?repository=testsrepository&project=print';
Expand Down
Loading

0 comments on commit 4e874cc

Please sign in to comment.