16.1. Struttura Plugin Python

per creare un plugin segui questi passi:

  1. Idea: hai un’idea di ciò che vuoi fare con il tuo nuovo plugin QGIS. Perché lo fai? Che problema vuoi risolvere? C’è già un altro plugin per quel problema?

  2. Crea i file: alcuni sono essenziazli (vedi Plugin file)

  3. Scrivi il codice: scriv il codice nei relativi file

  4. Test: Ricarica il tuo plugin per verificare che tutto è a posto

  5. Pubblica: pubblica il tuo plugin nel repository di QGIS ocrea il tuo repository personale come «magazzino» di «strumenti GIS» personali.

16.1.1. Scrivi un plugin

Dall’introduzione dei plugin Python in QGIS è apparso un numero di plugin. Il gruppo di QGIS mantiene un repository ufficiale di plugin Python. Puoi usarlo per saperne di più sulla programmazione con Pyqgis o vedere se stai duplicando uno sforzo già fatto.

16.1.1.1. Plugin file

Ecco la struttura della cartella del nostro plugin di esempio

PYTHON_PLUGINS_PATH/
  MyPlugin/
    __init__.py    --> *required*
    mainPlugin.py  --> *core code*
    metadata.txt   --> *required*
    resources.qrc  --> *likely useful*
    resources.py   --> *compiled version, likely useful*
    form.ui        --> *likely useful*
    form.py        --> *compiled version, likely useful*

Qual è il significato dei file:

  • __init__.py = il punto di partenza del plugin. Deve avere il metodo classFactory() e potrebbe avere qualsiasi altro codice di inizializzazione.

  • mainPlugin.py = il principale codice di lavoro del plugin. Contiene tutte le informazioni sulle azioni del plugin e il codice principale.

  • resources.qrc = il documento .xml creato da QT Designer. Contiene percorsi relativi alle risorse dei moduli.

  • resources.py = la traduzione in Python del file .qrc sopra descritto.

  • form.ui = la GUI creata da QT Designer.

  • form.py = la traduzione in Python del modulo.UI descritto sopra.

  • metadata.txt = contiene informazioni generali, versione, nome e alcuni altri metadati utilizzati dal sito web dei plugin e dell’infrastruttura del plugin.

Qui un modo per creare i file di base (scheletro) di un tipico plugin QGIS Python.

C’è un plugin QGIS chiamato Plugin Builder 3 che crea un modello di plugin per QGIS. Questa è l’opzione consigliata, in quanto produce plugin compatibili 3.x.

Avvertimento

Se pensi di caricare il plugin sul repository ufficiale Python Plugin devi verificare che il plugin segua alcune regole aggiuntive, richieste per la convalida Validazione del plugin

16.1.2. Contenuti del plugin

Qui puoi trovare informazioni ed esempi su cosa aggiungere in ciascuno dei file nella struttura del file sopra descritta.

16.1.2.1. Metadati del plugin

Innanzitutto, come creatore del plugin devi recuperare alcune informazioni di base sul plugin come il suo nome, la descrizione ecc. File metadata.txt è il posto giusto per mettere queste informazioni.

Nota

Tutti i metadati devono essere in codifica UTF-8.

Nome Metadati

Richiesto

Note

nome

Vero

Una breve stringa contenente il nome del plugin

qgisMinimumVersion

Vero

notazione della versione minima di QGIS

qgisMaximumVersion

Falso

notazione della versione massima

Descrizione

Vero

breve testo che descrive il plugin, non in HTML

su

Vero

testo più lungo che descrive il plugin nei dettagli, non è permesso HTML

versione

Vero

corta stringa con la notazione della versione

autore

Vero

nome dell’autore

email

Vero

email dell’autore, mostrato solo sul sito web per l’accesso degli utenti, ma visibile nel gestore plugin solo dopo l’installazione del plugin

cambiamenti

Falso

stringa, può essere multilinea, HTML non permesso

sperimentale

Falso

contrassegno, Vero o Falso - Vero se la versione è sperimentale

deprecato

Falso

contrassegno, Vero o Falso, si applica a tutto il plugin e non solo alla versione caricata

etichette

Falso

Elenco separato da virgola, gli spazi sono ammessi all’interno delle singole etichette

homepage

Falso

un URL valido per la pagina iniziale del tuo plugin

repository

Vero

un URL valido per il repository del codice sorgente

tracker

Falso

un URL valido per ticket e bug

icona

Falso

a file name or a relative path (relative to the base folder of the plugin’s compressed package) of a web friendly image (PNG, JPEG)

categoria

Falso

uno di Raster, Vector, Database e Web

plugin_dependencies

Falso

Elenco separato da virgole, simile a un PIP, di altri plugin da installare; utilizza i nomi dei plugin provenienti dal campo del nome dei rispettivi metadati.

server

Falso

contrassegno, Vero o Falso, determina se il plugin ha una interfaccia server

hasProcessingProvider

Falso

contrassegno, Vero o Falso, determina se il plugin prevede algoritmi processing

Per impostazione predefinita, i plugin sono inseriti nel menu Plugins (vedrai nella sezione successiva come aggiungere una voce di menu per il plugin) ma possono anche essere inseriti in Raster, Vector, Database e Web menus.

Una corrispondente voce di metadati: «categoria» esiste per specificare come può essere classificato il plugin. Questa voce dei metadati viene utilizzata per gli utenti e dice loro dove (in quale menu) è possibile trovare il plugin. I valori consentiti per «categoria» sono: vettoriali, raster, database o web. Ad esempio, se il tuo plugin sarà disponibile dal menu raster, aggiungilo a metadata.txt

category=Raster

Nota

Se`qgisMaximumVersion` è vuoto, sarà automaticamente impostata l’ultima versione più .99 quando caricato su Repository ufficiale dei plugin Python.

Un esempio di metadata.txt

; the next section is mandatory

[general]
name=HelloWorld
email=me@example.com
author=Just Me
qgisMinimumVersion=3.0
description=This is an example plugin for greeting the world.
    Multiline is allowed:
    lines starting with spaces belong to the same
    field, in this case to the "description" field.
    HTML formatting is not allowed.
about=This paragraph can contain a detailed description
    of the plugin. Multiline is allowed, HTML is not.
version=version 1.2
tracker=http://bugs.itopen.it
repository=http://www.itopen.it/repo
; end of mandatory metadata

; start of optional metadata
category=Raster
changelog=The changelog lists the plugin versions
    and their changes as in the example below:
    1.0 - First stable release
    0.9 - All features implemented
    0.8 - First testing release

; Tags are in comma separated value format, spaces are allowed within the
; tag name.
; Tags should be in English language. Please also check for existing tags and
; synonyms before creating a new one.
tags=wkt,raster,hello world

; these metadata can be empty, they will eventually become mandatory.
homepage=https://www.itopen.it
icon=icon.png

; experimental flag (applies to the single version)
experimental=True

; deprecated flag (applies to the whole plugin and not only to the uploaded version)
deprecated=False

; if empty, it will be automatically set to major version + .99
qgisMaximumVersion=3.99

; Since QGIS 3.8, a comma separated list of plugins to be installed
; (or upgraded) can be specified.
; The example below will try to install (or upgrade) "MyOtherPlugin" version 1.12
; and any version of "YetAnotherPlugin".
; Both "MyOtherPlugin" and "YetAnotherPlugin" names come from their own metadata's
; name field
plugin_dependencies=MyOtherPlugin==1.12,YetAnotherPlugin

16.1.2.2. __init__.py

Questo file è richiesto dal sistema di importazione di Python. Inoltre, QGIS richiede che questo file contenga una funzione classFactory(), che viene chiamata quando il plugin viene caricato in QGIS. Riceve un riferimento all’istanza di QgisInterface e deve restituire un oggetto della classe del tuo plugin dal file mainplugin.py — nel nostro caso si chiama TestPlugin (vedi sotto). Questo è come dovrebbe apparire __init__.py

def classFactory(iface):
  from .mainPlugin import TestPlugin
  return TestPlugin(iface)

# any other initialisation needed

16.1.2.3. mainPlugin.py

Qui è dove avviene e come appare la magia: (e.g. mainPlugin.py)

from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *

# initialize Qt resources from file resources.py
from . import resources

class TestPlugin:

  def __init__(self, iface):
    # save reference to the QGIS interface
    self.iface = iface

  def initGui(self):
    # create action that will start plugin configuration
    self.action = QAction(QIcon(":/plugins/testplug/icon.png"),
                          "Test plugin",
                          self.iface.mainWindow())
    self.action.setObjectName("testAction")
    self.action.setWhatsThis("Configuration for test plugin")
    self.action.setStatusTip("This is status tip")
    self.action.triggered.connect(self.run)

    # add toolbar button and menu item
    self.iface.addToolBarIcon(self.action)
    self.iface.addPluginToMenu("&Test plugins", self.action)

    # connect to signal renderComplete which is emitted when canvas
    # rendering is done
    self.iface.mapCanvas().renderComplete.connect(self.renderTest)

  def unload(self):
    # remove the plugin menu item and icon
    self.iface.removePluginMenu("&Test plugins", self.action)
    self.iface.removeToolBarIcon(self.action)

    # disconnect form signal of the canvas
    self.iface.mapCanvas().renderComplete.disconnect(self.renderTest)

  def run(self):
    # create and show a configuration dialog or something similar
    print("TestPlugin: run called!")

  def renderTest(self, painter):
    # use painter for drawing to map canvas
    print("TestPlugin: renderTest called!")

Le sole funzioni plugin che devono esistere nel file sorgente del plugin principale (e.g. mainPlugin.py) sono:

  • __init__ che da accesso all’interfaccia QGIS

  • initGui() chiamata se il plugin è caricato

  • unload() cchiamata quando il plugin è scaricato

Nell’esempio precedente, viene utilizzato addPluginToMenu(). Questo aggiungerà l’azione del menu corrispondente al menu Plugins. Esistono metodi alternativi per aggiungere l’azione a un menu diverso. Ecco un elenco di quei metodi:

Tutti hanno la stessa sintassi del metodo addPluginToMenu().

Si consiglia di aggiungere il tuo menu plugin con uno di questi metodi predefiniti per mantenere la coerenza nel modo in cui sono organizzati i plugin nel menu. Tuttavia, è possibile aggiungere il tuo gruppo di menu personalizzato direttamente alla barra dei menu, come dimostra il prossimo esempio:

def initGui(self):
    self.menu = QMenu(self.iface.mainWindow())
    self.menu.setObjectName("testMenu")
    self.menu.setTitle("MyMenu")

    self.action = QAction(QIcon(":/plugins/testplug/icon.png"),
                          "Test plugin",
                          self.iface.mainWindow())
    self.action.setObjectName("testAction")
    self.action.setWhatsThis("Configuration for test plugin")
    self.action.setStatusTip("This is status tip")
    self.action.triggered.connect(self.run)
    self.menu.addAction(self.action)

    menuBar = self.iface.mainWindow().menuBar()
    menuBar.insertMenu(self.iface.firstRightStandardMenu().menuAction(),
                       self.menu)

def unload(self):
    self.menu.deleteLater()

Non dimenticare di impostare QAction e QMenu objectName con un nome specifico per il tuo plugin in modo che possa essere personalizzato.

16.1.2.4. File delle risorse

Puoi vedere che in initGui() abbiamo usato un’icona dal file delle risorse (chiamato nel nostro caso resources.qrc)

<RCC>
  <qresource prefix="/plugins/testplug" >
     <file>icon.png</file>
  </qresource>
