## 4. Un tutorial d'escriptura del connector Python

This tutorial will teach you the basics about writing a Python plug-in for GIMP 3.0. You are expected to already have some basic knowledge about writing Python in general. If not, there are enough Python courses online, we are not going to duplicate them here.

GIMP plug-ins in Python (and other languages too) are called from within GIMP to perform certain actions. To be able to know how to communicate with, and call the plug-in, GIMP needs to know by what name to call it and what functions it supports.

Hi ha certs requisits pel que fa al nom de fitxer i el nom del directori d'un connector, que han de ser els mateixos. Per a més detalls, vegeu Instal·lació de nous connectors.

### 4.1. Els elements bàsics d'un connector per al GIMP

Parlarem de les parts bàsiques d'un connector que són necessàries, o almenys molt comunes per a treballar amb el GIMP.

- Requerit en Linux i macOS, i habitualment en Windows, comença amb l'anomenat shebang o hashbang, una codificació i un avís de drets d'autor. La primera línia és un shebang que especifica com es pot executar aquest script. La següent línia especifica la codificació del fitxer Python. Recomanem utf-8. Normalment, això va seguit per diverses línies que especifiquen la llicència sota la qual es publica l'script i una breu descripció del que fa l'script. No aprofundirem en això, ja que en general és comú a Python.

- Importació de mòduls necessaris per a accedir al GIMP i opcionalment a les funcions GEGL.

- Declara una classe amb diverses funcions predefinides que heu d'ajustar, de manera que el GIMP sàpiga quines funcions estan disponibles al vostre connector i quines funcions suporten. A continuació, entrarem en més detalls sobre aquest tema.

- Una trucada que inicia el vostre connector o consulta les seves capacitats, depenent dels arguments que li enviï GIMP.

#### 4.1.1. Mòduls requerits

Per a poder accedir a les funcions del GIMP, comencem amb `import gi`. Aquest mòdul pot esbrinar quines funcions estan disponibles en cada mòdul definit a través de la «introspecció d'objectes». El que això significa per a nosaltres és que importem tots els mòduls relacionats amb el GIMP que puguem necessitar mitjançant crides a `gi.repository`.

Per a la funcionalitat bàsica, només els mòduls Gimp i GimpUi poden ser suficients. Si voleu executar el connector des de la línia d'ordres, ni tan sols necessitareu el GimpUi. Comencem amb un exemple.

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    #
    #   GIMP - The GNU Image Manipulation Program
    #   Copyright (C) 1995 Spencer Kimball and Peter Mattis
    #
    #   gimp-tutorial-plug-in.py
    #   sample plug-in to illustrate the Python plug-in writing tutorial
    #   Copyright (C) 2023 Jacob Boerema
    #
    #   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 3 of the License, or
    #   (at your option) any later version.
    #
    #   This program is distributed in the hope that it will be useful,
    #   but WITHOUT ANY WARRANTY; without even the implied warranty of
    #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    #   GNU General Public License for more details.
    #
    #   You should have received a copy of the GNU General Public License
    #   along with this program.  If not, see <https://www.gnu.org/licenses/>.

    import sys

    import gi
    gi.require_version('Gimp', '3.0')
    from gi.repository import Gimp
    gi.require_version('GimpUi', '3.0')
    from gi.repository import GimpUi
    from gi.repository import GLib

We start with importing sys, which we need at the end for access to `sys.argv`, following that `import gi` tells Python that it needs to load the gi module. This module is used to enable access to GIMP specific functions through «object introspection».

A la següent línia li diem a gi que necessitem que la versió de l'API del GIMP sigui la versió 3.0. (Aquest connector no funcionarà amb versions anteriors del GIMP.) La línia següent demana importar totes les funcions, classes, etc. des del mòdul del Gimp.

Les dues línies següents fan el mateix pel GimpUi. GimpUi conté tots els elements relacionats amb la interfície per al GIMP. Si teniu pensat crear un connector que només es cridarà des de la línia d'ordres, no ho necessitareu. Acabem amb la importació de GLib que necessitarem més endavant per accedir a GLib.Error.

There are other optional modules that you can use, too, like Gegl and many others, but we won't go into that here.

