<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://wiki.gis-lab.info/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Elf</id>
	<title>GIS-Lab - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.gis-lab.info/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Elf"/>
	<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/w/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Elf"/>
	<updated>2026-04-29T06:07:52Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.39.6</generator>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B4%D0%BB%D1%8F_QGIS_%D0%BD%D0%B0_Python&amp;diff=25249</id>
		<title>Разработка простого расширения для QGIS на Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B4%D0%BB%D1%8F_QGIS_%D0%BD%D0%B0_Python&amp;diff=25249"/>
		<updated>2017-03-21T11:12:06Z</updated>

		<summary type="html">&lt;p&gt;Elf: Уточнение ОС для раздела &amp;quot;Интернационализация&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Опубликована|qgis-dev-python}}&lt;br /&gt;
{{Аннотация|Описание процесса создания элементарного расширения для QGIS.}}&lt;br /&gt;
&lt;br /&gt;
QGIS — свободная пользовательская ГИС, обладающая развитым API и продвинутой системой расширений (модулей). Модули создаются для расширения функциональности программы. QGIS написана на объектно-ориентированном языке высокого уровня C++. Так же в QGIS встроены привязки (bindings), которые реализуют практически весь функционал QGIS на языке Python. Графический интерфейс пользователя QGIS базируется на библиотеках Qt4. Разработка для QGIS может вестись на двух языках, Python и C++. Для разработки на языке Python необходимы привязки [http://www.riverbankcomputing.co.uk/software/pyqt/intro PyQt], обеспечивающие взаимодействия Python с Qt4. Помимо расширений библиотеки QGIS могут быть также использованы для разработки отдельных приложений, что подробно описано в статье «[http://gis-lab.info/qa/qgis-standalone.html Создание приложения на базе набора библиотек QGIS на Python]».&lt;br /&gt;
&lt;br /&gt;
Данная статья описывает процесс создания каркаса расширения на языке Python. Разработанный каркас можно в дальнейшем использовать как основу для других расширений, выполняющих нужные функции.&lt;br /&gt;
&lt;br /&gt;
Создание расширения состоит из нескольких этапов:&lt;br /&gt;
&lt;br /&gt;
* Идея&lt;br /&gt;
* Создание каркаса&lt;br /&gt;
* Разработка необходимой функциональности.&lt;br /&gt;
* Тестирование&lt;br /&gt;
* Публикация&lt;br /&gt;
&lt;br /&gt;
Задача этой статьи - иллюстрация процесса создания простого расширения, которое:&lt;br /&gt;
* добавит новую кнопку на панель инструментов&lt;br /&gt;
* добавит подменю в меню расширений&lt;br /&gt;
* выполнит простое действие&lt;br /&gt;
* будет доступно на двух языках. &lt;br /&gt;
&lt;br /&gt;
Это расширение можно будет использовать как каркас для других будущих, более функциональных расширений. Далее мы более подробно разберем процесс создания по шагам.&lt;br /&gt;
&lt;br /&gt;
=== Получение исходного кода ===&lt;br /&gt;
&lt;br /&gt;
Код расширения, работающий под QGIS 2.0 можно получить в [https://github.com/nextgis/testplugin репозитории GitHub]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git clone git@github.com:nextgis/testplugin.git&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Подготовка ===&lt;br /&gt;
&lt;br /&gt;
Для разработки расширения понадобится&lt;br /&gt;
&lt;br /&gt;
* Любой текстовый редактор&lt;br /&gt;
* Python, лучше версии 2.5-2.7.х (3.x не подойдет)&lt;br /&gt;
* QGIS версии 2.0 и выше, для проверки работоспособности расширения.&lt;br /&gt;
&lt;br /&gt;
Если вы установили QGIS с помощью установщика [http://gis-lab.info/qa/qgis-osgeo4w.html osgeo4w] или [http://nextgis.ru/nextgis-qgis NextGIS QGIS], то у вас уже есть все необходимое для разработки. Ничего дополнительно устанавливать не нужно.&lt;br /&gt;
&lt;br /&gt;
Разработку можно вести прямо в папке, где хранятся расширения или переместить его в нее после разработки, в QGIS эта папка либо &amp;lt;tt&amp;gt;QGIS\python\plugins&amp;lt;/tt&amp;gt; либо &amp;lt;/tt&amp;gt;C:\Documents and Settings\username\.qgis2\python\plugins\&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В папке с плагинами необходимо создать новую, назвав ее так, чтобы бы по названию можно было легко определить, что именно делает расширение. Назовем нашу папку &amp;lt;code&amp;gt;testplugin&amp;lt;/code&amp;gt;. Это название следует запомнить, так как оно будет фигурировать в различных компонентах кода.&lt;br /&gt;
&lt;br /&gt;
Перед разработкой, нам нужно создать в этой папке несколько новых, пока пустых текстовых файлов:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;__init__.py&amp;lt;/tt&amp;gt; — начальная точка, создаёт экземпляр основного класса, который передается в QGIS&lt;br /&gt;
* &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt; — основной код расширения. Содержит всю информацию о всех действиях расширения.&lt;br /&gt;
* &amp;lt;tt&amp;gt;resources.qrc&amp;lt;/tt&amp;gt; — xml файл, создаваемый Qt Designer или вручную и содержащий относительные пути к ресурсам расширения, формам, иконкам и т.п. Компилируется в py перед созданием пакета плагина.&lt;br /&gt;
* &amp;lt;tt&amp;gt;metadata.txt&amp;lt;/tt&amp;gt; — описание модуля, содержит информацию о расширении, версию, имя разработчика&lt;br /&gt;
&lt;br /&gt;
Помимо этих файлов, если расширение использует формы, могут также присутствовать файлы:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;form.ui&amp;lt;/tt&amp;gt; — форма созданная с помощью Qt Designer&lt;br /&gt;
* &amp;lt;tt&amp;gt;form.py&amp;lt;/tt&amp;gt; — она же, скомпилированная в виде программы на языке Python&lt;br /&gt;
&lt;br /&gt;
Для примера из данной статьи эти файлы не понадобятся.&lt;br /&gt;
&lt;br /&gt;
Итак, пустые файлы созданы и лежат в нужной папке.&lt;br /&gt;
&lt;br /&gt;
Перед разработкой, отредактируем файл metadata.txt. Этот файл содержит информацию о расширении, такую как его название &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;, т.е. то, как он будет показываться в Менеджере модулей, его описание &amp;lt;tt&amp;gt;description&amp;lt;/tt&amp;gt;, показывается там же. Нужно также указать минимальную версию QGIS, для которой разработано это расширение (при попытке загрузки в QGIS меньшей версии плагин будет отключен) и другие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;[general]&lt;br /&gt;
name=TestPlugin&lt;br /&gt;
description=This plugin is for testing and templating purposes&lt;br /&gt;
category=Vector&lt;br /&gt;
version=0.0.2&lt;br /&gt;
qgisMinimumVersion=2.0&lt;br /&gt;
&lt;br /&gt;
author=NextGIS&lt;br /&gt;
email=info@nextgis.org&lt;br /&gt;
&lt;br /&gt;
icon=icons/icon.png&lt;br /&gt;
&lt;br /&gt;
tags=testing,template&lt;br /&gt;
&lt;br /&gt;
homepage=http://gis-lab.info/qa/qgis-dev-python.html&lt;br /&gt;
tracker=https://github.com/nextgis/testplugin/issues&lt;br /&gt;
repository=https://github.com/nextgis/testplugin&lt;br /&gt;
&lt;br /&gt;
experimental=True&lt;br /&gt;
deprecated=False&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Разработка ===&lt;br /&gt;
&lt;br /&gt;
Разработка начинается с файла &amp;lt;tt&amp;gt;__init__.py&amp;lt;/tt&amp;gt;. Главным фрагментом кода является импорт исполняемой части расширения, содержащейся в файле &amp;lt;tt&amp;gt;plugin.py&amp;lt;/tt&amp;gt; (поэтому &amp;lt;tt&amp;gt;from testplugin&amp;lt;/tt&amp;gt;) и содержащей всю содержательную часть кода.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def classFactory(iface):&lt;br /&gt;
  # Import class TestPlugin from file testplugin.py&lt;br /&gt;
  from testplugin import TestPlugin&lt;br /&gt;
  return TestPlugin(iface)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Название главного импортируемого класса &amp;lt;tt&amp;gt;TestPlugin&amp;lt;/tt&amp;gt; должно быть равно названию класса в коде &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;, название — регистрозависимое, если вызывается &amp;lt;tt&amp;gt;TestPlugin&amp;lt;/tt&amp;gt;, а класс носит название &amp;lt;tt&amp;gt;testplugin&amp;lt;/tt&amp;gt;, будет выдано сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как и во всех программах на языке Python, все начинается с импорта необходимых для работы классов, в нашем случае это будут классы PyQt — обертки для Qt на языке Python: PyQt4.QtCore и PyQt4.QtGui, активно используемые QGIS и сами классы QGIS: qgis.core&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Помимо этого нужно также импортировать ресурсы самого расширения, в нашем случае они будут задаваться через &amp;lt;tt&amp;gt;resources.py&amp;lt;/tt&amp;gt;, как его создать мы разберем чуть позже.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import resources&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После импорта идет раздел главного класса, импортируемого в &amp;lt;tt&amp;gt;__init__.py&amp;lt;/tt&amp;gt; и содержащего все нужные функции. Необходимо обратить внимание, что название класса должно быть равно названию используемому для его вызова в &amp;lt;tt&amp;gt;__init__.py&amp;lt;/tt&amp;gt;. Определение функции начинается с ключевого слова &amp;lt;tt&amp;gt;def&amp;lt;/tt&amp;gt;, за которым следует имя функции и ее аргументы.&lt;br /&gt;
&lt;br /&gt;
Объявим наш основной класс и функцию инициализации:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class TestPlugin:&lt;br /&gt;
&lt;br /&gt;
  def __init__(self, iface):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Initialize class&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # сохраним ссылку на интерфейс QGIS//save reference to QGIS interface&lt;br /&gt;
    self.iface = iface&lt;br /&gt;
    self.qgsVersion = unicode(QGis.QGIS_VERSION_INT)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одна из важнейших функций — создание элементов интерфейса расширения &amp;lt;tt&amp;gt;initGui&amp;lt;/tt&amp;gt;. При загрузке расширения к пользовательскому интерфейсу &amp;lt;tt&amp;gt;iface.self&amp;lt;/tt&amp;gt; могут добавляться кнопки &amp;lt;tt&amp;gt;addToolBarIcon&amp;lt;/tt&amp;gt; или строки в меню «Модули», &amp;lt;tt&amp;gt;addPluginToMenu&amp;lt;/tt&amp;gt;. Не забываем документировать функции с помощью тройных кавычек.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import resources&lt;br /&gt;
def initGui(self):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Инициализируем графический интерфейс пользователя&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    #проверим, не пытаются ли запустить плагин из QGIS версии ниже 2.0//check if the plugin is ran below 2.0&lt;br /&gt;
    if int(self.qgsVersion) &amp;lt; 10900:&lt;br /&gt;
        qgisVersion = self.qgsVersion[0] + &amp;quot;.&amp;quot; + self.qgsVersion[2] + &amp;quot;.&amp;quot; + self.qgsVersion[3]&lt;br /&gt;
        QMessageBox.warning(self.iface.mainWindow(),&lt;br /&gt;
                            &amp;quot;TestPlugin&amp;quot;, &amp;quot;Error&amp;quot;,&lt;br /&gt;
                            &amp;quot;TestPlugin&amp;quot;, &amp;quot;QGIS %s detected.\n&amp;quot; % (qgisVersion) +&lt;br /&gt;
                            &amp;quot;TestPlugin&amp;quot;, &amp;quot;This version of TestPlugin requires at least QGIS version 2.0.\nPlugin will not be enabled.&amp;quot;)&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    # create action that will be run by the plugin//создадим действие, которое будет запускать конфигурацию расширения&lt;br /&gt;
    self.action = QAction(&amp;quot;Test plugin&amp;quot;, self.iface.mainWindow())&lt;br /&gt;
    self.action.setIcon(QIcon(&amp;quot;:/icons/icon.png&amp;quot;))&lt;br /&gt;
    self.action.setWhatsThis(&amp;quot;Configuration for test plugin&amp;quot;)&lt;br /&gt;
    self.action.setStatusTip(&amp;quot;This is status tip&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # добавим пункт в меню инструментов Vector//add plugin menu to Vector toolbar&lt;br /&gt;
    self.iface.addPluginToVectorMenu(&amp;quot;TestPlugin&amp;quot;,self.action)&lt;br /&gt;
    &lt;br /&gt;
    # добавим кнопку на панель инструментов Vector//add icon to new menu item in Vector toolbar&lt;br /&gt;
    self.iface.addVectorToolBarIcon(self.action)&lt;br /&gt;
&lt;br /&gt;
    # связь действия с функцией run//connect action to the run method&lt;br /&gt;
    self.action.triggered.connect(self.run)&lt;br /&gt;
      &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Следующая важная функция расширения описывает то, что происходит при его выгрузке, выключении через Менеджер модулей — &amp;lt;tt&amp;gt;unload(self)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
  def unload(self):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Действия при выгрузке расширения&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # удалить меню расширения и иконку//remove menu and icon from the menu&lt;br /&gt;
    self.iface.removeVectorToolBarIcon(self.action)&lt;br /&gt;
    self.iface.removePluginVectorMenu(&amp;quot;TestPlugin&amp;quot;,self.action)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
И наконец функция выполняющая единственное действие в нашем расширении — &amp;lt;tt&amp;gt;run()&amp;lt;/tt&amp;gt;. Функция создаёт строку сообщения и показывает ее в &amp;lt;tt&amp;gt;QMessageBox&amp;lt;/tt&amp;gt; в главном окне программы.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
  def run(self):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Действия при запуске расширения&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # создать и показать сообщение//create a string and show it&lt;br /&gt;
    infoString = &amp;quot;This is a test&amp;quot;&lt;br /&gt;
    QMessageBox.information(self.iface.mainWindow(),&amp;quot;About&amp;quot;,infoString)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Интернационализация ===&lt;br /&gt;
Интернационализация позволяет сделать ваш плагин доступным на разных языках. [https://ru.wikipedia.org/wiki/Интернационализация Об интернационализации на wiki]&lt;br /&gt;
В качестве примера рассмотрим добавление перевода на русский язык. Команды в данном разделе указаны для систем Ubuntu/Debian. &lt;br /&gt;
Для начала нам потребуется внести изменения в код файла &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
Добавим импорт нового модуля &amp;lt;tt&amp;gt;os&amp;lt;/tt&amp;gt;, который позволит нам обращаться к файловой системе. Добавьте перед существующими &amp;quot;импортами&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Воспользуемся новым модулем. Метод &amp;lt;tt&amp;gt;__init__&amp;lt;/tt&amp;gt; теперь будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
    def __init__(self, iface):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Initialize class&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        # save reference to QGIS interface&lt;br /&gt;
        self.iface = iface&lt;br /&gt;
        self.qgsVersion = unicode(QGis.QGIS_VERSION_INT)&lt;br /&gt;
        self.plugin_dir = os.path.dirname(__file__)&lt;br /&gt;
        # initialize locale&lt;br /&gt;
        locale = QSettings().value('locale/userLocale')[0:2]&lt;br /&gt;
        locale_path = os.path.join(&lt;br /&gt;
            self.plugin_dir,&lt;br /&gt;
            'i18n',&lt;br /&gt;
            'TestPlugin_{}.qm'.format(locale))&lt;br /&gt;
        if os.path.exists(locale_path):&lt;br /&gt;
            self.translator = QTranslator()&lt;br /&gt;
            self.translator.load(locale_path)&lt;br /&gt;
&lt;br /&gt;
            if qVersion() &amp;gt; '4.3.3':&lt;br /&gt;
                QCoreApplication.installTranslator(self.translator)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Что изменилось? Мы добавили атрибут &amp;lt;tt&amp;gt;self.plugin_dir&amp;lt;/tt&amp;gt;, хранящий путь к папке с текущим файлом (&amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;). Получили из настроек QGIS текущую локаль (&amp;lt;tt&amp;gt;locale&amp;lt;/tt&amp;gt;), которую пытаемся использовать для обращения к пути файла перевода (&amp;lt;tt&amp;gt;locale_path&amp;lt;/tt&amp;gt;). Если такой файл существует, то загружаем из него перевод.&lt;br /&gt;
Сразу после метода &amp;lt;tt&amp;gt;__init__&amp;lt;/tt&amp;gt; создадим новый:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
    def tr(self, message):&lt;br /&gt;
        return QCoreApplication.translate(&amp;quot;TestPlugin&amp;quot;, message)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В Qt4 для перевода строки необходимо использовать метод &amp;lt;tt&amp;gt;QCoreApplication.translate()&amp;lt;/tt&amp;gt;. Для каждой строки, требующей перевода, писать такую конструкцию неудобно, поэтому мы и добавили новый метод &amp;lt;tt&amp;gt;tr&amp;lt;/tt&amp;gt;. В нашем примере есть только две строки, требующие перевода, и без данного метода можно было и обойтись, но вам он должен упростить жизнь. Далее используем новый метод для того, чтобы &amp;quot;пометить&amp;quot; строки для перевода:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
    def run(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Action to run&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        # create a string and show it&lt;br /&gt;
        infoString = self.tr(&amp;quot;This is a test&amp;quot;)&lt;br /&gt;
        QMessageBox.information(self.iface.mainWindow(), self.tr(&amp;quot;About&amp;quot;), infoString)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С кодом почти закончили, перейдем к заключительным действиям. Создайте папку &amp;lt;tt&amp;gt;i18n&amp;lt;/tt&amp;gt; рядом с файлом &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;. В папке &amp;lt;tt&amp;gt;i18n&amp;lt;/tt&amp;gt; создайте файл &amp;lt;tt&amp;gt;&amp;lt;ИмяВашегоПлагина&amp;gt;.pro&amp;lt;/tt&amp;gt;. В нашем примере это будет файл &amp;lt;tt&amp;gt;TestPlugin.pro&amp;lt;/tt&amp;gt;. Содержимое файла должно быть таким:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;SOURCES += ../testplugin.py&lt;br /&gt;
TRANSLATIONS += TestPlugin_ru.ts&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В &amp;lt;tt&amp;gt;SOURCES&amp;lt;/tt&amp;gt; перечисляются файлы, в которых требуется искать строки для перевода. Таких источников может быть несколько, и необходимо перечислить их все, добавляя новые строки &amp;lt;tt&amp;gt;SOURCES += ../&amp;lt;ИмяФайла&amp;gt;&amp;lt;/tt&amp;gt;. В нашем примере ресурс один. В &amp;lt;tt&amp;gt;TRANSLATIONS&amp;lt;/tt&amp;gt; перечисляются файлы, содержащие перевод в виде разметки XML, которые необходимо сгенерировать. В имени файла &amp;lt;tt&amp;gt;ru&amp;lt;/tt&amp;gt; значит, что это файл перевода на русский. Если хотите добавить другой язык, то после нижнего подчеркивания следует указать соответствующие две буквы. Например, &amp;lt;tt&amp;gt;uk&amp;lt;/tt&amp;gt; — украинский.&lt;br /&gt;
Далее необходимо установить инструменты разработчика. В частности, нам понадобятся &amp;lt;tt&amp;gt;pylupdate4&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;linguist&amp;lt;/tt&amp;gt;. Это делается следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install pyqt4-dev-tools&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В терминале выполняем команды:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;cd i18n&lt;br /&gt;
pylupdate4 TestPlugin.pro&lt;br /&gt;
linguist TestPlugin_ru.ts&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если требуется переводить сразу на несколько языков, то можно открыть несколько файлов, перечислив их: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;linguist TestPlugin_ru.ts TestPlugin_uk.ts&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или открыть все доступные файлы переводов: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;linguist *.ts&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Всплывающее окно заполните так:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Linguist_settings.jpg]]&lt;br /&gt;
&lt;br /&gt;
Если языков несколько, то настройте каждый отдельно в меню &amp;quot;Правка -&amp;gt; Параметры файла перевода&amp;quot;.&lt;br /&gt;
В поле &amp;quot;Русский перевод&amp;quot; введите желаемый перевод — &amp;quot;Это тест&amp;quot; и нажмите &amp;lt;tt&amp;gt;Ctrl+Enter&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Linguist_translation_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
Теперь введите &amp;quot;О Плагине&amp;quot; и нажмите &amp;lt;tt&amp;gt;Ctrl+Enter&amp;lt;/tt&amp;gt;. Далее &amp;quot;Файл -&amp;gt; Сохранить&amp;quot; и &amp;quot;Файл -&amp;gt; Скомпилировать&amp;quot;. Последняя операция создаст бинарный файл  &amp;lt;tt&amp;gt;TestPlugin_ru.qm&amp;lt;/tt&amp;gt;, содержащий перевод. Именно этот файл и будет использоваться при отображении плагина на русском языке.&lt;br /&gt;
Осталось проверить результат. Для перезагрузки разрабатываемых плагинов удобно использовать плагин с говорящим названием &amp;quot;Plugin Reloader&amp;quot;. В QGIS откройте меню &amp;quot;Модули -&amp;gt; Управление модулями&amp;quot;. Во вкладке &amp;quot;Параметры&amp;quot; поставьте галочку напротив &amp;quot;Разрешить установку экспериментальных модулей&amp;quot;. Во вкладке &amp;quot;Все&amp;quot; введите &amp;quot;Plugin Reloader&amp;quot; и нажмите &amp;quot;Установить модуль&amp;quot;. В настройках появившейся иконки плагина &amp;quot;Plugin Reloader&amp;quot; нажмите &amp;quot;Choose plugin to be reloaded&amp;quot; и выберите плагин &amp;quot;testplugin&amp;quot; из списка. Нажмите на иконку плагина &amp;quot;Plugin Reloader&amp;quot;, откройте &amp;quot;testplugin&amp;quot; и посмотрите результат.&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Файл:Testplugin_en.jpg‎|До перевода&lt;br /&gt;
Файл:Testplugin_ru.jpg‎|После перевода&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Какие функции из API доступны через Python ===&lt;br /&gt;
&lt;br /&gt;
К сожалению, не все функции API QGIS доступны через Python (через C++ доступны все). Чтобы определить, доступны ли конкретные классы и функции, необходимо сначала найти их в документации к API GIS [http://doc.qgis.org/ http://doc.qgis.org]. А затем в консоли Python (Модули\Консоль Python) определить с помощью команды &amp;lt;tt&amp;gt;dir&amp;lt;/tt&amp;gt; видны ли эти классы и функции из Python.&lt;br /&gt;
&lt;br /&gt;
Например, определим доступные классы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import qgis.core&lt;br /&gt;
dir(qgis.core)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Результат:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
['DEFAULT_LINE_WIDTH', 'DEFAULT_POINT_SIZE', 'DEFAULT_SEGMENT_EPSILON', 'ELLPS_PREFIX_LEN', 'GEOCRS_ID', 'GEOPROJ4', 'GEOSRID', 'GEOWKT', 'GEO_EPSG_CRS_AUTHID', 'GEO_EPSG_CRS_ID', 'GEO_NONE', 'LAT_PREFIX_LEN', 'MINIMUM_POINT_SIZE', 'NULL', 'PROJECT_SCALES', 'PROJ_PREFIX_LEN', 'QGis', 'QgsAbstractCacheIndex', 'QgsAbstractFeatureIterator', 'QgsAction', 'QgsAddRemoveItemCommand', 'QgsAddRemoveMultiFrameCommand', 'QgsApplication', 'QgsAtlasComposition', 'QgsAttributeAction', 'QgsAttributeEditorContainer', 'QgsAttributeEditorElement', 'QgsAttributeEditorField', 'QgsBilinearRasterResampler', 'QgsBrightnessContrastFilter', 'QgsBrowserModel', 'QgsCRSCache', 'QgsCacheIndexFeatureId', 'QgsCachedFeatureIterator', 'QgsCachedFeatureWriterIterator', 'QgsCategorizedSymbolRendererV2', 'QgsCentroidFillSymbolLayerV2', 'QgsClipToMinMaxEnhancement', 'QgsClipper', 'QgsColorBrewerPalette', 'QgsColorRampShader', 'QgsComposerArrow', 'QgsComposerAttributeTable', 'QgsComposerAttributeTableCompare', 'QgsComposerEffect', 'QgsComposerFrame', 'QgsComposerGroupItem', 'QgsComposerHtml', 'QgsComposerItem', 'QgsComposerItemCommand', 'QgsComposerItemGroup', 'QgsComposerLabel', 'QgsComposerLayerItem', 'QgsComposerLegend', 'QgsComposerLegendItem', 'QgsComposerLegendStyle', 'QgsComposerMap', 'QgsComposerMergeCommand', 'QgsComposerMultiFrame', 'QgsComposerMultiFrameCommand', 'QgsComposerPicture', 'QgsComposerRasterSymbolItem', 'QgsComposerScaleBar', 'QgsComposerShape', 'QgsComposerSymbolV2Item', 'QgsComposerTable', 'QgsComposerTextTable', 'QgsComposition', 'QgsContextHelp', 'QgsContrastEnhancement', 'QgsContrastEnhancementFunction', 'QgsCoordinateReferenceSystem', 'QgsCoordinateTransform', 'QgsCoordinateTransformCache', 'QgsCptCityArchive', 'QgsCptCityBrowserModel', 'QgsCptCityCollectionItem', 'QgsCptCityColorRampItem', 'QgsCptCityColorRampV2', 'QgsCptCityDataItem', 'QgsCptCityDirectoryItem', 'QgsCptCitySelectionItem', 'QgsCredentials', 'QgsCredentialsConsole', 'QgsCsException', 'QgsCubicRasterResampler', 'QgsDataCollectionItem', 'QgsDataDefined', 'QgsDataItem', 'QgsDataProvider', 'QgsDataSourceURI', 'QgsDbFilterProxyModel', 'QgsDiagram', 'QgsDiagramInterpolationSettings', 'QgsDiagramLayerSettings', 'QgsDiagramRendererV2', 'QgsDiagramSettings', 'QgsDirectoryItem', 'QgsDirectoryParamWidget', 'QgsDistanceArea', 'QgsDoubleBoxScaleBarStyle', 'QgsEllipseSymbolLayerV2', 'QgsError', 'QgsErrorItem', 'QgsErrorMessage', 'QgsException', 'QgsExpression', 'QgsFavouritesItem', 'QgsFeature', 'QgsFeatureIterator', 'QgsFeatureRendererV2', 'QgsFeatureRequest', 'QgsFeatureStore', 'QgsField', 'QgsFields', 'QgsFillSymbolLayerV2', 'QgsFillSymbolV2', 'QgsFontMarkerSymbolLayerV2', 'QgsFontUtils', 'QgsGPSConnection', 'QgsGPSConnectionRegistry', 'QgsGPSDetector', 'QgsGPSInformation', 'QgsGeometry', 'QgsGeometryCache', 'QgsGeometryValidator', 'QgsGml', 'QgsGmlFeatureClass', 'QgsGmlSchema', 'QgsGpsdConnection', 'QgsGradientStop', 'QgsGraduatedSymbolRendererV2', 'QgsHistogramDiagram', 'QgsHttpTransaction', 'QgsHueSaturationFilter', 'QgsImageFillSymbolLayer', 'QgsLabel', 'QgsLabelAttributes', 'QgsLabelCandidate', 'QgsLabelComponent', 'QgsLabelPosition', 'QgsLabelSearchTree', 'QgsLabelingEngineInterface', 'QgsLayerItem', 'QgsLegendModel', 'QgsLinePatternFillSymbolLayer', 'QgsLineSymbolLayerV2', 'QgsLineSymbolV2', 'QgsLinearMinMaxEnhancement', 'QgsLinearMinMaxEnhancementWithClip', 'QgsLinearlyInterpolatedDiagramRenderer', 'QgsLogger', 'QgsMapLayer', 'QgsMapLayerRegistry', 'QgsMapRenderer', 'QgsMapToPixel', 'QgsMarkerLineSymbolLayerV2', 'QgsMarkerSymbolLayerV2', 'QgsMarkerSymbolV2', 'QgsMessageLog', 'QgsMessageLogConsole', 'QgsMessageOutput', 'QgsMessageOutputConsole', 'QgsMimeDataUtils', 'QgsMultiBandColorRenderer', 'QgsNMEAConnection', 'QgsNetworkAccessManager', 'QgsNumericScaleBarStyle', 'QgsOWSConnection', 'QgsOfflineEditing', 'QgsOgcUtils', 'QgsPaintEngineHack', 'QgsPalLabeling', 'QgsPalLayerSettings', 'QgsPalettedRasterRenderer', 'QgsPaperItem', 'QgsPieDiagram', 'QgsPluginLayer', 'QgsPluginLayerRegistry', 'QgsPluginLayerType', 'QgsPoint', 'QgsPointDisplacementRenderer', 'QgsPointPatternFillSymbolLayer', 'QgsProject', 'QgsProjectBadLayerDefaultHandler', 'QgsProjectBadLayerHandler', 'QgsProjectFileTransform', 'QgsProjectVersion', 'QgsProperty', 'QgsPropertyKey', 'QgsPropertyValue', 'QgsProviderCountCalcEvent', 'QgsProviderExtentCalcEvent', 'QgsProviderMetadata', 'QgsProviderRegistry', 'QgsPseudoColorShader', 'QgsPythonRunner', 'QgsRaster', 'QgsRasterBandStats', 'QgsRasterBlock', 'QgsRasterChecker', 'QgsRasterDataProvider', 'QgsRasterDrawer', 'QgsRasterFileWriter', 'QgsRasterHistogram', 'QgsRasterIdentifyResult', 'QgsRasterInterface', 'QgsRasterIterator', 'QgsRasterLayer', 'QgsRasterNuller', 'QgsRasterPipe', 'QgsRasterProjector', 'QgsRasterPyramid', 'QgsRasterRange', 'QgsRasterRenderer', 'QgsRasterResampleFilter', 'QgsRasterResampler', 'QgsRasterShader', 'QgsRasterShaderFunction', 'QgsRasterTransparency', 'QgsRasterViewPort', 'QgsRectangle', 'QgsRenderChecker', 'QgsRenderContext', 'QgsRendererCategoryV2', 'QgsRendererRangeV2', 'QgsRendererV2AbstractMetadata', 'QgsRendererV2Metadata', 'QgsRendererV2Registry', 'QgsRuleBasedRendererV2', 'QgsRunProcess', 'QgsSVGFillSymbolLayer', 'QgsSatelliteInfo', 'QgsScaleBarStyle', 'QgsScaleCalculator', 'QgsScaleUtils', 'QgsSimpleFillSymbolLayerV2', 'QgsSimpleLineSymbolLayerV2', 'QgsSimpleMarkerSymbolLayerV2', 'QgsSingleBandColorDataRenderer', 'QgsSingleBandGrayRenderer', 'QgsSingleBandPseudoColorRenderer', 'QgsSingleBoxScaleBarStyle', 'QgsSingleCategoryDiagramRenderer', 'QgsSingleSymbolRendererV2', 'QgsSnapper', 'QgsSnappingResult', 'QgsSpatialIndex', 'QgsStyleV2', 'QgsSvgCache', 'QgsSvgCacheEntry', 'QgsSvgMarkerSymbolLayerV2', 'QgsSymbolLayerV2', 'QgsSymbolLayerV2AbstractMetadata', 'QgsSymbolLayerV2Metadata', 'QgsSymbolLayerV2Registry', 'QgsSymbolLayerV2Utils', 'QgsSymbolV2', 'QgsSymbolV2LevelItem', 'QgsSymbolV2RenderContext', 'QgsSymbologyV2Conversion', 'QgsTextDiagram', 'QgsTicksScaleBarStyle', 'QgsTolerance', 'QgsVectorColorBrewerColorRampV2', 'QgsVectorColorRampV2', 'QgsVectorDataProvider', 'QgsVectorFieldSymbolLayer', 'QgsVectorFileWriter', 'QgsVectorGradientColorRampV2', 'QgsVectorJoinInfo', 'QgsVectorLayer', 'QgsVectorLayerCache', 'QgsVectorLayerEditBuffer', 'QgsVectorLayerEditUtils', 'QgsVectorLayerFeatureIterator', 'QgsVectorLayerImport', 'QgsVectorLayerJoinBuffer', 'QgsVectorRandomColorRampV2', 'QgsZipItem', 'USER_CRS_START_ID', '__doc__', '__file__', '__name__', '__package__']&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее, после выбора нужного класса, например QgsFeature, посмотрим его методы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
dir(qgis.core.QgsFeature)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Результат:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
['__class__', '__delattr__', '__delitem__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'attribute', 'attributes', 'deleteAttribute', 'fieldNameIndex', 'fields', 'geometry', 'geometryAndOwnership', 'id', 'initAttributes', 'isValid', 'setAttribute', 'setAttributes', 'setFeatureId', 'setFields', 'setGeometry', 'setGeometryAndOwnership', 'setValid']&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ресурсы ===&lt;br /&gt;
&lt;br /&gt;
Для разработки расширения понадобится создать специальный файл, который будет содержать указатели на используемые расширением ресурсы, такие как например иконки. Пример такого файла:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;RCC&amp;gt;&lt;br /&gt;
&amp;lt;qresource prefix=&amp;quot;&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;file&amp;gt;icons/icon.png&amp;lt;/file&amp;gt;&lt;br /&gt;
&amp;lt;/qresource&amp;gt;&lt;br /&gt;
&amp;lt;/RCC&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рекомендуется использовать уникальный qresource prefix, который не будет конфликтовать с другими расширениями.&lt;br /&gt;
&lt;br /&gt;
После создания этого файла, необходимо его скомпилировать с помощью &amp;lt;tt&amp;gt;pyrcc4&amp;lt;/tt&amp;gt; в формат, который можно импортировать с помощью Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pyrcc4 -o resources.py resources.qrc &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
И как уже упоминалось выше, импортировать получившиеся ресурсы в основном коде &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Заключение ===&lt;br /&gt;
&lt;br /&gt;
Разработка каркаса нашего расширения завершена. Если она велась в папке расширений, то после запуска QGIS расширение должно автоматически появиться в списке расширений и можно начать его тестирование, отладку и, конечно, наполнение нужными полезными функциями.&lt;br /&gt;
&lt;br /&gt;
Помните, что лучшим пособием по разработке для QGIS являются расширения созданные другими авторами.&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-standalone.html Создание приложения на базе набора библиотек QGIS на Python]&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-repo.html Организация и работа с репозиториями расширений QGIS]&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>Elf</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B4%D0%BB%D1%8F_QGIS_%D0%BD%D0%B0_Python&amp;diff=25247</id>
		<title>Разработка простого расширения для QGIS на Python</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A0%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%B3%D0%BE_%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B4%D0%BB%D1%8F_QGIS_%D0%BD%D0%B0_Python&amp;diff=25247"/>
		<updated>2017-03-13T23:10:57Z</updated>

		<summary type="html">&lt;p&gt;Elf: Добавлен раздел об интернационализации. На гитхабе сделан pull request c изменениями кода.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Статья|Опубликована|qgis-dev-python}}&lt;br /&gt;
{{Аннотация|Описание процесса создания элементарного расширения для QGIS.}}&lt;br /&gt;
&lt;br /&gt;
QGIS — свободная пользовательская ГИС, обладающая развитым API и продвинутой системой расширений (модулей). Модули создаются для расширения функциональности программы. QGIS написана на объектно-ориентированном языке высокого уровня C++. Так же в QGIS встроены привязки (bindings), которые реализуют практически весь функционал QGIS на языке Python. Графический интерфейс пользователя QGIS базируется на библиотеках Qt4. Разработка для QGIS может вестись на двух языках, Python и C++. Для разработки на языке Python необходимы привязки [http://www.riverbankcomputing.co.uk/software/pyqt/intro PyQt], обеспечивающие взаимодействия Python с Qt4. Помимо расширений библиотеки QGIS могут быть также использованы для разработки отдельных приложений, что подробно описано в статье «[http://gis-lab.info/qa/qgis-standalone.html Создание приложения на базе набора библиотек QGIS на Python]».&lt;br /&gt;
&lt;br /&gt;
Данная статья описывает процесс создания каркаса расширения на языке Python. Разработанный каркас можно в дальнейшем использовать как основу для других расширений, выполняющих нужные функции.&lt;br /&gt;
&lt;br /&gt;
Создание расширения состоит из нескольких этапов:&lt;br /&gt;
&lt;br /&gt;
* Идея&lt;br /&gt;
* Создание каркаса&lt;br /&gt;
* Разработка необходимой функциональности.&lt;br /&gt;
* Тестирование&lt;br /&gt;
* Публикация&lt;br /&gt;
&lt;br /&gt;
Задача этой статьи - иллюстрация процесса создания простого расширения, которое:&lt;br /&gt;
* добавит новую кнопку на панель инструментов&lt;br /&gt;
* добавит подменю в меню расширений&lt;br /&gt;
* выполнит простое действие&lt;br /&gt;
* будет доступно на двух языках. &lt;br /&gt;
&lt;br /&gt;
Это расширение можно будет использовать как каркас для других будущих, более функциональных расширений. Далее мы более подробно разберем процесс создания по шагам.&lt;br /&gt;
&lt;br /&gt;
=== Получение исходного кода ===&lt;br /&gt;
&lt;br /&gt;
Код расширения, работающий под QGIS 2.0 можно получить в [https://github.com/nextgis/testplugin репозитории GitHub]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git clone git@github.com:nextgis/testplugin.git&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Подготовка ===&lt;br /&gt;
&lt;br /&gt;
Для разработки расширения понадобится&lt;br /&gt;
&lt;br /&gt;
* Любой текстовый редактор&lt;br /&gt;
* Python, лучше версии 2.5-2.7.х (3.x не подойдет)&lt;br /&gt;
* QGIS версии 2.0 и выше, для проверки работоспособности расширения.&lt;br /&gt;
&lt;br /&gt;
Если вы установили QGIS с помощью установщика [http://gis-lab.info/qa/qgis-osgeo4w.html osgeo4w] или [http://nextgis.ru/nextgis-qgis NextGIS QGIS], то у вас уже есть все необходимое для разработки. Ничего дополнительно устанавливать не нужно.&lt;br /&gt;
&lt;br /&gt;
Разработку можно вести прямо в папке, где хранятся расширения или переместить его в нее после разработки, в QGIS эта папка либо &amp;lt;tt&amp;gt;QGIS\python\plugins&amp;lt;/tt&amp;gt; либо &amp;lt;/tt&amp;gt;C:\Documents and Settings\username\.qgis2\python\plugins\&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В папке с плагинами необходимо создать новую, назвав ее так, чтобы бы по названию можно было легко определить, что именно делает расширение. Назовем нашу папку &amp;lt;code&amp;gt;testplugin&amp;lt;/code&amp;gt;. Это название следует запомнить, так как оно будет фигурировать в различных компонентах кода.&lt;br /&gt;
&lt;br /&gt;
Перед разработкой, нам нужно создать в этой папке несколько новых, пока пустых текстовых файлов:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;__init__.py&amp;lt;/tt&amp;gt; — начальная точка, создаёт экземпляр основного класса, который передается в QGIS&lt;br /&gt;
* &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt; — основной код расширения. Содержит всю информацию о всех действиях расширения.&lt;br /&gt;
* &amp;lt;tt&amp;gt;resources.qrc&amp;lt;/tt&amp;gt; — xml файл, создаваемый Qt Designer или вручную и содержащий относительные пути к ресурсам расширения, формам, иконкам и т.п. Компилируется в py перед созданием пакета плагина.&lt;br /&gt;
* &amp;lt;tt&amp;gt;metadata.txt&amp;lt;/tt&amp;gt; — описание модуля, содержит информацию о расширении, версию, имя разработчика&lt;br /&gt;
&lt;br /&gt;
Помимо этих файлов, если расширение использует формы, могут также присутствовать файлы:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;form.ui&amp;lt;/tt&amp;gt; — форма созданная с помощью Qt Designer&lt;br /&gt;
* &amp;lt;tt&amp;gt;form.py&amp;lt;/tt&amp;gt; — она же, скомпилированная в виде программы на языке Python&lt;br /&gt;
&lt;br /&gt;
Для примера из данной статьи эти файлы не понадобятся.&lt;br /&gt;
&lt;br /&gt;
Итак, пустые файлы созданы и лежат в нужной папке.&lt;br /&gt;
&lt;br /&gt;
Перед разработкой, отредактируем файл metadata.txt. Этот файл содержит информацию о расширении, такую как его название &amp;lt;tt&amp;gt;name&amp;lt;/tt&amp;gt;, т.е. то, как он будет показываться в Менеджере модулей, его описание &amp;lt;tt&amp;gt;description&amp;lt;/tt&amp;gt;, показывается там же. Нужно также указать минимальную версию QGIS, для которой разработано это расширение (при попытке загрузки в QGIS меньшей версии плагин будет отключен) и другие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;[general]&lt;br /&gt;
name=TestPlugin&lt;br /&gt;
description=This plugin is for testing and templating purposes&lt;br /&gt;
category=Vector&lt;br /&gt;
version=0.0.2&lt;br /&gt;
qgisMinimumVersion=2.0&lt;br /&gt;
&lt;br /&gt;
author=NextGIS&lt;br /&gt;
email=info@nextgis.org&lt;br /&gt;
&lt;br /&gt;
icon=icons/icon.png&lt;br /&gt;
&lt;br /&gt;
tags=testing,template&lt;br /&gt;
&lt;br /&gt;
homepage=http://gis-lab.info/qa/qgis-dev-python.html&lt;br /&gt;
tracker=https://github.com/nextgis/testplugin/issues&lt;br /&gt;
repository=https://github.com/nextgis/testplugin&lt;br /&gt;
&lt;br /&gt;
experimental=True&lt;br /&gt;
deprecated=False&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Разработка ===&lt;br /&gt;
&lt;br /&gt;
Разработка начинается с файла &amp;lt;tt&amp;gt;__init__.py&amp;lt;/tt&amp;gt;. Главным фрагментом кода является импорт исполняемой части расширения, содержащейся в файле &amp;lt;tt&amp;gt;plugin.py&amp;lt;/tt&amp;gt; (поэтому &amp;lt;tt&amp;gt;from testplugin&amp;lt;/tt&amp;gt;) и содержащей всю содержательную часть кода.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def classFactory(iface):&lt;br /&gt;
  # Import class TestPlugin from file testplugin.py&lt;br /&gt;
  from testplugin import TestPlugin&lt;br /&gt;
  return TestPlugin(iface)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Название главного импортируемого класса &amp;lt;tt&amp;gt;TestPlugin&amp;lt;/tt&amp;gt; должно быть равно названию класса в коде &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;, название — регистрозависимое, если вызывается &amp;lt;tt&amp;gt;TestPlugin&amp;lt;/tt&amp;gt;, а класс носит название &amp;lt;tt&amp;gt;testplugin&amp;lt;/tt&amp;gt;, будет выдано сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Как и во всех программах на языке Python, все начинается с импорта необходимых для работы классов, в нашем случае это будут классы PyQt — обертки для Qt на языке Python: PyQt4.QtCore и PyQt4.QtGui, активно используемые QGIS и сами классы QGIS: qgis.core&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# -*- coding: utf-8 -*-&lt;br /&gt;
from PyQt4.QtCore import *&lt;br /&gt;
from PyQt4.QtGui import *&lt;br /&gt;
from qgis.core import *&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Помимо этого нужно также импортировать ресурсы самого расширения, в нашем случае они будут задаваться через &amp;lt;tt&amp;gt;resources.py&amp;lt;/tt&amp;gt;, как его создать мы разберем чуть позже.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import resources&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
После импорта идет раздел главного класса, импортируемого в &amp;lt;tt&amp;gt;__init__.py&amp;lt;/tt&amp;gt; и содержащего все нужные функции. Необходимо обратить внимание, что название класса должно быть равно названию используемому для его вызова в &amp;lt;tt&amp;gt;__init__.py&amp;lt;/tt&amp;gt;. Определение функции начинается с ключевого слова &amp;lt;tt&amp;gt;def&amp;lt;/tt&amp;gt;, за которым следует имя функции и ее аргументы.&lt;br /&gt;
&lt;br /&gt;
Объявим наш основной класс и функцию инициализации:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class TestPlugin:&lt;br /&gt;
&lt;br /&gt;
  def __init__(self, iface):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Initialize class&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # сохраним ссылку на интерфейс QGIS//save reference to QGIS interface&lt;br /&gt;
    self.iface = iface&lt;br /&gt;
    self.qgsVersion = unicode(QGis.QGIS_VERSION_INT)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Одна из важнейших функций — создание элементов интерфейса расширения &amp;lt;tt&amp;gt;initGui&amp;lt;/tt&amp;gt;. При загрузке расширения к пользовательскому интерфейсу &amp;lt;tt&amp;gt;iface.self&amp;lt;/tt&amp;gt; могут добавляться кнопки &amp;lt;tt&amp;gt;addToolBarIcon&amp;lt;/tt&amp;gt; или строки в меню «Модули», &amp;lt;tt&amp;gt;addPluginToMenu&amp;lt;/tt&amp;gt;. Не забываем документировать функции с помощью тройных кавычек.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import resources&lt;br /&gt;
def initGui(self):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Инициализируем графический интерфейс пользователя&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    #проверим, не пытаются ли запустить плагин из QGIS версии ниже 2.0//check if the plugin is ran below 2.0&lt;br /&gt;
    if int(self.qgsVersion) &amp;lt; 10900:&lt;br /&gt;
        qgisVersion = self.qgsVersion[0] + &amp;quot;.&amp;quot; + self.qgsVersion[2] + &amp;quot;.&amp;quot; + self.qgsVersion[3]&lt;br /&gt;
        QMessageBox.warning(self.iface.mainWindow(),&lt;br /&gt;
                            &amp;quot;TestPlugin&amp;quot;, &amp;quot;Error&amp;quot;,&lt;br /&gt;
                            &amp;quot;TestPlugin&amp;quot;, &amp;quot;QGIS %s detected.\n&amp;quot; % (qgisVersion) +&lt;br /&gt;
                            &amp;quot;TestPlugin&amp;quot;, &amp;quot;This version of TestPlugin requires at least QGIS version 2.0.\nPlugin will not be enabled.&amp;quot;)&lt;br /&gt;
        return None&lt;br /&gt;
&lt;br /&gt;
    # create action that will be run by the plugin//создадим действие, которое будет запускать конфигурацию расширения&lt;br /&gt;
    self.action = QAction(&amp;quot;Test plugin&amp;quot;, self.iface.mainWindow())&lt;br /&gt;
    self.action.setIcon(QIcon(&amp;quot;:/icons/icon.png&amp;quot;))&lt;br /&gt;
    self.action.setWhatsThis(&amp;quot;Configuration for test plugin&amp;quot;)&lt;br /&gt;
    self.action.setStatusTip(&amp;quot;This is status tip&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    # добавим пункт в меню инструментов Vector//add plugin menu to Vector toolbar&lt;br /&gt;
    self.iface.addPluginToVectorMenu(&amp;quot;TestPlugin&amp;quot;,self.action)&lt;br /&gt;
    &lt;br /&gt;
    # добавим кнопку на панель инструментов Vector//add icon to new menu item in Vector toolbar&lt;br /&gt;
    self.iface.addVectorToolBarIcon(self.action)&lt;br /&gt;
&lt;br /&gt;
    # связь действия с функцией run//connect action to the run method&lt;br /&gt;
    self.action.triggered.connect(self.run)&lt;br /&gt;
      &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Следующая важная функция расширения описывает то, что происходит при его выгрузке, выключении через Менеджер модулей — &amp;lt;tt&amp;gt;unload(self)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
  def unload(self):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Действия при выгрузке расширения&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # удалить меню расширения и иконку//remove menu and icon from the menu&lt;br /&gt;
    self.iface.removeVectorToolBarIcon(self.action)&lt;br /&gt;
    self.iface.removePluginVectorMenu(&amp;quot;TestPlugin&amp;quot;,self.action)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
И наконец функция выполняющая единственное действие в нашем расширении — &amp;lt;tt&amp;gt;run()&amp;lt;/tt&amp;gt;. Функция создаёт строку сообщения и показывает ее в &amp;lt;tt&amp;gt;QMessageBox&amp;lt;/tt&amp;gt; в главном окне программы.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
  def run(self):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Действия при запуске расширения&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    # создать и показать сообщение//create a string and show it&lt;br /&gt;
    infoString = &amp;quot;This is a test&amp;quot;&lt;br /&gt;
    QMessageBox.information(self.iface.mainWindow(),&amp;quot;About&amp;quot;,infoString)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Интернационализация ===&lt;br /&gt;
Интернационализация позволяет сделать ваш плагин доступным на разных языках. [https://ru.wikipedia.org/wiki/Интернационализация Об интернационализации на wiki]&lt;br /&gt;
В качестве примера рассмотрим добавление перевода на русский язык.&lt;br /&gt;
Для начала нам потребуется внести изменения в код файла &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
Добавим импорт нового модуля &amp;lt;tt&amp;gt;os&amp;lt;/tt&amp;gt;, который позволит нам обращаться к файловой системе. Добавьте перед существующими &amp;quot;импортами&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Воспользуемся новым модулем. Метод &amp;lt;tt&amp;gt;__init__&amp;lt;/tt&amp;gt; теперь будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
    def __init__(self, iface):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Initialize class&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        # save reference to QGIS interface&lt;br /&gt;
        self.iface = iface&lt;br /&gt;
        self.qgsVersion = unicode(QGis.QGIS_VERSION_INT)&lt;br /&gt;
        self.plugin_dir = os.path.dirname(__file__)&lt;br /&gt;
        # initialize locale&lt;br /&gt;
        locale = QSettings().value('locale/userLocale')[0:2]&lt;br /&gt;
        locale_path = os.path.join(&lt;br /&gt;
            self.plugin_dir,&lt;br /&gt;
            'i18n',&lt;br /&gt;
            'TestPlugin_{}.qm'.format(locale))&lt;br /&gt;
        if os.path.exists(locale_path):&lt;br /&gt;
            self.translator = QTranslator()&lt;br /&gt;
            self.translator.load(locale_path)&lt;br /&gt;
&lt;br /&gt;
            if qVersion() &amp;gt; '4.3.3':&lt;br /&gt;
                QCoreApplication.installTranslator(self.translator)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Что изменилось? Мы добавили атрибут &amp;lt;tt&amp;gt;self.plugin_dir&amp;lt;/tt&amp;gt;, хранящий путь к папке с текущим файлом (&amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;). Получили из настроек QGIS текущую локаль (&amp;lt;tt&amp;gt;locale&amp;lt;/tt&amp;gt;), которую пытаемся использовать для обращения к пути файла перевода (&amp;lt;tt&amp;gt;locale_path&amp;lt;/tt&amp;gt;). Если такой файл существует, то загружаем из него перевод.&lt;br /&gt;
Сразу после метода &amp;lt;tt&amp;gt;__init__&amp;lt;/tt&amp;gt; создадим новый:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
    def tr(self, message):&lt;br /&gt;
        return QCoreApplication.translate(&amp;quot;TestPlugin&amp;quot;, message)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В Qt4 для перевода строки необходимо использовать метод &amp;lt;tt&amp;gt;QCoreApplication.translate()&amp;lt;/tt&amp;gt;. Для каждой строки, требующей перевода, писать такую конструкцию неудобно, поэтому мы и добавили новый метод &amp;lt;tt&amp;gt;tr&amp;lt;/tt&amp;gt;. В нашем примере есть только две строки, требующие перевода, и без данного метода можно было и обойтись, но вам он должен упростить жизнь. Далее используем новый метод для того, чтобы &amp;quot;пометить&amp;quot; строки для перевода:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
    def run(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Action to run&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        # create a string and show it&lt;br /&gt;
        infoString = self.tr(&amp;quot;This is a test&amp;quot;)&lt;br /&gt;
        QMessageBox.information(self.iface.mainWindow(), self.tr(&amp;quot;About&amp;quot;), infoString)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С кодом почти закончили, перейдем к заключительным действиям. Создайте папку &amp;lt;tt&amp;gt;i18n&amp;lt;/tt&amp;gt; рядом с файлом &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;. В папке &amp;lt;tt&amp;gt;i18n&amp;lt;/tt&amp;gt; создайте файл &amp;lt;tt&amp;gt;&amp;lt;ИмяВашегоПлагина&amp;gt;.pro&amp;lt;/tt&amp;gt;. В нашем примере это будет файл &amp;lt;tt&amp;gt;TestPlugin.pro&amp;lt;/tt&amp;gt;. Содержимое файла должно быть таким:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;SOURCES += ../testplugin.py&lt;br /&gt;
TRANSLATIONS += TestPlugin_ru.ts&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В &amp;lt;tt&amp;gt;SOURCES&amp;lt;/tt&amp;gt; перечисляются файлы, в которых требуется искать строки для перевода. Таких источников может быть несколько, и необходимо перечислить их все, добавляя новые строки &amp;lt;tt&amp;gt;SOURCES += ../&amp;lt;ИмяФайла&amp;gt;&amp;lt;/tt&amp;gt;. В нашем примере ресурс один. В &amp;lt;tt&amp;gt;TRANSLATIONS&amp;lt;/tt&amp;gt; перечисляются файлы, содержащие перевод в виде разметки XML, которые необходимо сгенерировать. В имени файла &amp;lt;tt&amp;gt;ru&amp;lt;/tt&amp;gt; значит, что это файл перевода на русский. Если хотите добавить другой язык, то после нижнего подчеркивания следует указать соответствующие две буквы. Например, &amp;lt;tt&amp;gt;uk&amp;lt;/tt&amp;gt; — украинский.&lt;br /&gt;
Далее необходимо установить инструменты разработчика. В частности, нам понадобятся &amp;lt;tt&amp;gt;pylupdate4&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;linguist&amp;lt;/tt&amp;gt;. Это делается следующей командой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo apt-get install pyqt4-dev-tools&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Данная команда подходит для систем Ubuntu/Debian. Если у вас Windows и команды &amp;lt;tt&amp;gt;pylupdate4&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;linguist&amp;lt;/tt&amp;gt; недоступны, то установите [http://pyqt.sourceforge.net/Docs/PyQt4/installation.html PyQt4]. В терминале выполняем команды:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;cd i18n&lt;br /&gt;
pylupdate4 TestPlugin.pro&lt;br /&gt;
linguist TestPlugin_ru.ts&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если требуется переводить сразу на несколько языков, то можно открыть несколько файлов, перечислив их: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;linguist TestPlugin_ru.ts TestPlugin_uk.ts&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или открыть все доступные файлы переводов: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;linguist *.ts&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Всплывающее окно заполните так:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Linguist_settings.jpg]]&lt;br /&gt;
&lt;br /&gt;
Если языков несколько, то настройте каждый отдельно в меню &amp;quot;Правка -&amp;gt; Параметры файла перевода&amp;quot;.&lt;br /&gt;
В поле &amp;quot;Русский перевод&amp;quot; введите желаемый перевод — &amp;quot;Это тест&amp;quot; и нажмите &amp;lt;tt&amp;gt;Ctrl+Enter&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Linguist_translation_example.jpg]]&lt;br /&gt;
&lt;br /&gt;
Теперь введите &amp;quot;О Плагине&amp;quot; и нажмите &amp;lt;tt&amp;gt;Ctrl+Enter&amp;lt;/tt&amp;gt;. Далее &amp;quot;Файл -&amp;gt; Сохранить&amp;quot; и &amp;quot;Файл -&amp;gt; Скомпилировать&amp;quot;. Последняя операция создаст бинарный файл  &amp;lt;tt&amp;gt;TestPlugin_ru.qm&amp;lt;/tt&amp;gt;, содержащий перевод. Именно этот файл и будет использоваться при отображении плагина на русском языке.&lt;br /&gt;
Осталось проверить результат. Для перезагрузки разрабатываемых плагинов удобно использовать плагин с говорящим названием &amp;quot;Plugin Reloader&amp;quot;. В QGIS откройте меню &amp;quot;Модули -&amp;gt; Управление модулями&amp;quot;. Во вкладке &amp;quot;Параметры&amp;quot; поставьте галочку напротив &amp;quot;Разрешить установку экспериментальных модулей&amp;quot;. Во вкладке &amp;quot;Все&amp;quot; введите &amp;quot;Plugin Reloader&amp;quot; и нажмите &amp;quot;Установить модуль&amp;quot;. В настройках появившейся иконки плагина &amp;quot;Plugin Reloader&amp;quot; нажмите &amp;quot;Choose plugin to be reloaded&amp;quot; и выберите плагин &amp;quot;testplugin&amp;quot; из списка. Нажмите на иконку плагина &amp;quot;Plugin Reloader&amp;quot;, откройте &amp;quot;testplugin&amp;quot; и посмотрите результат.&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Файл:Testplugin_en.jpg‎|До перевода&lt;br /&gt;
Файл:Testplugin_ru.jpg‎|После перевода&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Какие функции из API доступны через Python ===&lt;br /&gt;
&lt;br /&gt;
К сожалению, не все функции API QGIS доступны через Python (через C++ доступны все). Чтобы определить, доступны ли конкретные классы и функции, необходимо сначала найти их в документации к API GIS [http://doc.qgis.org/ http://doc.qgis.org]. А затем в консоли Python (Модули\Консоль Python) определить с помощью команды &amp;lt;tt&amp;gt;dir&amp;lt;/tt&amp;gt; видны ли эти классы и функции из Python.&lt;br /&gt;
&lt;br /&gt;
Например, определим доступные классы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import qgis.core&lt;br /&gt;
dir(qgis.core)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Результат:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
['DEFAULT_LINE_WIDTH', 'DEFAULT_POINT_SIZE', 'DEFAULT_SEGMENT_EPSILON', 'ELLPS_PREFIX_LEN', 'GEOCRS_ID', 'GEOPROJ4', 'GEOSRID', 'GEOWKT', 'GEO_EPSG_CRS_AUTHID', 'GEO_EPSG_CRS_ID', 'GEO_NONE', 'LAT_PREFIX_LEN', 'MINIMUM_POINT_SIZE', 'NULL', 'PROJECT_SCALES', 'PROJ_PREFIX_LEN', 'QGis', 'QgsAbstractCacheIndex', 'QgsAbstractFeatureIterator', 'QgsAction', 'QgsAddRemoveItemCommand', 'QgsAddRemoveMultiFrameCommand', 'QgsApplication', 'QgsAtlasComposition', 'QgsAttributeAction', 'QgsAttributeEditorContainer', 'QgsAttributeEditorElement', 'QgsAttributeEditorField', 'QgsBilinearRasterResampler', 'QgsBrightnessContrastFilter', 'QgsBrowserModel', 'QgsCRSCache', 'QgsCacheIndexFeatureId', 'QgsCachedFeatureIterator', 'QgsCachedFeatureWriterIterator', 'QgsCategorizedSymbolRendererV2', 'QgsCentroidFillSymbolLayerV2', 'QgsClipToMinMaxEnhancement', 'QgsClipper', 'QgsColorBrewerPalette', 'QgsColorRampShader', 'QgsComposerArrow', 'QgsComposerAttributeTable', 'QgsComposerAttributeTableCompare', 'QgsComposerEffect', 'QgsComposerFrame', 'QgsComposerGroupItem', 'QgsComposerHtml', 'QgsComposerItem', 'QgsComposerItemCommand', 'QgsComposerItemGroup', 'QgsComposerLabel', 'QgsComposerLayerItem', 'QgsComposerLegend', 'QgsComposerLegendItem', 'QgsComposerLegendStyle', 'QgsComposerMap', 'QgsComposerMergeCommand', 'QgsComposerMultiFrame', 'QgsComposerMultiFrameCommand', 'QgsComposerPicture', 'QgsComposerRasterSymbolItem', 'QgsComposerScaleBar', 'QgsComposerShape', 'QgsComposerSymbolV2Item', 'QgsComposerTable', 'QgsComposerTextTable', 'QgsComposition', 'QgsContextHelp', 'QgsContrastEnhancement', 'QgsContrastEnhancementFunction', 'QgsCoordinateReferenceSystem', 'QgsCoordinateTransform', 'QgsCoordinateTransformCache', 'QgsCptCityArchive', 'QgsCptCityBrowserModel', 'QgsCptCityCollectionItem', 'QgsCptCityColorRampItem', 'QgsCptCityColorRampV2', 'QgsCptCityDataItem', 'QgsCptCityDirectoryItem', 'QgsCptCitySelectionItem', 'QgsCredentials', 'QgsCredentialsConsole', 'QgsCsException', 'QgsCubicRasterResampler', 'QgsDataCollectionItem', 'QgsDataDefined', 'QgsDataItem', 'QgsDataProvider', 'QgsDataSourceURI', 'QgsDbFilterProxyModel', 'QgsDiagram', 'QgsDiagramInterpolationSettings', 'QgsDiagramLayerSettings', 'QgsDiagramRendererV2', 'QgsDiagramSettings', 'QgsDirectoryItem', 'QgsDirectoryParamWidget', 'QgsDistanceArea', 'QgsDoubleBoxScaleBarStyle', 'QgsEllipseSymbolLayerV2', 'QgsError', 'QgsErrorItem', 'QgsErrorMessage', 'QgsException', 'QgsExpression', 'QgsFavouritesItem', 'QgsFeature', 'QgsFeatureIterator', 'QgsFeatureRendererV2', 'QgsFeatureRequest', 'QgsFeatureStore', 'QgsField', 'QgsFields', 'QgsFillSymbolLayerV2', 'QgsFillSymbolV2', 'QgsFontMarkerSymbolLayerV2', 'QgsFontUtils', 'QgsGPSConnection', 'QgsGPSConnectionRegistry', 'QgsGPSDetector', 'QgsGPSInformation', 'QgsGeometry', 'QgsGeometryCache', 'QgsGeometryValidator', 'QgsGml', 'QgsGmlFeatureClass', 'QgsGmlSchema', 'QgsGpsdConnection', 'QgsGradientStop', 'QgsGraduatedSymbolRendererV2', 'QgsHistogramDiagram', 'QgsHttpTransaction', 'QgsHueSaturationFilter', 'QgsImageFillSymbolLayer', 'QgsLabel', 'QgsLabelAttributes', 'QgsLabelCandidate', 'QgsLabelComponent', 'QgsLabelPosition', 'QgsLabelSearchTree', 'QgsLabelingEngineInterface', 'QgsLayerItem', 'QgsLegendModel', 'QgsLinePatternFillSymbolLayer', 'QgsLineSymbolLayerV2', 'QgsLineSymbolV2', 'QgsLinearMinMaxEnhancement', 'QgsLinearMinMaxEnhancementWithClip', 'QgsLinearlyInterpolatedDiagramRenderer', 'QgsLogger', 'QgsMapLayer', 'QgsMapLayerRegistry', 'QgsMapRenderer', 'QgsMapToPixel', 'QgsMarkerLineSymbolLayerV2', 'QgsMarkerSymbolLayerV2', 'QgsMarkerSymbolV2', 'QgsMessageLog', 'QgsMessageLogConsole', 'QgsMessageOutput', 'QgsMessageOutputConsole', 'QgsMimeDataUtils', 'QgsMultiBandColorRenderer', 'QgsNMEAConnection', 'QgsNetworkAccessManager', 'QgsNumericScaleBarStyle', 'QgsOWSConnection', 'QgsOfflineEditing', 'QgsOgcUtils', 'QgsPaintEngineHack', 'QgsPalLabeling', 'QgsPalLayerSettings', 'QgsPalettedRasterRenderer', 'QgsPaperItem', 'QgsPieDiagram', 'QgsPluginLayer', 'QgsPluginLayerRegistry', 'QgsPluginLayerType', 'QgsPoint', 'QgsPointDisplacementRenderer', 'QgsPointPatternFillSymbolLayer', 'QgsProject', 'QgsProjectBadLayerDefaultHandler', 'QgsProjectBadLayerHandler', 'QgsProjectFileTransform', 'QgsProjectVersion', 'QgsProperty', 'QgsPropertyKey', 'QgsPropertyValue', 'QgsProviderCountCalcEvent', 'QgsProviderExtentCalcEvent', 'QgsProviderMetadata', 'QgsProviderRegistry', 'QgsPseudoColorShader', 'QgsPythonRunner', 'QgsRaster', 'QgsRasterBandStats', 'QgsRasterBlock', 'QgsRasterChecker', 'QgsRasterDataProvider', 'QgsRasterDrawer', 'QgsRasterFileWriter', 'QgsRasterHistogram', 'QgsRasterIdentifyResult', 'QgsRasterInterface', 'QgsRasterIterator', 'QgsRasterLayer', 'QgsRasterNuller', 'QgsRasterPipe', 'QgsRasterProjector', 'QgsRasterPyramid', 'QgsRasterRange', 'QgsRasterRenderer', 'QgsRasterResampleFilter', 'QgsRasterResampler', 'QgsRasterShader', 'QgsRasterShaderFunction', 'QgsRasterTransparency', 'QgsRasterViewPort', 'QgsRectangle', 'QgsRenderChecker', 'QgsRenderContext', 'QgsRendererCategoryV2', 'QgsRendererRangeV2', 'QgsRendererV2AbstractMetadata', 'QgsRendererV2Metadata', 'QgsRendererV2Registry', 'QgsRuleBasedRendererV2', 'QgsRunProcess', 'QgsSVGFillSymbolLayer', 'QgsSatelliteInfo', 'QgsScaleBarStyle', 'QgsScaleCalculator', 'QgsScaleUtils', 'QgsSimpleFillSymbolLayerV2', 'QgsSimpleLineSymbolLayerV2', 'QgsSimpleMarkerSymbolLayerV2', 'QgsSingleBandColorDataRenderer', 'QgsSingleBandGrayRenderer', 'QgsSingleBandPseudoColorRenderer', 'QgsSingleBoxScaleBarStyle', 'QgsSingleCategoryDiagramRenderer', 'QgsSingleSymbolRendererV2', 'QgsSnapper', 'QgsSnappingResult', 'QgsSpatialIndex', 'QgsStyleV2', 'QgsSvgCache', 'QgsSvgCacheEntry', 'QgsSvgMarkerSymbolLayerV2', 'QgsSymbolLayerV2', 'QgsSymbolLayerV2AbstractMetadata', 'QgsSymbolLayerV2Metadata', 'QgsSymbolLayerV2Registry', 'QgsSymbolLayerV2Utils', 'QgsSymbolV2', 'QgsSymbolV2LevelItem', 'QgsSymbolV2RenderContext', 'QgsSymbologyV2Conversion', 'QgsTextDiagram', 'QgsTicksScaleBarStyle', 'QgsTolerance', 'QgsVectorColorBrewerColorRampV2', 'QgsVectorColorRampV2', 'QgsVectorDataProvider', 'QgsVectorFieldSymbolLayer', 'QgsVectorFileWriter', 'QgsVectorGradientColorRampV2', 'QgsVectorJoinInfo', 'QgsVectorLayer', 'QgsVectorLayerCache', 'QgsVectorLayerEditBuffer', 'QgsVectorLayerEditUtils', 'QgsVectorLayerFeatureIterator', 'QgsVectorLayerImport', 'QgsVectorLayerJoinBuffer', 'QgsVectorRandomColorRampV2', 'QgsZipItem', 'USER_CRS_START_ID', '__doc__', '__file__', '__name__', '__package__']&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Далее, после выбора нужного класса, например QgsFeature, посмотрим его методы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
dir(qgis.core.QgsFeature)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Результат:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
['__class__', '__delattr__', '__delitem__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'attribute', 'attributes', 'deleteAttribute', 'fieldNameIndex', 'fields', 'geometry', 'geometryAndOwnership', 'id', 'initAttributes', 'isValid', 'setAttribute', 'setAttributes', 'setFeatureId', 'setFields', 'setGeometry', 'setGeometryAndOwnership', 'setValid']&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ресурсы ===&lt;br /&gt;
&lt;br /&gt;
Для разработки расширения понадобится создать специальный файл, который будет содержать указатели на используемые расширением ресурсы, такие как например иконки. Пример такого файла:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;RCC&amp;gt;&lt;br /&gt;
&amp;lt;qresource prefix=&amp;quot;&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;file&amp;gt;icons/icon.png&amp;lt;/file&amp;gt;&lt;br /&gt;
&amp;lt;/qresource&amp;gt;&lt;br /&gt;
&amp;lt;/RCC&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Рекомендуется использовать уникальный qresource prefix, который не будет конфликтовать с другими расширениями.&lt;br /&gt;
&lt;br /&gt;
После создания этого файла, необходимо его скомпилировать с помощью &amp;lt;tt&amp;gt;pyrcc4&amp;lt;/tt&amp;gt; в формат, который можно импортировать с помощью Python:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pyrcc4 -o resources.py resources.qrc &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
И как уже упоминалось выше, импортировать получившиеся ресурсы в основном коде &amp;lt;tt&amp;gt;testplugin.py&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Заключение ===&lt;br /&gt;
&lt;br /&gt;
Разработка каркаса нашего расширения завершена. Если она велась в папке расширений, то после запуска QGIS расширение должно автоматически появиться в списке расширений и можно начать его тестирование, отладку и, конечно, наполнение нужными полезными функциями.&lt;br /&gt;
&lt;br /&gt;
Помните, что лучшим пособием по разработке для QGIS являются расширения созданные другими авторами.&lt;br /&gt;
&lt;br /&gt;
=== Ссылки по теме ===&lt;br /&gt;
&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-standalone.html Создание приложения на базе набора библиотек QGIS на Python]&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-repo.html Организация и работа с репозиториями расширений QGIS]&lt;br /&gt;
* [http://gis-lab.info/qa/qgis-install-plugin.html Установка модулей расширения в QGIS]&lt;br /&gt;
* [http://gis-lab.info/docs/qgis Документация по QGIS]&lt;/div&gt;</summary>
		<author><name>Elf</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Testplugin_ru.jpg&amp;diff=25246</id>
		<title>Файл:Testplugin ru.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Testplugin_ru.jpg&amp;diff=25246"/>
		<updated>2017-03-13T22:57:26Z</updated>

		<summary type="html">&lt;p&gt;Elf: Interface of testplugin in Russian.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Interface of testplugin in Russian.&lt;/div&gt;</summary>
		<author><name>Elf</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Testplugin_en.jpg&amp;diff=25245</id>
		<title>Файл:Testplugin en.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Testplugin_en.jpg&amp;diff=25245"/>
		<updated>2017-03-13T22:56:38Z</updated>

		<summary type="html">&lt;p&gt;Elf: загружена новая версия «Файл:Testplugin en.jpg»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Interface of testplugin in English.&lt;/div&gt;</summary>
		<author><name>Elf</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Testplugin_en.jpg&amp;diff=25244</id>
		<title>Файл:Testplugin en.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Testplugin_en.jpg&amp;diff=25244"/>
		<updated>2017-03-13T22:55:58Z</updated>

		<summary type="html">&lt;p&gt;Elf: Отмена правки 25243, сделанной участником Elf (обс.)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Interface of testplugin in English.&lt;/div&gt;</summary>
		<author><name>Elf</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Testplugin_en.jpg&amp;diff=25243</id>
		<title>Файл:Testplugin en.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Testplugin_en.jpg&amp;diff=25243"/>
		<updated>2017-03-13T22:55:07Z</updated>

		<summary type="html">&lt;p&gt;Elf: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Interface of testplugin in Russian.&lt;/div&gt;</summary>
		<author><name>Elf</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Testplugin_en.jpg&amp;diff=25242</id>
		<title>Файл:Testplugin en.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Testplugin_en.jpg&amp;diff=25242"/>
		<updated>2017-03-13T22:52:17Z</updated>

		<summary type="html">&lt;p&gt;Elf: Interface of testplugin in English.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Interface of testplugin in English.&lt;/div&gt;</summary>
		<author><name>Elf</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Linguist_translation_example.jpg&amp;diff=25241</id>
		<title>Файл:Linguist translation example.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Linguist_translation_example.jpg&amp;diff=25241"/>
		<updated>2017-03-13T22:36:58Z</updated>

		<summary type="html">&lt;p&gt;Elf: Linguist example of translation&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Linguist example of translation&lt;/div&gt;</summary>
		<author><name>Elf</name></author>
	</entry>
	<entry>
		<id>https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Linguist_settings.jpg&amp;diff=25240</id>
		<title>Файл:Linguist settings.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.gis-lab.info/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Linguist_settings.jpg&amp;diff=25240"/>
		<updated>2017-03-13T22:30:08Z</updated>

		<summary type="html">&lt;p&gt;Elf: Screenshot of Linguist settings pop-up window.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Screenshot of Linguist settings pop-up window.&lt;/div&gt;</summary>
		<author><name>Elf</name></author>
	</entry>
</feed>