</RCC>

È bene usare un prefisso che non si scontra con altri plugin o parti di QGIS, altrimenti potresti ottenere risorse che non vuoi. Ora hai solo bisogno di generare un file Python che conterrà le risorse. È fatto con il comando pyrcc5:

pyrcc5 -o resources.py resources.qrc

Nota

In ambienti Windows, il tentativo di eseguire pyrcc5 dal prompt dei comandi o PowerShell probabilmente comporterà l’errore «Windows non può accedere al dispositivo, al percorso o al file specificato […].». La soluzione più semplice è probabilmente quella di utilizzare la shell OSGeo4W ma se puoi modificare la variabile ambiente del percorso o specifichi il percorso verso l’eseguibile dovresti essere in grado di trovarela in <Your QGIS Install Directory>\bin\pyrcc5.exe.

E questo è tutto … niente di complicato :)

Se hai fatto tutto correttamente, dovresti essere in grado di trovare e caricare il tuo plugin nel gestore plugin e vedere un messaggio in console se è selezionata l’icona della barra degli strumenti o la voce di menu appropriata.

Se lavori su un plugin reale è saggio scrivere il plugin in un’altra directory (funzionante) e creare un makefile che genererà file UI + file risorse e installa il plugin nella tuainstallazione QGIS.

16.1.3. Documentazione

Puoi scrivere la documentazione per il plugin come file HTML. Il modulo qgis.utils fornisce una funzione, showPluginHelp() che aprirà il browser del file della Guida, allo stesso modo dell’aiuto di QGIS.

La funzione:func:showPluginHelp cerca i file di aiuto nella stessa cartella del modulo di chiamata. Cercherà, a turno, index-ll_cc.html, index-ll.html, index-en.html, index-en_us.html e index.html. Qui ll_cc is the QGIS. Ciò consente a più traduzioni della documentazione da includere nel plugin.

La funzione showPluginHelp() può anche accettare i parametri packageName, che identifica uno specifico plugin per il quale verrà visualizzata la guida, filename, che può sostituire «index» nei nomi dei file da ricercare, e section, che è il nome di un anchor tag html nel documento su cui verrà posizionato il browser.

16.1.4. Traduzione

Con pochi passaggi puoi impostare l’ambiente per la localizzazione del plugin, in modo che, a seconda delle impostazioni locali del computer, il plugin venga caricato in lingue diverse.

16.1.4.1. Requisiti software

Il modo più semplice per creare e gestire tutti i file di traduzione è installare Qt Linguist. In un ambiente GNU/Linux basato su Debian è possibile installarlo digitando:

sudo apt install qttools5-dev-tools

16.1.4.2. File e cartella

Quando crei il plugin troverai la cartella i18n all’interno della cartella principale dei plugin.

Tutti i file di traduzione devono trovarsi in questa cartella.

16.1.4.2.1. .pro file

Per prima cosa devi creare un file ``.pro””, cioè un file progetto che può essere gestito da Qt Linguist.

In questo file ``.pro”” devi specificare tutti i file e i moduli che vuoi tradurre. Questo file viene usato per impostare i file di localizzazione e le variabili. Un possibile file di progetto, che corrisponde alla struttura del nostro example plugin:

FORMS = ../form.ui
SOURCES = ../your_plugin.py
TRANSLATIONS = your_plugin_it.ts

Il tuo plugin potrebbe avere una struttura più complessa ed essere distribuito in diversi file. In questo caso, tieni presente che pylupdate5, il programma che si usa per leggere il file .pro e aggiornare la stringa traducibile, non espande i caratteri jolly, quindi devi inserire ogni file esplicitamente nel file .pro. Il file di progetto potrebbe quindi avere un aspetto simile a questo:

FORMS = ../ui/about.ui ../ui/feedback.ui \
        ../ui/main_dialog.ui
SOURCES = ../your_plugin.py ../computation.py \
          ../utils.py

