And including this in loadModels() is a fairly safe way to remove the copied model files from previous versions:
modelsFiles = glob.glob(os.path.join(self.modelsPath, '*.model3')) for modelFileName in modelsFiles: destFilename = os.path.join(ModelerUtils.defaultModelsFolder(), os.path.basename(modelFileName)) try: if os.path.exists(destFilename): move(destFilename, destFilename + '.bak') except Exception as ex: QgsMessageLog.logMessage(self.tr('Failed to rename existing model: {} - {}'.format(destFilename, str(ex))), self.messageTag, Qgis.Warning) continue It does mean that if someone happens to have a model with the same name as one provided by the plugin, it will disappear, but at least it will still be there as a *.bak file, rather than just being overwritten. On Tue, 16 May 2023 at 13:19, Alister Hood <alister.h...@gmail.com> wrote: > 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.h...@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() >> >
_______________________________________________ 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