Важно
Перевод - это работа сообщества : ссылка:Вы можете присоединиться. Эта страница в настоящее время переводится |прогресс перевода|.
1. Стандарты программирования QGIS
Стандарты кодирования QGIS описаны в документе о политике, доступном по адресу QEP #314. Все разработчики обязаны следовать этим правилам. Обратите внимание, что QEP #314 - это живой документ, и со временем эти правила могут измениться.
1.1. Классы
1.1.1. Функции доступа
Убедитесь, что аксессоры правильно помечены const
. Там, где это уместно, может потребоваться, чтобы переменные-члены типа кэшированного значения были помечены изменяемыми
.
1.1.2. Аргументы функции
Обратите внимание на то, когда аргументы следует передавать по ссылке. Если только объекты аргументов не малы и тривиально копируемы (например, объекты QPoint), их следует передавать по ссылке const. Для согласованности с Qt API даже неявно разделяемые объекты передаются по const-ссылке (например, setTitle( const QString& title )
вместо setTitle( QString title )
.
1.1.3. Возвращаемые значения функций
Возвращает небольшие и тривиально копируемые объекты в качестве значений. Более крупные объекты должны возвращаться по ссылке const. Исключением являются неявно разделяемые объекты, которые всегда возвращаются по значению. Возвращать QObject
или подклассифицированные объекты в виде указателей.
int maximumValue() const
const LayerSet& layers() const
QString title() const
(QString
неявно разделяется)QList< QgsMapLayer* > layers() const
(QList
неявно разделяется)QgsVectorLayer *layer() const;
(QgsVectorLayer
наследуетQObject
)QgsAbstractGeometry *geometry() const;
(QgsAbstractGeometry
является абстрактной и, вероятно, нуждается в кастинге)
1.2. API Документация
Требуется написать документацию API для каждого класса, метода, перечисления и другого кода, который доступен в публичном API.
QGIS использует Doxygen для документации. Пишите описательные и содержательные комментарии, которые дают читателю информацию о том, чего следует ожидать, что происходит в крайних случаях и дают подсказки о других интерфейсах, которые он может искать, лучших практиках и примерах кода.
1.2.1. Члены Переменные
Переменные-члены обычно должны находиться в секции приват
и быть доступны через геттеры и сеттеры. Исключение составляют контейнеры данных, например, для отчетов об ошибках. В таких случаях не следует добавлять к члену префикс m
.
1.3. Qt Designer
1.3.1. Сгенерированные классы
Классы QGIS, сгенерированные из файлов Qt Дизайнер (ui), должны иметь суффикс База. Это идентифицирует класс как сгенерированный базовый класс.
Примеры:
QgsPluginManagerBase
QgsUserOptionsBase
1.3.2. Диалоги
Во всех диалогах должны быть реализованы подсказки для всех значков панели инструментов и других соответствующих виджетов. Всплывающие подсказки значительно повышают удобство использования функций как для новичков, так и для опытных пользователей.
Убедитесь, что порядок вкладок для виджетов обновляется при изменении макета диалога.
1.4. C++ Файлы
1.4.1. Стандартный заголовок и лицензия
Каждый исходный файл должен содержать раздел заголовка по образцу следующего примера:
/***************************************************************************
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.
*
***************************************************************************/
Примечание
В git-репозитории есть шаблон для Qt Creator. Чтобы использовать его, скопируйте его из qt_creator_license_template в локальное место, настройте почтовый адрес и - если требуется - имя и настройте QtCreator на его использование: .
1.5. Редактирование
Для редактирования кода QGIS можно использовать любой текстовый редактор/IDE, если соблюдены следующие требования.
1.5.1. Вкладки
Установите в редакторе эмуляцию табуляции с помощью пробелов. Расстояние между табуляциями должно составлять 2 пробела.
Примечание
В vim это делается с помощью set expandtab ts=2
1.5.2. Индентирование
Для улучшения читабельности исходного кода следует делать отступы. Существует файл prepare_commit.sh, который просматривает измененные файлы и переиндексирует их с помощью astyle. Он должен быть запущен перед фиксацией. Вы также можете использовать astyle.sh для отступа отдельных файлов.
Поскольку в новых версиях astyle отступы отличаются от тех, которые используются для полной переиндексации исходного текста, скрипт использует старую версию astyle, которую мы включили в наш репозиторий (включите WITH_ASTYLE
в cmake, чтобы включить ее в сборку).
1.6. Совместимость с API
Существует API документация для C++.
Мы стараемся поддерживать стабильность и обратную совместимость API. Очистка API должна производиться аналогично исходному коду Qt, например.
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. Связывание SIP
Некоторые из SIP-файлов создаются автоматически с помощью специального скрипта.
1.7.1. Предварительная обработка заголовков
Вся информация для правильного построения SIP-файла должна содержаться в заголовочном файле C++. Для такого определения доступны некоторые макросы:
Используйте
#ifdef SIP_RUN
для генерации кода только в SIP-файлах или#ifndef SIP_RUN
только для кода на C++. Операторы#else
обрабатываются в обоих случаях.Используйте
SIP_SKIP
, чтобы отбросить строкуСледующие аннотации обрабатываются:
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/
Секции
привата
не отображаются, за исключением случаев, когда в этом блоке используется оператор#ifdef SIP_RUN
.SIP_PYDEFAULTVALUE(value)
можно использовать для определения альтернативного значения по умолчанию для метода python. Если значение по умолчанию содержит запятую,
, то значение должно быть окружено одинарными кавычками'
SIP_PYTYPE(type)
можно использовать для определения альтернативного типа аргумента метода python. Если тип содержит запятую,
, то тип должен быть окружен одинарными кавычками'
Также доступен демонстрационный файл, sipifyheader.h.
1.7.2. Формирование SIP файла
SIP-файл может быть создан с помощью специального скрипта. Например:
scripts/sipify.pl src/core/qgsvectorlayer.h > python/core/qgsvectorlayer.sip
Для автоматической генерации SIP-файла только что добавленного C++ файла необходимо выполнить sip_include.sh.
Как только SIP-файл будет добавлен в один из исходных файлов (core_auto.sip, gui_auto.sip или analysis_auto.sip), он будет считаться сгенерированным автоматически. Проверка убедится, что этот файл соответствует своему заголовку.
Для принудительного воссоздания SIP-файлов необходимо выполнить sipify_all.sh.
1.7.3. Улучшение скрипта sipify
Если для скрипта sipify требуются некоторые улучшения, пожалуйста, добавьте недостающие биты в демонстрационный файл sipifyheader.h и создайте файл ожидаемого заголовка sipifyheader.expected.sip
. Это также будет автоматически проверено в качестве модульного теста самого скрипта.
1.8. Установки
Кодовая база QGIS предлагает механизм для объявления, регистрации и использования настроек.
параметры должны быть определены с помощью одной из доступных реализаций (QgsSettingsEntryString, QgsSettingsEntryInteger, …).
настройки должны быть интегрированы в дерево настроек (QgsSettingsTree), это автоматически происходит при использовании конструктора с родительским узлом (QgsSettingsTreeNode).
Они объявляются как
const static
либо в специальном классе, либо непосредственно в реестре (core, gui, app, …).ключ настройки должен использовать
кебабный регистр
.
1.9. Стиль кодирования
Здесь описаны некоторые подсказки и советы по программированию, которые, надеемся, сократят количество ошибок, время разработки и обслуживания.
1.9.1. Везде, где это возможно, обобщайте код
Если вы вырезаете и вставляете код или пишете одно и то же несколько раз, подумайте о том, чтобы объединить код в одну функцию.
Это позволит:
позволяют вносить изменения в одном месте, а не в нескольких
помогают предотвратить разрастание кода
усложняют эволюцию различий между несколькими копиями с течением времени, тем самым усложняя понимание и поддержку для других
1.9.2. Выносите команды на отдельные строки
При чтении кода легко пропустить команды, если они не находятся в начале строки. При быстром чтении кода часто приходится пропускать строки, если в первых нескольких символах они не похожи на то, что вы ищете. Кроме того, принято ожидать команду после условного выражения типа if
.
Рассмотрите:
if (foo) bar();
baz(); bar();
Очень легко упустить часть потока управления. Вместо этого используйте
if (foo)
bar();
baz();
bar();
1.9.3. Книжные рекомендации
Effective Modern C++, Scott Meyers
More Effective C++, Scott Meyers
Effective STL, Scott Meyers
Design Patterns, GoF
Вам также следует прочитать эту статью из Qt Quarterly о разработке стиля Qt (API).
1.10. Кредиты на взносы
Разработчикам новых функций рекомендуется сообщать людям о своем вкладе:
добавление примечания в журнал изменений для первой версии, в которую был включен код, вида:
This feature was funded by: Olmiomland https://olmiomland.ol This feature was developed by: Chuck Norris https://chucknorris.kr
написать статью о новой функции в блоге и добавить ее в QGIS Planet.
добавление их имени к: