Importante

La traducción es un esfuerzo comunitario puede unirse. Esta página está actualmente traducida en |progreso de traducción|.

1. Estándares de codificación de QGIS

QGIS coding standards are described in the policy document available at QEP #314. All developers are required to follow those policies. Please note that QEP #314 is a live document, and that these policies may change over time.

1.1. Clases

1.1.1. Funciones del accesor

Asegúrese de que los accesores estén correctamente marcados con const. Cuando sea apropiado, esto puede requerir que el valor en caché de las variables del tipo miembro estén marcadas con mutable.

1.1.2. Argumentos de la función

Preste atención especial a cuándo se deben pasar los argumentos por referencia. A menos que los objetos de argumento sean pequeños y se copien trivialmente (como los objetos QPoint), se deben pasar por referencia const. Para mantener coherencia con la API Qt, incluso los objetos compartidos implícitamente pasan por referencia const (por ejemplo, `` setTitle (const QString & title) `` en lugar de `` setTitle (QString title) ``.

1.1.3. Función que regresa valores

Devuelva objetos pequeños y que se puedan copiar de forma trivial como valores. Los objetos más grandes deberían devolverse como una referencia constante. Una excepción a esto son los objetos compartidos de forma implícita, que siempre se devuelven por valor. Devuelva los objetos de tipo QObject u objetos de subclases de este como punteros.

  • int maximumValue() const

  • const LayerSet& layers() const

  • QString title() const (QString se comparte de forma implícita)

  • QList< QgsMapLayer* > layers() const (QList se comparte de manera implícita)

  • QgsVectorLayer *layer() const; (QgsVectorLayer hereda de QObject)

  • QgsAbstractGeometry *geometry() const; (QgsAbstractGeometry es abstracta y probablemente necesitará ser convertida al tipo específico)

1.2. Documentación de la API

Se necesita escribir la documentación de la API para cada clase, método, enumerado y cualquier otro código que esté accesible a través de la API pública.

QGIS utiliza Doxygen para la documentación. Escribe comentarios descriptivos y significativos que den al lector información sobre qué esperar, qué ocurre en casos extremos y le den pistas sobre otras interfaces que podría estar buscando, mejores prácticas y ejemplos de código.

1.2.1. Atributos de clase

Los atributos de clase deberían normalmente estar en la sección private y acceder a ellos a través de métodos getters y setters. Una excepción a esto son los contenedores de datos como los que se usan para informar de errores. En esos caso no se debe añadir el prefijo m al atributo.

1.3. Diseñador Qt

1.3.1. Clases Generadas

Las clases QGIS que se se generan desde archivos Qt Designer (ui) deberían tener un sufijo de Base. Esto identifica la clase como una clase base generada.

Ejemplos:

  • QgsPluginManagerBase

  • QgsUserOptionsBase

1.3.2. Diálogos

Todos los cuadros de diálogo deben implementar ayuda con información sobre herramientas para todos los iconos de la barra de herramientas y otros widgets relevantes. La información sobre herramientas agrega mucho a la detección de características para usuarios nuevos y experimentados.

Asegúrese de que el orden de tabulación para widgets se actualice cada vez que cambie el diseño de un diálogo.

1.4. Archivos C++

1.4.1. Encabezado y Licencia Estándar

Cada archivo de origen debería contener una sección de encabezado que siga el siguiente patrón de ejemplo:

/***************************************************************************
  qgsfield.cpp - Describes a field in a layer or table
  --------------------------------------
  Date : 01-Jan-2004
  Copyright: (C) 2004 by Gary E.Sherman
  Email: sherman at mrcc.com
/***************************************************************************
 *
 * 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 2 of the License, or
 * (at your option) any later version.
 *
 ***************************************************************************/

Nota

Hay una plantilla para Qt Creator en el repositorio git. Para usarla, cópiala de qt_creator_license_template a una ubicación local, ajusta la dirección de correo y -si es necesario- el nombre y configura QtCreator para usarla: Herramientas ► Opciones ► C++ ► Nombres de archivos.

1.5. Editando

Cualquier editor de texto/IDE puede ser usado para editar código QGIS, siempre que los siguientes requerimientos sean atendidos.

1.5.1. Tabulaciones

Defina su editor para emular tabulaciones con espacios. El espaciado de tabulación debería establecerse en 2 espacios.

Nota

En vim esto se hace con set expandtab ts=2

1.5.2. Indentación

El código fuente debe ser sangrado para mejorar la legibilidad. Hay un fichero prepare_commit.sh que busca los ficheros cambiados y los reentrelaza usando astyle. Debe ejecutarse antes de confirmar. También puede utilizar astyle.sh para sangrar archivos individuales.

Puesto que las nuevas versiones de astyle sangran de manera diferente a la versión que se usó para realizar el sangrado completo de todo el código fuente, el script usa una versión antigua de astyle que hemos incluido en nuestro repositorio (habilite WITH_ASTYLE en cmake para incluirla en la compilación)

1.6. Compatibilidad API

Aquí está API de documentación para C++.

Intentamos mantener la API estable y compatible con versiones anteriores. La limpieza de la API debe hacerse de forma similar al código fuente de Qt, por ejemplo

class Foo
{
  public:
    /**
     * This method will be deprecated, you are encouraged to use
     * doSomethingBetter() rather.
     * \deprecated use doSomethingBetter()
     */
    Q_DECL_DEPRECATED bool doSomething();

    /**
     * Does something a better way.
     * \note added in 1.1
     */
    bool doSomethingBetter();

  signals:
    /**
     * This signal will be deprecated, you are encouraged to
     * connect to somethingHappenedBetter() rather.
     * \deprecated use somethingHappenedBetter()
     */
#ifndef Q_MOC_RUN
    Q_DECL_DEPRECATED
#endif
    bool somethingHappened();

    /**
     * Something happened
     * \note added in 1.1
     */
    bool somethingHappenedBetter();
}

1.7. Enlaces con SIP

Algunos de los ficheros SIP se generan de forma automática a través de un script específico.

1.7.1. Preprocesamiento de cabeceras

Toda la información necesaria para generar de manera correcta el fichero SIP debe estar presente en el fichero de cabecera de C++. Están disponibles algunas macros para dicha definición:

  • Use #ifdef SIP_RUN para generar código sólo en los ficheros SIP o #ifndef SIP_RUN para generar sólo código C++. Las sentencias #else se procesan en ambos casos.

  • Use SIP_SKIP para descartar una línea

  • Se procesan las siguientes anotaciones:

    • SIP_FACTORY: /Factory/

    • SIP_OUT: /Out/

    • SIP_INOUT: /In,Out/

    • SIP_TRANSFER: /Transfer/

    • SIP_PYNAME(name): /PyName=name/

    • SIP_KEEPREFERENCE: /KeepReference/

    • SIP_TRANSFERTHIS: /TransferThis/

    • SIP_TRANSFERBACK: /TransferBack/

  • Las secciones private no se muestran, excepto si usa una sentencia #ifdef SIP_RUN en este bloque.

  • SIP_PYDEFAULTVALUE(value) puede usarse para definir un valor alternativo por defecto para el método Python. Si el valor por defecto contiene una coma ,, el valor debe rodearse por comillas simples '

  • SIP_PYTYPE(type) puede usarse para definir un tipo alternativo para el argumento de un método Python. Si el tipo contiene una coma ,, el tipo debe rodearse por comillas simples '

También está disponible un archivo de demostración, sipifyheader.h.

1.7.2. Generando el fichero SIP

El fichero SIP se puede generar usando un script específico. Por ejemplo:

scripts/sipify.pl src/core/qgsvectorlayer.h > python/core/qgsvectorlayer.sip

Para generar automáticamente el fichero SIP de un fichero C++ recién añadido es necesario ejecutar sip_include.sh.

En cuanto se añada un fichero SIP a uno de los ficheros fuente (core_auto.sip, gui_auto.sip o analysis_auto.sip), se considerará generado automáticamente. Un test on asegurará que este fichero está actualizado con su correspondiente cabecera.

Para forzar la recreación de los ficheros SIP, se ejecutará sipify_all.sh.

1.7.3. Mejorando el script sipify

If some improvements are required for sipify script, please add the missing bits to the demo file sipifyheader.h and create the expected header sipifyheader.expected.sip file. This will also be automatically tested as a unit test of the script itself.

1.8. Configuración

El código base de QGIS ofrece un mecanismo para declarar, registrar y utilizar configuraciones.

  • los ajustes deben definirse utilizando una de las implementaciones disponibles (QgsSettingsEntryString, QgsSettingsEntryInteger, …).

  • los ajustes deben integrarse en el árbol de ajustes (QgsSettingsTree), esto se hace automáticamente cuando se utiliza el constructor con un nodo padre (QgsSettingsTreeNode).

  • se declaran como const static ya sea en una clase dedicada o en el registro directamente (core, gui, app, …).

  • la clave de ajuste debe usar una kebab-case.

1.9. Estilo de Codificación

Aquí se describen algunas pistas y consejos de programación que podrán reducir errores, el tiempo de desarrollo y el mantenimiento.

1.9.1. Siempre que sea Posible Generalizar Código

Si usted está cortando y pegando código, o escribiendo la misma cosa más de una vez, considere consolidar el código en una sola función.

Esto hará:

  • permite hacer cambios en una ubicacion en lugar de en multiples ubicaciones

  • ayuda a prevenir codigo innnecesariamente largo o lento

  • dificulta para multiples copias la evolucion de diferencias en el tiempo, lo cual dificulta a otros entender y mantener

1.9.2. Ponga los comandos en líneas separadas

Cuando se lee codigo, es facil omitir comandos si estos no estan al comienzo de la linea. Cuando se lee rapidamente a lo largo del código, es comun saltarse lineas si estas no lucen como lo que se esta buscando en los primeros caracteres. Es tambien commun esperar un comando despues de una sentencia condicional como «if»

Considere:

if (foo) bar();

baz(); bar();

Es muy facil perder parte de lo que es el flujo de control. En lugar use

if (foo)
  bar();

baz();
bar();

1.9.3. Recomendaciones de libros

Debería también leer este artículo de Qt Quarterly sobre designing Qt style (APIs)

1.10. Créditos para contribuciones

Se anima a los que contribuyen nuevas funciones a hacer conocer a la gente acerca de sus contribuciones mediante: