Il 23/01/2021 15:35, JD L ha scritto:
Hi Giulio,
add the flags methods to tell your algorithm is not thread-safe. From
the documentation :
https://docs.qgis.org/3.16/en/docs/user_manual/processing/scripts.html#flags
<https://docs.qgis.org/3.16/en/docs/user_manual/processing/scripts.html#flags>
If your algorithm is regularly crashing, you are probably using API
calls which are not safe to do in a background thread. Try returning
the *QgsProcessingAlgorithm.FlagNoThreading flag from your algorithm’s
flags() method* to force Processing to run your algorithm in the main
thread instead.
I just tested and it works.
Regards,
Le ven. 22 janv. 2021 à 14:56, Giulio Fattori <giulio.fatt...@tin.it
<mailto:giulio.fatt...@tin.it>> a écrit :
Hello,
i'm developing a QGIS plugin algorithm that composes a print layout.
The attached code works but the map window appears in the composer
with the word "Rendering map".
and I get these messages:
WARNING QObject::connect: Cannot queue arguments of type
'QItemSelection'
(Make sure 'QItemSelection' is registered using
qRegisterMetaType().)
WARNING QObject::connect: Cannot queue arguments of type
'QItemSelection'
(Make sure 'QItemSelection' is registered using
qRegisterMetaType().)
WARNING QObject::connect: Cannot queue arguments of type
'QItemSelection'
(Make sure 'QItemSelection' is registered using
qRegisterMetaType().)
WARNING QObject::startTimer: Timers cannot be started from
another thread
CRITICAL Qt : QObject::killTimer: Timers cannot be stopped from
another thread
CRITICAL Qt : QObject::startTimer: Timers cannot be started
from another thread
CRITICAL Qt : QObject::killTimer: Timers cannot be stopped from
another thread
CRITICAL Qt : QObject::startTimer: Timers can only be used with
threads started with QThread
Only after saving and reopening QGIS do I get the correct result
in the composer.
What is missing to make it work properly?
Can someone help me?
_______________________________________________
QGIS-Developer mailing list
QGIS-Developer@lists.osgeo.org <mailto:QGIS-Developer@lists.osgeo.org>
List info: https://lists.osgeo.org/mailman/listinfo/qgis-developer
<https://lists.osgeo.org/mailman/listinfo/qgis-developer>
Unsubscribe:
https://lists.osgeo.org/mailman/listinfo/qgis-developer
<https://lists.osgeo.org/mailman/listinfo/qgis-developer>
Hi Daniel,
thanks for your kind response, could you send me the code correct as you
say?
Regards
# -*- coding: utf-8 -*-
"""
***************************************************************************
* Korto19 - last modified 17.01.2020/2021 19.01
* Put a map to composer
* 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 PyQt5.QtGui import QFont
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsProcessing,
QgsProject,
QgsPrintLayout,
QgsLayoutItemPage,
QgsLayoutItemMap,
QgsLayoutPoint,
QgsUnitTypes,
QgsLayoutSize,
QgsRectangle,
QgsLayoutItemLabel,
QgsProcessingAlgorithm,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink)
from qgis import processing
from qgis.utils import iface
import math
class TestMapProcessingAlgorithm(QgsProcessingAlgorithm):
"""
"""
# Constants used to refer to parameters and outputs. They will be
# used when calling the algorithm from another algorithm, or when
# calling from the QGIS console.
INPUT = 'INPUT'
OUTPUT = 'OUTPUT'
def tr(self, string):
"""
Returns a translatable string with the self.tr() function.
"""
return QCoreApplication.translate('Processing', string)
def createInstance(self):
return TestMapProcessingAlgorithm()
def name(self):
"""
Returns the algorithm name, used for identifying the algorithm. This
string should be fixed for the algorithm, and must not be localised.
The name should be unique within each provider. Names should contain
lowercase alphanumeric characters only and no spaces or other
formatting characters.
"""
return 'Test Map'
def displayName(self):
"""
Returns the translated algorithm name, which should be used for any
user-visible display of the algorithm name.
"""
return self.tr('Test Map')
def group(self):
"""
Returns the name of the group this algorithm belongs to. This string
should be localised.
"""
return self.tr('Test Map')
def groupId(self):
"""
Returns the unique ID of the group this algorithm belongs to. This
string should be fixed for the algorithm, and must not be localised.
The group id should be unique within each provider. Group id should
contain lowercase alphanumeric characters only and no spaces or other
formatting characters.
"""
return 'Test Map'
def shortHelpString(self):
"""
Returns a localised short helper string for the algorithm. This string
should provide a basic description about what the algorithm does and the
parameters and outputs associated with it..
"""
return self.tr("Test map composition")
def initAlgorithm(self, config=None):
"""
Here we define the inputs and output of the algorithm, along
with some other properties.
"""
# We add the input vector features source. It can have any kind of
geometry.
self.addParameter(
QgsProcessingParameterFeatureSource(
self.INPUT,
self.tr('Input layer'),
[QgsProcessing.TypeVectorAnyGeometry]
)
)
def processAlgorithm(self, parameters, context, feedback):
"""
Here is where the processing itself takes place.
"""
source = self.parameterAsLayer(
parameters,
self.INPUT,
context
)
#Inizialize references
project = QgsProject.instance() #gets a reference to the
project instance
manager = project.layoutManager() #gets a reference to the
layout manager
root = project.layerTreeRoot() #get reference to tree root
#set pagesize, layout name and scale (fit or numeric)
pagesize = 'A3'
layoutName = "CompoMap_" + pagesize + ' ' + source.name()
map_scala = 'fit'
#If exist remove layout
layouts_list = manager.printLayouts()
for layout in layouts_list:
if layout.name() == layoutName:
manager.removeLayout(layout)
#create layout
layout = QgsPrintLayout(project)
layout.initializeDefaults()
layout.setName(layoutName)
layout.pageCollection().page(0).setPageSize(pagesize,
QgsLayoutItemPage.Orientation.Portrait)
manager.addLayout(layout)
#calculates the size of the map minus the edges
xm = (layout.pageCollection().page(0).pageSize().width()-10)
ym = (layout.pageCollection().page(0).pageSize().height()-10)
#set layer active and fit map
iface.setActiveLayer(source)
root.findLayer(source.id()).setItemVisibilityChecked(True)
canvas = iface.mapCanvas()
canvas.setExtent(source.extent())
canvas.refresh()
#add map to layout and set position
map = QgsLayoutItemMap(layout)
map.setRect(20, 20, 20, 20)
map.setExtent(canvas.extent())
map.setId(source.name())
map.attemptMove(QgsLayoutPoint(5, 5, QgsUnitTypes.LayoutMillimeters))
map.attemptResize(QgsLayoutSize(xm, ym, QgsUnitTypes.LayoutMillimeters))
#override scale Test_map
if map_scala == 'fit':
h_map_scala =
math.ceil(source.extent().height()/map.rect().height())*1000
w_map_scala = math.ceil(source.extent().width()
/map.rect().width())*1000
map_scala = max(h_map_scala,w_map_scala)
extent = map.extent()
center = extent.center()
newwidth = extent.width() / map.scale() * map_scala
newheight = extent.height() / map.scale() * map_scala
x1 = center.x() - 0.5 * newwidth
y1 = center.y() - 0.5 * newheight
x2 = center.x() + 0.5 * newwidth
y2 = center.y() + 0.5 * newheight
map.setExtent(QgsRectangle(x1, y1, x2, y2))
#add map to layout
layout.addLayoutItem(map)
#select and lock map set
map.setLayers([source])
map.setKeepLayerSet(True)
map.setKeepLayerStyles(True)
map.setBackgroundEnabled(False)
#Add title
title = QgsLayoutItemLabel(layout)
title.setText(source.name())
title.setFont(QFont("Arial Black", 12))
title.adjustSizeToText()
title.attemptMove(QgsLayoutPoint(5, 5, QgsUnitTypes.LayoutMillimeters))
layout.addLayoutItem(title)
feedback.pushInfo("WOW The plugin is working as it should, created " +
layoutName)
return {self.OUTPUT: None}
_______________________________________________
QGIS-Developer mailing list
QGIS-Developer@lists.osgeo.org
List info: https://lists.osgeo.org/mailman/listinfo/qgis-developer
Unsubscribe: https://lists.osgeo.org/mailman/listinfo/qgis-developer