[QGIS-Developer] Best practice for plugins including processing models
Alister Hood
alister.hood at gmail.com
Mon May 15 18:19:50 PDT 2023
Further to this, I am now using the following code to load the models
directly from the plugin folder, rather than copying them into
%AppData%\Roaming\QGIS\QGIS3\profiles\default\processing\models
def loadModels(self):
modelsFolders=ModelerUtils.modelsFolders()
if self.modelsPath not in modelsFolders:
modelsFolders.append(self.modelsPath)
ProcessingConfig.setSettingValue(ModelerUtils.MODELS_FOLDER,
';'.join(modelsFolders))
QgsApplication.processingRegistry().providerById('model').refreshAlgorithms()
def unloadModels(self):
modelsFolders=ModelerUtils.modelsFolders()
if self.modelsPath in modelsFolders:
modelsFolders.remove(self.modelsPath)
ProcessingConfig.setSettingValue(ModelerUtils.MODELS_FOLDER,
';'.join(modelsFolders))
QgsApplication.processingRegistry().providerById('model').refreshAlgorithms()
On Fri, 28 Apr 2023 at 15:07, Alister Hood <alister.hood at gmail.com> wrote:
> Hi, I maintain an in-house plugin for our team of civil engineers, who
> apart from myself are not very advanced GIS users.
> It does things like set useful defaults and install a set of useful
> plugins. It also includes some processing models, which are loaded with
> the code below, which seems to be the conventional way models are loaded in
> publicly available plugins which ship processing models. This code copies
> the model files included in the plugin to the default folder for processing
> models - somewhere like
> %AppData%\Roaming\QGIS\QGIS3\profiles\default\processing\models
>
> One of my colleagues did some QGIS training and created a processing
> model, which coincidentally had the same filename as a model I created on
> the same day, so his model got overwritten when my plugin was updated.
> This is not a problem for us as we are a small team and can be careful what
> we do going forward. But it highlights that the way plugin authors are
> loading model files is what seems to me to be pretty poor practice, for two
> reasons.
>
> Firstly models are available in qgis even when the plugin is unloaded or
> uninstalled, which is probably not desirable.
> It is trivial to implement an unloadModels function to rectify this, and I
> have done so in my in-house plugin. I'm wondering - should plugin authors
> be encouraged to do the same?
>
> Secondly, loading the plugin will silently overwrite any existing models
> with the same filename, as occurred here. Plugins generally contain models
> with fairly special filenames, so hopefully this is unlikely to occur,
> unless:
> - someone produces a plugin that is a fork of another one, or
> - someone ships a plugin with a model that is previously publicly
> available somewhere else, or that was created by following an online
> tutorial, or
> - a user edits a model provided by a plugin.
> In any case, would it be a good idea to encourage plugin authors to load
> models another way, without copying them into
> %AppData%\Roaming\QGIS\QGIS3\profiles\default\processing\models?
> I realise that to change an existing plugin there is the added
> complication of what to do when updating from an old version - the only
> safeish way I can think of to automatically clean up obsolete model files
> would be to check for them and then use a checksum to verify whether they
> should be deleted.
> For what it's worth, I note that when a user tries to manually "add model
> to toolbox", QGIS refuses if there is an existing model with the same
> filename.
>
> Thanks.
>
>
> def loadModels(self):
> '''Register models present in models folder of the plugin.'''
> try:
> iface.initializationCompleted.disconnect(self.loadModels)
> except:
> pass
>
> #QgsMessageLog.logMessage(self.tr('testing'),
> self.messageTag, Qgis.Warning)
> modelsFiles = glob.glob(os.path.join(self.modelsPath,
> '*.model3'))
>
> for modelFileName in modelsFiles:
> alg = QgsProcessingModelAlgorithm()
> if not alg.fromFile(modelFileName):
> QgsMessageLog.logMessage(self.tr('Not well formed
> model: {}'.format(modelFileName)), self.messageTag, Qgis.Warning)
> continue
>
> destFilename =
> os.path.join(ModelerUtils.modelsFolders()[0],
> os.path.basename(modelFileName))
> try:
> if os.path.exists(destFilename):
> os.remove(destFilename)
>
> if isWindows():
> copyfile(modelFileName, destFilename)
> else:
> os.symlink(modelFileName, destFilename)
> except Exception as ex:
> QgsMessageLog.logMessage(self.tr('Failed to install
> model: {} - {}'.format(modelFileName, str(ex))), self.messageTag,
> Qgis.Warning)
> continue
>
>
> QgsApplication.processingRegistry().providerById('model').refreshAlgorithms()
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/qgis-developer/attachments/20230516/54cd78ae/attachment.htm>
More information about the QGIS-Developer
mailing list