#### 4.1.2. Definiu la vostra classe de connector

El GIMP ha de saber quines funcions estan disponibles, quina funcionalitat admeten i quina ubicació del menú utilitzar. Per això definim una classe que es deriva de la classe `Gimp.PlugIn`.

A minimal plug-in needs at least the following functions defined in this class:

- A `do_query_procedure` method, which GIMP calls to find out the names of the procedures that can be called in this plug-in.

- A `do_set_i18n` method, which GIMP calls to find out if your plug-in supports translations.

- A `do_create_procedure` method, which GIMP calls to start one of your plug-ins functions. When this is called you should initialize certain information for GIMP. You start by creating a procedure that tells GIMP the name of the Python function to call to start your plug-in. Then you supply additional information, like what types of images your plug-in supports, where in the menu should your plug-in be found, and other optional settings.

- La funció real (anomenada procediment pel GIMP) que heu especificat anteriorment. Sovint l'anomenem `run`, però pot tenir qualsevol nom permès per Python. Aquesta funció és on afegireu el vostre propi codi per aplicar els efectes desitjats.

Ara entrarem una mica més en detall. No s'inclou a sota la primera part del codi Python que es mostrava a dalt. Això només mostra el disseny bàsic de la classe.

    class MyFirstPlugin (Gimp.PlugIn):
        def do_query_procedures(self):
            return [ "jb-plug-in-first-try" ]

        def do_set_i18n (self, name):
            return False

        def do_create_procedure(self, name):
            procedure = Gimp.ImageProcedure.new(self, name,
                                                Gimp.PDBProcType.PLUGIN,
                                                self.run, None)

            procedure.set_image_types("*")

            procedure.set_menu_label("My first Python plug-in")
            procedure.add_menu_path('<Image>/Filters/Tutorial/')

            procedure.set_documentation("My first Python plug-in tryout",
                                        "My first Python 3 plug-in for GIMP 3",
                                        name)
            procedure.set_attribution("Your name", "Your name", "2023")

            return procedure

        def run(self, procedure, run_mode, image, drawables, config, run_data):
            Gimp.message("Hello world!")
            # do what you want to do, then, in case of success, return:
            return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())

Let's take a closer look at `do_query_procedures`. In the line `return [ "jb-plug-in-first-try" ]` we tell GIMP what the name of our procedure is: we call it "jb-plug-in-first-try". This is the name that will be shown in GIMP's Procedure Browser.

Podeu tenir més d'un procediment definit en un connector. En aquest cas llistareu tots els noms separats per una coma.

És una bona pràctica iniciar tots els vostres tràmits amb les vostres inicials o alguna altra etiqueta reconeixible i única. D'aquesta manera és menys probable que el vostre nom sigui el mateix que el connector d'algú altre, cosa que podria confondre el GIMP. A més d'això, podeu anomenar-lo com vulgueu.

A continuació, li diem al GIMP que no admetem traduccions retornant False en la crida a `do_set_i18n`. Què fer quan voleu que el vostre connector es tradueixi i està fora de l'abast d'aquest tutorial.

El mètode `do_create_procedure` és on es fa la major part de la inicialització del GIMP.

Procediment 13.1. Configurant do_create_procedure

1. Si definiu més d'un procediment al vostre connector, primer heu de comprovar el paràmetre «nom» per a veure quin procediment està cridat pel GIMP. No entrarem en això.

   Per a inicialitzar el vostre procediment de connector, primer hem de crear-lo i emplenar en el nom de la nostra funció Python que farà el treball real. Ho fem cridant a Gimp.ImageProcedure.new.

           procedure = Gimp.ImageProcedure.new(self, name,
                                               Gimp.PDBProcType.PLUGIN,
                                               self.run, None)

   En aquest cas, definim el nom del nostre connector com a `self.run`. Quan qualifiquem la nostra funció amb «self.», vol dir que és un mètode dins de la nostra classe. Si ho prefereixes, també pots definir-la com una funció normal fora de la teva classe, en aquest cas ometríeu «self.». No cal posar-li el nom «run», podeu donar-li qualsevol nom que accepti Python.

