From f3f5a9f1c34f7ce403d229e4a813ed2df7ac92c0 Mon Sep 17 00:00:00 2001 From: ghtmtt Date: Wed, 8 Jun 2022 16:49:58 +0200 Subject: [PATCH 1/3] new custom function to get the colors from categories used --- DataPlotly/core/plot_expressions.py | 53 +++++++++++++++++++++++++++++ DataPlotly/data_plotly.py | 11 +++++- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 DataPlotly/core/plot_expressions.py diff --git a/DataPlotly/core/plot_expressions.py b/DataPlotly/core/plot_expressions.py new file mode 100644 index 00000000..55d7e133 --- /dev/null +++ b/DataPlotly/core/plot_expressions.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +""" +/*************************************************************************** + DataPlotly + A QGIS plugin + D3 Plots for QGIS + ------------------- + begin : 2022-06-08 + git sha : $Format:%H$ + copyright : (C) 2020 by matteo ghetta + email : matteo.ghetta@faunalia.it + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +""" + +from qgis.utils import qgsfunction, iface + +@qgsfunction(args='auto', group='DataPlotly') +def get_categories_colors(field, feature, parent): + """ + Retrieve the color of each category as html code. You can use this function + to set the plot items (pie slices, bars, points, etc) to the same color + of the feature visible in the map. +

Syntax

+

+ get_categories_colors(categorization_field) +

+

Arguments

+

categorization_field: the name of the field used in the categorization

+

Example

+

+ get_categories_colors("CONTINENT") -> '#da1ddd' +

+ """ + + layer = iface.activeLayer() + renderer = layer.renderer() + + if layer.renderer().type() == "categorizedSymbol": + for category in renderer.categories(): + if field == category.value(): + category_color = category.symbol().color().name() + break + + return category_color \ No newline at end of file diff --git a/DataPlotly/data_plotly.py b/DataPlotly/data_plotly.py index 97e0e523..ea7c94a0 100644 --- a/DataPlotly/data_plotly.py +++ b/DataPlotly/data_plotly.py @@ -25,7 +25,7 @@ from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication, Qt, QUrl from qgis.PyQt.QtGui import QDesktopServices from qgis.PyQt.QtWidgets import QAction -from qgis.core import Qgis, QgsApplication +from qgis.core import Qgis, QgsApplication, QgsExpression from qgis.gui import QgsGui # Import the code for the dialog @@ -39,6 +39,9 @@ from DataPlotly.layouts.plot_layout_item import PlotLayoutItemMetadata from DataPlotly.gui.layout_item_gui import PlotLayoutItemGuiMetadata +# import custom expressions +from .core.plot_expressions import get_categories_colors + class DataPlotly: # pylint: disable=too-many-instance-attributes """QGIS Plugin Implementation.""" @@ -132,6 +135,9 @@ def initGui(self): self.iface.pluginHelpMenu().addAction(self.help_action) self.help_action.triggered.connect(self.open_help) + # register the function + QgsExpression.registerFunction(get_categories_colors) + def initProcessing(self): """Create the Processing provider""" QgsApplication.processingRegistry().addProvider(self.provider) @@ -151,6 +157,9 @@ def unload(self): # Remove processing provider QgsApplication.processingRegistry().removeProvider(self.provider) + # unregister the function + QgsExpression.unregisterFunction('get_categories_colors') + @staticmethod def open_help(): """ Open the online help. """ From e47707274661b2fbf67eed2b0c88021a39c585e3 Mon Sep 17 00:00:00 2001 From: ghtmtt Date: Mon, 13 Jun 2022 17:00:07 +0200 Subject: [PATCH 2/3] fix selection for scatterplot --- DataPlotly/core/plot_factory.py | 2 ++ DataPlotly/gui/plot_settings_widget.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/DataPlotly/core/plot_factory.py b/DataPlotly/core/plot_factory.py index 0c7e7735..95aa6a46 100644 --- a/DataPlotly/core/plot_factory.py +++ b/DataPlotly/core/plot_factory.py @@ -511,6 +511,8 @@ def js_callback(_): if(data.points[i].data.type == 'scatter'){ dd["uid"] = data.points[i].data.uid dd["type"] = data.points[i].data.type + dd["field"] = data.points[i].data.customdata[0] + dd["id"] = data.points[i].x data.points.forEach(function(pt){ dd["fid"] = pt.id diff --git a/DataPlotly/gui/plot_settings_widget.py b/DataPlotly/gui/plot_settings_widget.py index 7d5780cf..3fea9b04 100644 --- a/DataPlotly/gui/plot_settings_widget.py +++ b/DataPlotly/gui/plot_settings_widget.py @@ -483,7 +483,11 @@ def getJSmessage(self, status): # if a clicking event is performed depending on the plot type elif dic["mode"] == 'clicking': if dic['type'] == 'scatter': - self.layer_combo.currentLayer().selectByIds([dic['fidd']]) + exp = """ {} = '{}' """.format(dic['field'], dic['id']) + # set the iterator with the expression as filter in feature request + request = QgsFeatureRequest().setFilterExpression(exp) + it = self.layer_combo.currentLayer().getFeatures(request) + self.layer_combo.currentLayer().selectByIds([f.id() for f in it]) elif dic["type"] == 'pie': exp = """ "{}" = '{}' """.format(dic['field'], dic['label']) # set the iterator with the expression as filter in feature request From 22bd390f90567f65ddd5f8bfcca5115ea9f94ab6 Mon Sep 17 00:00:00 2001 From: ghtmtt Date: Mon, 13 Jun 2022 18:05:13 +0200 Subject: [PATCH 3/3] clean js --- DataPlotly/core/plot_factory.py | 6 ++---- DataPlotly/gui/plot_settings_widget.py | 9 +++++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/DataPlotly/core/plot_factory.py b/DataPlotly/core/plot_factory.py index 95aa6a46..59be929d 100644 --- a/DataPlotly/core/plot_factory.py +++ b/DataPlotly/core/plot_factory.py @@ -485,13 +485,11 @@ def js_callback(_): dds["type"] = data.points[0].data.type featureIds = []; - featureIdsTernary = []; data.points.forEach(function(pt){ - featureIds.push(parseInt(pt.id)) - featureIdsTernary.push(parseInt(pt.pointNumber)) + featureIds.push(pt.x) dds["id"] = featureIds - dds["tid"] = featureIdsTernary + dds["field"] = pt.data.customdata[0] }) //console.log(dds) window.status = JSON.stringify(dds) diff --git a/DataPlotly/gui/plot_settings_widget.py b/DataPlotly/gui/plot_settings_widget.py index 3fea9b04..b11095f4 100644 --- a/DataPlotly/gui/plot_settings_widget.py +++ b/DataPlotly/gui/plot_settings_widget.py @@ -475,10 +475,15 @@ def getJSmessage(self, status): # if a selection event is performed if dic['mode'] == 'selection': + exp = """ {} IN {} """.format(dic['field'], dic['id']) + exp = exp.replace('[', '(').replace(']', ')') + # set the iterator with the expression as filter in feature request + request = QgsFeatureRequest().setFilterExpression(exp) + it = self.layer_combo.currentLayer().getFeatures(request) if dic['type'] == 'scatter': - self.layer_combo.currentLayer().selectByIds(dic['id']) + self.layer_combo.currentLayer().selectByIds([f.id() for f in it]) else: - self.layer_combo.currentLayer().selectByIds(dic['tid']) + self.layer_combo.currentLayer().selectByIds([f.id() for f in it]) # if a clicking event is performed depending on the plot type elif dic["mode"] == 'clicking':