Inoltre, il file tuo_plugin.py è il file che richiama tutti i menu e i sottomenu del tuo plugin nella barra degli strumenti di QGIS e tu vuoi tradurli tutti.

Infine, con la variabile TRANSLATIONS puoi specificare le lingue di traduzione volute.

Avvertimento

Assicurati di denominare il file ts come tuo_plugin_ + language + .ts altrimenti il caricamento della lingua fallirà! Utilizza la scorciatoia di 2 lettere per la lingua (it per l’italiano, de per il tedesco, ecc…)

16.1.4.2.2. .ts file

Una volta che hai creato il file .pro, sei pronto a generare il(i) file .ts per la lingua(e) del plugin.

Apri un terminale, vai nella cartella tuo_plugin/i18n e digita:

pylupdate5 your_plugin.pro

dovresti vedere il(i) file tuo_plugin_language.ts.

Apri il file ``.ts”” con Qt Linguist e inizia a tradurre.

16.1.4.2.3. .qm file

Quando hai finito di tradurre il plugin (se alcune stringhe non sono state completate, verrà usata la lingua di partenza per quelle stringhe), devi creare il file .qm (il file .ts compilato che verrà usato da QGIS).

Devi solo aprire un terminale con un cd nella cartella tuo_plugin/i18n e digitare:

lrelease your_plugin.ts

ora, nella cartella i18n vedrai il(i) file tuo_plugin.qm.

16.1.4.3. Tradurre con Makefile

In alternativa, puoi usare il makefile per estrarre i messaggi dal codice python e dalle finestre di dialogo Qt, se hai creato il plugin con Plugin Builder. All’inizio del Makefile c’è una variabile LOCALES:

LOCALES = en

Aggiungi l’abbreviazione della lingua a questa variabile, ad esempio per la lingua ungherese:

LOCALES = en hu

Ora puoi generare o aggiornare il file hu.ts (e anche en.ts) dai sorgenti da:

make transup

In questo modo, hai il file .ts aggiornato per tutte le lingue impostate nella variabile LOCALES. Utilizza Qt Linguist per tradurre i messaggi del programma. Al termine della traduzione, i file .qm possono essere creati da transcompile:

make transcompile

Devi installare i file ``.ts”” con il tuo plugin.

16.1.4.4. Caricare il plugin

Per vedere la traduzione del plugin, apri QGIS, cambia la lingua (:menuselection: Impostazioni –> Opzioni –> Generale) e riavvia QGIS.

Dovresti vedere il tuo plugin nella lingua corretta.

Avvertimento

Sei modifichi qualcosa nel plugin (nuove UI, nuovi menu, ecc.) devi generare nuovamente la versione aggiornata di entrambi i file .ts e .qm, quindi eseguire nuovamente il comando di cui sopra.

16.1.5. Suggerimenti e trucchi

16.1.5.1. Plugin Reloader

Durante lo sviluppo del tuo plugin sarà spesso necessario ricaricarlo in QGIS per testarlo. Questo è molto semplice utilizzando il plugin Plugin Reloader. È possibile trovarlo con il comando Plugin Manager.

16.1.5.2. Accessere ai plugin

Puoi accedere a tutte le classi dei plugin installati dall’interno di QGIS usando python, il che può essere utile a fini di debug.

my_plugin = qgis.utils.plugins['My Plugin']

16.1.5.3. Messaggi di Log

I plugin hanno una propria scheda all’interno del Pannello Messaggi di Log.

16.1.5.4. Condividi ilation tuo plugin

QGIS ospita centinaia di plugin nel repository dei plugin. Considera di condividere il tuo! Estenderà le possibilità di QGIS e le persone potranno imparare dal tuo codice. Tutti i plugin ospitati possono essere trovati e installati dall’interno di QGIS con il Plugin Manager.

Informazioni e requisiti sono disponibili qui: plugins.qgis.org.