2. A continuació li direm al GIMP amb quins tipus d'imatges pot treballar aquest connector cridant al procedure.set_image_types. En cas que el tipus d'imatge no importi, utilitzarem "*", que significa tots els tipus suportats pel GIMP. Altres exemples:

   1. "RGB*,GRAY*", on el "*" ací significa que admetem les dues versions amb i sense canal A(lpha).

   2. El connector «INDEXED» només funciona en imatges indexades, sense canal alfa.

   3. El connector «RGBA», només funciona en una imatge RGB amb canal alfa.

3. Ser capaç d'iniciar el connector des del menú del GIMP sol ser una bona idea. Comencem definint una etiqueta descriptiva per a l'entrada del menú: procedure.set_menu_label.

4. A continuació, especifiqueu on hauria d'aparèixer en el menú: procedure.add_menu_path. En aquest cas li demanem que afegeixi el nostre connector al menú Filtres, a la categoria Tutorial (submenú).

5. Si voleu, també podeu afegir un consell d'ajuda addicional mitjançant procedure.set_documentation, i podeu establir el vostre nom com a autor del connector utilitzant procedure.set_attribution .

6. L'última línia del procediment de creació és `procediment de retorn`, que torna a enviar la informació afegida anteriorment al GIMP. Després d'això, el GIMP cridarà el vostre procediment d'execució.

#### 4.1.3. Afegiu el punt d'entrada principal al vostre connector

Cada connector comença amb una crida a `Gimp.main`.

            Gimp.main(MyFirstPlugin.__gtype__, sys.argv)

L'única cosa que heu de canviar en aquesta línia per al vostre connector és el nom de la vostra classe de connector, ací anomenada «MyFirstPlugin».

#### 4.1.4. El connector Python complet

A continuació presentem l'script Python sencer que s'hauria d'executar sempre que se li doni el nom correcte en un directori amb el mateix nom, i en una ubicació que conegui el GIMP. Mostrarà el missatge «Hola món!» a la consola d'errors o en un diàleg emergent.

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    #
    #   GIMP - The GNU Image Manipulation Program
    #   Copyright (C) 1995 Spencer Kimball and Peter Mattis
    #
    #   gimp-tutorial-plug-in.py
    #   sample plug-in to illustrate the Python plug-in writing tutorial
    #   Copyright (C) 2023 Jacob Boerema
    #
    #   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 3 of the License, or
    #   (at your option) any later version.
    #
    #   This program is distributed in the hope that it will be useful,
    #   but WITHOUT ANY WARRANTY; without even the implied warranty of
    #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    #   GNU General Public License for more details.
    #
    #   You should have received a copy of the GNU General Public License
    #   along with this program.  If not, see <https://www.gnu.org/licenses/>.

    import sys

    import gi
    gi.require_version('Gimp', '3.0')
    from gi.repository import Gimp
    gi.require_version('GimpUi', '3.0')
    from gi.repository import GimpUi

    from gi.repository import GLib

    class MyFirstPlugin (Gimp.PlugIn):
        def do_query_procedures(self):
            return [ "jb-plug-in-first-try" ]

        def do_set_i18n (self, name):
            return False

        def do_create_procedure(self, name):
            procedure = Gimp.ImageProcedure.new(self, name,
                                                Gimp.PDBProcType.PLUGIN,
                                                self.run, None)

            procedure.set_image_types("*")

            procedure.set_menu_label("My first Python plug-in")
            procedure.add_menu_path('<Image>/Filters/Tutorial/')

            procedure.set_documentation("My first Python plug-in tryout",
                                        "My first Python 3 plug-in for GIMP 3.0",
                                        name)
            procedure.set_attribution("Your name", "Your name", "2023")

            return procedure

        def run(self, procedure, run_mode, image, drawables, config, run_data):
            Gimp.message("Hello world!")
            # do what you want to do, then, in case of success, return:
            return procedure.new_return_values(Gimp.PDBStatusType.SUCCESS, GLib.Error())

    Gimp.main(MyFirstPlugin.__gtype__, sys.argv)

3.7. El vostre script i la vostra feina |  | Part III. Referència de funcions

Report a bug in GIMP Informa d'un error de documentació