Важно

Перевод - это работа сообщества : ссылка:Вы можете присоединиться. Эта страница в настоящее время переводится |прогресс перевода|.

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 на его использование: Инструменты ► Опции ► C++ ► Именование файлов.

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. Книжные рекомендации

Вам также следует прочитать эту статью из Qt Quarterly о разработке стиля Qt (API).

1.10. Кредиты на взносы

Разработчикам новых функций рекомендуется сообщать людям о своем вкладе: