Padrão de codificação do QGIS¶
Esses padrões devem ser seguidos por todos os desenvolvedores do QGIS
Classes¶
Nomes¶
A classe em QGIS começa com Qgs e é formada usando camel case.
Exemplos:
QgsPoint
QgsMapCanvas
QgsRasterLayer
Membros¶
Os nomes dos membros da classe começam com um m minúsculo e são formados usando maiúsculas e minúsculas.
mMapCanvas
mCurrentExtent
Todos os membros da classe devem ser privados. Membros públicos na classe são FORTEMENTE desencorajados. Os membros protegidos devem ser evitados quando o membro pode precisar ser acessado a partir de subclasses Python, uma vez que os membros protegidos não podem ser usados nas ligações Python.
Mutable static class member names should begin with a lower case s
,
but constant static class member names should be all caps:
sRefCounter
DEFAULT_QUEUE_SIZE
Funções do acessório¶
Os valores dos membros da classe devem ser obtidos através das funções do acessório. A função deve ser nomeada sem um prefixo de obtenção. As funções de acessório para os dois membros privados acima seriam.
mapCanvas()
currentExtent()
Certifique-se de que os acessadores estejam corretamente marcados com `` const``. Quando apropriado, isso pode exigir que as variáveis de membro do tipo de valor em cache sejam marcadas com `` mutable``.
Funções¶
Os nomes das funções começam com uma letra minúscula e são formados usando maiúsculas e minúsculas. O nome da função deve transmitir algo sobre o propósito da função.
updateMapExtent()
setUserOptions()
Por consistência com a API QGIS existente e com a API Qt, abreviações devem ser evitadas. Por exemplo. SetDestinationSize
ao invés de setDestSize
, setMaximumValue
ao invés de setMaxVal
.
Os acrônimos também devem utilizar camel case para consistência. Por exemplo. SetXml
ao invés de setXML
.
Argumentos de função¶
Function arguments should use descriptive names. Do not use single letter
arguments (e.g. setColor( const QColor& color )
instead of
setColor( const QColor& c )
).
Preste muita atenção quando os argumentos devem ser passados por referência. A menos que os objetos dos argumentos sejam pequenos e copiados trivialmente (como objetos QPoint), eles devem ser passados por referência. Por consistência com a API Qt, mesmo os objetos compartilhados implicitamente são passados por referência (por exemplo, setTitle (const QString & title)
ao invés de setTitle (QString title)
.
Valores de retorno da função¶
Return small and trivially copied objects as values. Larger objects
should be returned by const reference. The one exception to this
is implicitly shared objects, which are always returned by value. Return
QObject
or subclassed objects as pointers.
int maximumValue() const
const LayerSet& layers() const
QString title() const
(QString
is implicitly shared)QList< QgsMapLayer* > layers() const
(QList
is implicitly shared)QgsVectorLayer *layer() const;
(QgsVectorLayer
inheritsQObject
)QgsAbstractGeometry *geometry() const;
(QgsAbstractGeometry
is abstract and will probably need to be casted)
API Documentation¶
It is required to write API documentation for every class, method, enum and other code that is available in the public API.
QGIS uses Doxygen for documentation. Write descriptive and meaningful comments that give a reader information about what to expect, what happens in edge cases and give hints about other interfaces he could be looking for, best practices and code samples.
Methods¶
Method descriptions should be written in a descriptive form, using the 3rd
person. Methods require a \since
tag that defines when they have been
introduced. You should add additional \since
tags for important changes
that were introduced later on.
/**
* Cleans the laundry by using water and fast rotation.
* It will use the provided \a detergent during the washing programme.
*
* \returns True if everything was successful. If false is returned, use
* \link error() \endlink to get more information.
*
* \note Make sure to manually call dry() after this method.
*
* \since QGIS 3.0
* \see dry()
*/
Members Variables¶
Member variables should normally be in the private
section and made
available via getters and setters. One exception to this is for data
containers like for error reporting. In such cases do not prefix the member
with an m
.
/**
* \ingroup core
* Represents points on the way along the journey to a destination.
*
* \since QGIS 2.20
*/
class QgsWaypoint
{
/**
* Holds information about results of an operation on a QgsWaypoint.
*
* \since QGIS 3.0
*/
struct OperationResult
{
QgsWaypoint::ResultCode resultCode; //!< Indicates if the operation completed successfully.
QString message; //!< A human readable localized error message. Only set if the resultCode is not QgsWaypoint::Success.
QVariant result; //!< The result of the operation. The content depends on the method that returned it. \since QGIS 3.2
};
};
Qt Designer¶
Classes Geradas¶
Classes QGIS geradas a partir dos arquivos Qt Designer (ui) devem ter o sufixo Base. Isto identifica a classe como uma classe base gerada.
Exemplos:
QgsPluginManagerBase
QgsUserOptionsBase
Diálogos¶
Todos os diálogos devem implementar dicas de contexto para todos os ícones da barra de ferramentas e outros widgets relevantes. Dicas de contexto auxiliam muito na descoberta de funcionalidade tanto para usuários novos quanto experientes.
Garanta que a ordem das tabulações para os widgets seja atualizada sempre que o layout de um diálogo for alterado.
Arquivos C++¶
Nomes¶
Arquivos C++ de código e cabeçalhos devem ter extensão .cpp e .h, respectivamente. Nomes de arquivos devem ser todos em minúsculas e, no caso de representar uma classe, ter o mesmo nome da classe.
Example:
Class QgsFeatureAttribute
source files are
qgsfeatureattribute.cpp
and qgsfeatureattribute.h
Nota
No caso de não ter ficado claro na declaração acima, o nome do arquivo combinar com o nome da classe significa, implicitamente, que cada classe deve ser declarada e implementada em seu próprio arquivo. isto torna muito mais fácil para recèm-chegados identificar onde o código relativo para uma classe específica está localizado.
Cabeçalho Padrão e Licença¶
Cada arquivo de código fonte deve conter uma seção de cabeçalho padronizado conforme o exemplo a seguir:
/***************************************************************************
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
Este é um template para o Qt Creator no git. Para usá-lo, faça uma cópia local de doc/qt_creator_license_template
, ajuste o endereço de email e - se necessário - o nome e configure o QtCreator para usá-lo: .
Nomes de Variáveis¶
Nomes de variáveis locais devem começar com uma letra minúscula e serem formadas por maiúsculas e minúsculas. Não use prefixos como my
ou the
.
Exemplos:
mapCanvas
currentExtent
Tipos Enumerados¶
Tipos enumerados devem ser nomeados usando CamelCase iniciando com uma maiúscula. Exemplo:
enum UnitType
{
Meters,
Feet,
Degrees,
UnknownUnit
};
Não use nomes de tipos genéricos que causarão conflito com outros tipos. Exemplo. Use UnknownUnit
ao invés de Unknown
Constantes Globais & Macros¶
Constantes globais e macros devem ser escritas em maiúsculas e separadas por sublinha. ex.:
const long GEOCRS_ID = 3344;
Comments¶
Comments to class methods should use a third person indicative style instead of the imperative style:
/**
* Creates a new QgsFeatureFilterModel, optionally specifying a \a parent.
*/
explicit QgsFeatureFilterModel( QObject *parent = nullptr );
~QgsFeatureFilterModel() override;
Qt Signals e Slots¶
Todos as conexões de signal/slot devem ser feitas utilizando as conexões “new style” disponíveis no Qt5. Mais informações sobre este requisito está disponível em QEP #77.
Evite utilizar a auto conexão de slots do Qt (ex. aquelas nomeadas com void on_mSpinBox_valueChanged
). Conexões automáticas são frágeis e tendem a se quebrar sem aviso se os diálogos são alterados.
Editando¶
Qualquer editor de texto/IDE pode ser utilizada para editar o código do QGIS desde que os seguintes requisitos sejam satisfeitos.
Tabulações¶
Ajuste seu editor para emular tabulações com espaços. As tabulações devem ser ajustadas para 2 espaços.
Nota
No vin isto é feito com set expandtab ts=2
Indentação¶
Source code should be indented to improve readability. There is a
scripts/prepare-commit.sh
that looks up the changed files and reindents
them using astyle. This should be run before committing. You can also use
scripts/astyle.sh
to indent individual files.
As newer versions of astyle indent differently than the version used to do a
complete reindentation of the source, the script uses an old astyle version,
that we include in our repository (enable WITH_ASTYLE
in cmake to include
it in the build).
Parênteses¶
Parênteses devem iniciar na linha seguindo a expressão:
if( foo == 1 )
{
// do stuff
...
}
else
{
// do something else
...
}
Compatibilidade da API¶
There is API documentation for C++.
Tentamos manter a API estável e com compatível com versões anteriores. Limpezas na API devem ser feitas de maneira similar ao código fonte Qt. ex.
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();
}
SIP Bindings¶
Some of the SIP files are automatically generated using a dedicated script.
Header pre-processing¶
All the information to properly build the SIP file must be found in the C++ header file. Some macros are available for such definition:
Use
#ifdef SIP_RUN
to generate code only in SIP files or#ifndef SIP_RUN
for C++ code only.#else
statements are handled in both cases.Use
SIP_SKIP
to discard a lineThe following annotations are handled:
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/
private
sections are not displayed, except if you use a#ifdef SIP_RUN
statement in this block.SIP_PYDEFAULTVALUE(value)
can be used to define an alternative default value of the python method. If the default value contains a comma,
, the value should be surrounded by single quotes'
SIP_PYTYPE(type)
can be used to define an alternative type for an argument of the python method. If the type contains a comma,
, the type should be surrounded by single quotes'
A demo file can be found in tests/scripts/sipifyheader.h
.
Generating the SIP file¶
The SIP file can be generated using a dedicated script. For instance:
scripts/sipify.pl src/core/qgsvectorlayer.h > python/core/qgsvectorlayer.sip
As soon as a SIP file is added to one of the source file
(python/core/core.sip
, python/gui/gui.sip
or
python/analysis/analysis.sip
), it will be considered as generated
automatically. A test on Travis will ensure that this file is up to date with
its corresponding header.
Older files for which the automatic creation is not enabled yet are listed in
python/auto_sip.blacklist
.
Improving sipify script¶
If some improvements are required for sipify script, please add the missing bits
to the demo file tests/scripts/sipifyheader.h
and create the expected
header tests/scripts/sipifyheader.expected.si
. This will also be
automatically tested on Travis as a unit test of the script itself.
Estilo de Codificação¶
Aqui são descritas algumas dicas de programação que, esperamos, reduzirão erros, tempo de desenvolvimento e manutenção.
Sempre que possível, generalize o código¶
Se fizer cópia-cola do código, ou escrevendo a mesma coisa mais de uma vez, considere consolidar o código em uma função.
Isso vai:
permitir que alterações sejam feitas em apenas um local ao invés de vários
ajuda a prevenir inchaço no código
tornar mais difícil para várias cópias irem se diferenciando longo do tempo, tornando mais difícil a compreensão e a manutenção para os outros
Prefira Ter Constantes Antes nos Predicados¶
Prefira colocar as constantes primeiro nso predicados.
0 == value
ao invés de value == 0
Isso ajudará a impedir que os programadores acidentalmente usem `` = `` quando eles pretendem usar `` == ``, o que pode introduzir erros de lógica muito sutis. O compilador gerará um erro se você usar acidentalmente `` = `` em vez de `` == `` para comparações, uma vez que as constantes não podem ser atribuídas valores inerentes.
Espaços Podem Ser Seus Amigos¶
Adicionar espaços entre operadores, declarações e funções torna mais fácil para os humanos analisar o código.
O que é mais fácil de ler, isto:
if (!a&&b)
ou isto:
if ( ! a && b )
Nota
scripts/prepare-commit.sh
will take care of this.
Coloque comandos em linhas separadas¶
Ao ler o código, é fácil perder os comandos, se não estiverem no início da linha. Ao ler rapidamente o código, é comum ignorar linhas se não se parecem com o que você procura nos primeiros caracteres. Também é comum esperar um comando após um condicional como `` if``.
Considere:
if (foo) bar();
baz(); bar();
É muito fácil perder parte do fluxo de controle. Em vez disso use
if (foo)
bar();
baz();
bar();
Indente modificadores de acesso¶
Os modificadores de acesso estruturam uma classe em seções de API pública, API protegida e API privada. Os próprios modificadores de acesso agrupam o código nesta estrutura. Indente o modificador de acesso e as declarações.
class QgsStructure
{
public:
/**
* Constructor
*/
explicit QgsStructure();
}
Recomendações de Livros¶
Effective Modern C++, Scott Meyers
More Effective C++, Scott Meyers
Effective STL, Scott Meyers
Design Patterns, GoF
Você também deve realmente ler este artigo do Qt Quarterly sobre designing Qt style (APIs)
Créditos para as contribuições¶
Colaboradores de novas funções são encorajados em deixar as pessoas saberem sobre suas contribuições por:
Adicionando uma nota ao changelog na primeira versão em que o código for incorporado, do tipo:
This feature was funded by: Olmiomland https://olmiomland.ol This feature was developed by: Chuck Norris https://chucknorris.kr
writing an article about the new feature on a blog, and add it to the QGIS planet https://plugins.qgis.org/planet/
Adicionando seu nome em: