Importante

La traduzione è uno sforzo comunitario a cui puoi unirti. Questa pagina è attualmente tradotta al 99.41%.

16.1. Struttura Plugin Python

I passi principali per la creazione di un plugin sono:

  1. Idea: Avere un’idea di ciò che si vuole fare con il nuovo plugin QGIS.

  2. Impostazione: Create the files for your plugin. A seconda del tipo di plugin, alcuni sono obbligatori mentre altri sono opzionali

  3. Sviluppo: Write the code nei file appropriati

  4. Documentazione: Write the plugin documentation

  5. Opzionalmente: Tradurre: Translate your plugin in diverse lingue

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

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

16.1.1. Come iniziare

Prima di iniziare a scrivere un nuovo plugin, dai un’occhiata al Repository ufficiale dei plugin Python. Il codice sorgente dei plugin esistenti può aiutare a imparare di più sulla programmazione. Potresti anche scoprire che esiste già un plugin simile e che potresti essere in grado di estenderlo o almeno di basarti su di esso per sviluppare il tuo.

16.1.1.1. Imposta la struttura dei file del plugin

Per iniziare con un nuovo plugin, dobbiamo impostare i file necessari per il plugin.

Esistono due risorse relative a modelli di plugin che possono aiutarti a iniziare:

  • A scopo didattico o quando si desidera un approccio minimalista, il minimal plugin template fornisce i file di base (scheletro) necessari per creare un plugin QGIS Python valido.

  • Per un modello di plugin più completo, il Plugin Builder può creare modelli per diversi tipi di plugin, incluse funzionalità come la localizzazione (traduzione) e il testing.

Una tipica cartella contenente plugin comprende i seguenti file:

  • metadata.txt - obbligatorio - Contiene informazioni generali, versione, nome e alcuni altri metadati utilizzati dal sito web e dall’infrastruttura del plugin.

  • __init__.py - obbligatorio - Il punto di lancio del plugin. Deve avere il metodo classFactory() e può avere qualsiasi altro codice di inizializzazione.

  • mainPlugin.py - codice di base - Il codice di base del plugin. Contiene tutte le informazioni sulle azioni del plugin e il codice di base.

  • form.ui - per i plugin con GUI personalizzata - L’interfaccia grafica creata da Qt Designer.

  • form.py - GUI compilata - La traduzione del form.ui descritto sopra in Python.

  • resources.qrc - opzionale - Un documento .xml creato da Qt Designer. Contiene i percorsi relativi alle risorse utilizzate nei moduli della GUI.

  • resources.py - risorse compilate, opzionale - La traduzione in Python del file .qrc descritto sopra.

Avvertimento

Se tu vuoi caricare il plugin sul Repository ufficiale dei plugin Python devi controllare che il tuo plugin segua alcune regole aggiuntive, obbligatorie per la Validazione del plugin.

16.1.2. Scrivere codice per i plugin

La sezione seguente mostra il contenuto da aggiungere in ciascuno dei file introdotti in precedenza.

16.1.2.1. metadata.txt

Per prima cosa, il Plugin Manager deve recuperare alcune informazioni di base sul plugin, come il nome, la descrizione ecc. Queste informazioni sono memorizzate in metadata.txt.

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

una tra Raster, Vettore, Database, Mesh 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 Plugin (vedremo nella prossima sezione come aggiungere una voce di menu per il tuo plugin), ma possono anche essere inseriti nei menu Raster, Vettore, Database, Mesh e Web.

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("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("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.

Anche se le azioni di aiuto e di informazione possono essere aggiunte al menu personalizzato, un posto conveniente per renderle disponibili è il menu principale di QGIS Guida ► Plugin. Per farlo si utilizza il metodo pluginHelpMenu().

def initGui(self):

    self.help_action = QAction(
        QIcon("testplug:icon.png"),
        self.tr("Test Plugin..."),
        self.iface.mainWindow()
    )
    # Add the action to the Help menu
    self.iface.pluginHelpMenu().addAction(self.help_action)

    self.help_action.triggered.connect(self.show_help)

@staticmethod
def show_help():
    """ Open the online help. """
    QDesktopServices.openUrl(QUrl('https://docs.qgis.org'))

def unload(self):

    self.iface.pluginHelpMenu().removeAction(self.help_action)
    del self.help_action

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. Documentare plugin

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. Tradurre plugin

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. Condividere il 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.

16.1.6. Suggerimenti e trucchi

16.1.6.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.6.2. Automatizzare la pacchettizzazione, il rilascio e la traduzione con qgis-plugin-ci

qgis-plugin-ci fornisce un’interfaccia a linea di comando per eseguire l’impacchettamento e la distribuzione automatizzata dei plugin QGIS sul tuo computer, o utilizzando l’integrazione continua come i flussi di lavoro di GitHub o Gitlab-CI e Transifex per la traduzione.

Permette di rilasciare, tradurre, pubblicare o generare un file XML di repository di plugin tramite CLI o in azioni CI.

16.1.6.3. 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.6.4. Messaggi di Log

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

16.1.6.5. File delle risorse

Alcuni plugin utilizzano file di risorse, ad esempio resources.qrc che definiscono risorse per la GUI, come le icone:

<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.