파이썬 플러그인 개발

파이썬 프로그래밍 언어로 플러그인을 생성할 수 있습니다. C++로 작성된 전통적인 플러그인에 비해 더 쉽게 플러그인을 작성하고, 이해하고, 유지하고 배포할 수 있는데, 이는 파이썬 언어의 동적 특성 덕분입니다.

QGIS 플러그인 관리자가 C++ 플러그인과 파이썬 플러그인의 목록을 모두 보여줍니다. 다음 경로에서 플러그인들을 찾습니다.

  • UNIX/Mac: ~/.qgis2/python/plugins and (qgis_prefix)/share/qgis/python/plugins
  • Windows: ~/.qgis2/python/plugins and (qgis_prefix)/python/plugins

윈도우의 홈 디렉터리(앞에서 ~ 로 표시된)는 보통 C:\Documents and Settings\(user) (윈도우 XP 또는 이전 버전의 경우) 또는 C:\Users\(user) 입니다. QGIS가 파이썬 2.7 버전을 이용하게 된 후부터, 플러그인으로 임포트되려면 파이썬 패키지로 인식되어야 하고, 때문에 이 경로의 하위 디렉터리들은 __init__.py 파일이 있어야 합니다.

주석

기존 디렉터리 경로를 QGIS_PLUGINPATH 에 설정해서, 플러그인 탐색 경로 목록에 이 경로를 추가할 수 있습니다.

개발 과정 :

  1. 발상 : 새 QGIS 플러그인으로 어떤 작업을 하고 싶은지에 대한 생각이 있어야 합니다. 어째서 그 작업을 하는 건가요? 어떤 문제를 해결하고 싶은 건가요? 그 문제를 위한 다른 플러그인이 이미 있는 건 아닌가요?

  2. 파일 생성 : 다음 기술된 파일들을 생성하십시오. 시작점(__init__.py) 생성. 플러그인 메타데이터 (metadata.txt) 작성. 파이썬 플러그인의 주요 본체 파일(mainplugin.py) 생성. Qt 디자이너 폼(form.ui)과 여기에서 사용될 resources.qrc 파일 생성.

  3. 코드 작성 : mainplugin.py 파일에 코드를 작성하십시오.

  4. 테스트 : QGIS를 종료하고 다시 실행한 다음 여러분이 만든 플러그인을 임포트하십시오. 아무 이상이 없는지 확인하세요.

  5. 공개 : QGIS 공식 저장소(repository)에 여러분의 플러그인을 올리거나, 자신만의 “GIS 무기”의 “무기고”로서 여러분 자신의 저장소를 만드십시오.

플러그인 작성

QGIS가 파이썬 플러그인을 지원하기 시작하면서, 수많은 플러그인들이 생겨났습니다. 플러그인 저장소 위키 페이지 에서 그중 일부를 찾아볼 수 있습니다. 여러분은 여기에 올려진 플러그인의 소스를 통해 PyQGIS의 프로그래밍에 대해 더 배우거나, 다른 사람이 했던 고생을 되풀이 하고 있는 것은 아닌지 확인할 수 있습니다. 또한 QGIS 팀에서 공식 파이썬 플러그인 저장소 를 운영하고 있습니다. 플러그인을 개발할 준비는 됐지만 뭘 해야 할지 모르겠다고요? 파이썬 플러그인 아이디어 위키 페이지 에서 PyQGIS 커뮤니티가 원하는 플러그인 기능들을 찾아볼 수 있답니다!

플러그인 파일

다음은 우리가 만들 예시 플러그인의 디렉터리 구조입니다.

PYTHON_PLUGINS_PATH/
  MyPlugin/
    __init__.py    --> *required*
    mainPlugin.py  --> *required*
    metadata.txt   --> *required*
    resources.qrc  --> *likely useful*
    resources.py   --> *compiled version, likely useful*
    form.ui        --> *likely useful*
    form.py        --> *compiled version, likely useful*

이 파일들이 의미하는 바는 다음과 같습니다.

  • __init__.py = 플러그인의 시작점입니다. 이 파일 내부에 classFactory() 메소드는 반드시 있어야 하고, 다른 초기화 코드도 들어갈 수 있습니다.

  • mainPlugin.py = 플러그인의 주요 작업 코드입니다. 이 파일은 플러그인이 수행할 작업에 대한 모든 정보와 주요 코드를 담고 있습니다.

  • resources.qrc = Qt 디자이너가 생성한 .xml 문서입니다. 폼이 사용하는 리소스의 상대 경로를 담고 있습니다.

  • resources.py = 방금 설명한 .qrc 파일을 파이썬으로 번역한 파일입니다.

  • form.ui = Qt 디자이너가 생성한 GUI입니다.

  • form.py = 방금 설명한 form.ui 파일을 파이썬으로 번역한 파일입니다.

  • metadata.txt = Required for QGIS >= 1.8.0. Contains general info, version, name and some other metadata used by plugins website and plugin infrastructure. Since QGIS 2.0 the metadata from __init__.py are not accepted anymore and the metadata.txt is required.

웹페이지 를 통해 온라인 상에서 자동화된 방법으로, 전형적인 QGIS 파이썬 플러그인의 (골격이 되는) 기본 파일들을 생성할 수 있습니다.

또 인터넷 연결 없이도 QGIS에서 플러그인 템플릿을 생성할 수 있는 Plugin Builder 라는 QGIS 플러그인도 있습니다. QGIS 2.0 버전과 호환되는 소스를 생성하므로 이 플러그인을 사용하는 편이 좋습니다.

경고

공식 파이썬 플러그인 저장소 에 플러그인을 업로드할 계획이라면, 여러분의 플러그인이 플러그인 검증 에 필요한 몇 가지 추가 규칙을 따르는지 확인해야 합니다.

플러그인 구성요소

이제 앞에서 설명한 파일 구조 내부의 각 파일들에 어떤 내용을 추가해야 하는 지를 설명하고 예시를 보여 드리겠습니다.

플러그인 메타데이터

플러그인 관리자가 플러그인 명칭, 설명 등등 플러그인에 관한 기본 정보를 검색할 수 있어야 합니다. 이 정보들이 metadata.txt 파일이 이 정보들이 들어가야 할 곳입니다.

중요

모든 메타데이터는 UTF-8로 인코딩이어야 합니다.

메타데이터 명

필수 여부

설명

name

플러그인의 명칭을 담은 짧은 문자열

qgisMinimumVersion

점으로 구분 표기된, 플러그인 구동을 위한 QGIS 최하 버전

qgisMaximumVersion

점으로 구분 표기된, 플러그인 구동을 위한 QGIS 최상 버전

description

플러그인을 설명하는 짧은 텍스트, HTML 사용 불가

about

플러그인을 자세히 설명하는 긴 텍스트, HTML 사용 불가

version

플러그인의 버전을 점으로 구분해 표기한 짧은 문자열

author

작성자 명

email

email of the author, not shown in the QGIS plugin manager or in the website unless by a registered logged in user, so only visible to other plugin authors and plugin website administrators
changelog

문자열이며 줄바꿈 가능, HTML 사용 불가

experimental

실험적인 플러그인인지 여부, True 또는 False

deprecated

중요도가 떨어져 더 이상 사용되지 않고 앞으로는 사라지게 될 플러그인임을 표시, True 또는 False, 업로드된 버전뿐만이 아니라 플러그인의 모든 버전에 적용

tags

검색을 위한 태그. 쉼표로 분리된 목록임, 개별 태그 내부 공백 허용

homepage

플러그인의 홈페이지를 가리키는 유효한 URL

repository

소스 코드 저장소를 가리키는 유효한 URL

tracker

버그 티켓 및 버그 보고 사이트를 가리키는 유효한 URL

icon

a file name or a relative path (relative to the base folder of the plugin’s compressed package) of a web friendly image (PNG, JPEG)
category

플러그인의 범주. 지정된 범주 하위 메뉴로 플러그인이 들어감. Raster, Vector, Database, Web 중의 하나

기본적으로 플러그인은 Plugins 메뉴에 들어가게 되지만 (여러분의 플러그인을 메뉴 항목에 추가하는 방법은 다음 단락에서 설명하겠습니다) Raster, Vector, Database, Web 메뉴에 추가할 수도 있습니다.

메타데이터의 “category” 항목이 플러그인을 어떤 메뉴에 추가할지 설정하는 데 쓰이기 때문에, 이 항목이 플러그인 분류에도 쓰일 수 있습니다. 이 메타데이터 항목이 사용자가 어디에서(어떤 메뉴에서) 플러그인을 찾을 수 있는지 알려주는 역할을 합니다. “category”에 쓸 수 있는 값은 Vector, Raster, Database 또는 Web 4가지입니다. 예를 들어 Raster 메뉴에서 플러그인을 사용할 수 있게 하려면 metadata.txt 에 다음 내용을 추가하십시오.

category=Raster

주석

qgisMaximumVersion 항목이 비어 있으면, 공식 파이썬 플러그인 저장소 에 업로드 시 자동적으로 현재 QGIS 메인 버전에 .99 를 더한 값으로 설정됩니다.

다음은 metadata.txt 파일의 예시입니다.

; the next section is mandatory

[general]
name=HelloWorld
[email protected]
author=Just Me
qgisMinimumVersion=2.0
description=This is an example plugin for greeting the world.
    Multiline is allowed:
    lines starting with spaces belong to the same
    field, in this case to the "description" field.
    HTML formatting is not allowed.
about=This paragraph can contain a detailed description
    of the plugin. Multiline is allowed, HTML is not.
version=version 1.2
tracker=http://bugs.itopen.it
repository=http://www.itopen.it/repo
; end of mandatory metadata

; start of optional metadata
category=Raster
changelog=The changelog lists the plugin versions
    and their changes as in the example below:
    1.0 - First stable release
    0.9 - All features implemented
    0.8 - First testing release

; Tags are in comma separated value format, spaces are allowed within the
; tag name.
; Tags should be in English language. Please also check for existing tags and
; synonyms before creating a new one.
tags=wkt,raster,hello world

; these metadata can be empty, they will eventually become mandatory.
homepage=http://www.itopen.it
icon=icon.png

; experimental flag (applies to the single version)
experimental=True

; deprecated flag (applies to the whole plugin and not only to the uploaded version)
deprecated=False

; if empty, it will be automatically set to major version + .99
qgisMaximumVersion=2.0

__init__.py

이 파일은 파이썬의 임포트 체계에서 필요로 합니다. 또한, QGIS는 이 파일 내부에 QGIS가 플러그인을 불러올 때 호출되는 classFactory() 함수가 들어 있을 것을 요구합니다. 이 함수는 QgisInterface 클래스 인스턴스의 참조값을 받아서 mainplugin.py 파일에 있는 플러그인 클래스의 인스턴스를 반환해야만 합니다. 본 예시에서는 TestPlugin 이라는 이름이군요(다음 코드를 보세요). __init__.py 파일에는 다음과 같은 내용이 들어갑니다.

def classFactory(iface):
  from mainPlugin import TestPlugin
  return TestPlugin(iface)

## any other initialisation needed

mainPlugin.py

이 파일이 실제 작업을 수행하는 파일이며, 다음과 같은 (예시: mainPlugin.py) 내용을 담고 있습니다.

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *

# initialize Qt resources from file resources.py
import resources

class TestPlugin:

  def __init__(self, iface):
    # save reference to the QGIS interface
    self.iface = iface

  def initGui(self):
    # create action that will start plugin configuration
    self.action = QAction(QIcon(":/plugins/testplug/icon.png"), "Test plugin", self.iface.mainWindow())
    self.action.setObjectName("testAction")
    self.action.setWhatsThis("Configuration for test plugin")
    self.action.setStatusTip("This is status tip")
    QObject.connect(self.action, SIGNAL("triggered()"), self.run)

    # add toolbar button and menu item
    self.iface.addToolBarIcon(self.action)
    self.iface.addPluginToMenu("&Test plugins", self.action)

    # connect to signal renderComplete which is emitted when canvas
    # rendering is done
    QObject.connect(self.iface.mapCanvas(), SIGNAL("renderComplete(QPainter *)"), self.renderTest)

  def unload(self):
    # remove the plugin menu item and icon
    self.iface.removePluginMenu("&Test plugins", self.action)
    self.iface.removeToolBarIcon(self.action)

    # disconnect form signal of the canvas
    QObject.disconnect(self.iface.mapCanvas(), SIGNAL("renderComplete(QPainter *)"), self.renderTest)

  def run(self):
    # create and show a configuration dialog or something similar
    print "TestPlugin: run called!"

  def renderTest(self, painter):
    # use painter for drawing to map canvas
    print "TestPlugin: renderTest called!"

플러그인의 메인 소스 파일(예를 들어 mainPlugin.py) 안에 다음과 같은 플러그인 함수들이 반드시 들어가야 합니다.

  • __init__ –> QGIS 인터페이스에 접근할 수 있게 해줍니다.

  • initGui() –> 플러그인이 로드될 때 호출됩니다.

  • unload() –> 플러그인이 언로드될 때 호출됩니다.

앞의 예시 코드에서 볼 수 있듯이, addPluginToMenu() 함수가 쓰이고 있습니다. 이 함수가 Plugins 메뉴에 플러그인과 연결되는 메뉴 액션을 추가할 것입니다. 다른 메뉴에 액션을 추가하는 유사 메소드도 있습니다. 다음은 그 메소드들의 목록입니다.

  • addPluginToRasterMenu()
  • addPluginToVectorMenu()
  • addPluginToDatabaseMenu()
  • addPluginToWebMenu()

이들은 모두 addPluginToMenu() 메소드와 동일한 문법을 따릅니다.

플러그인 항목을 구성하는 방법의 일관성을 유지하려면, 여러분의 플러그인 메뉴를 이런 미리 정의된 메소드를 이용해 추가하는 편이 좋습니다. 하지만, 여러분이 임으로 만든 메뉴 그룹을 다음 예시에서와 같이 직접 메뉴 바에 추가할 수도 있습니다.

def initGui(self):
    self.menu = QMenu(self.iface.mainWindow())
    self.menu.setObjectName("testMenu")
    self.menu.setTitle("MyMenu")

    self.action = QAction(QIcon(":/plugins/testplug/icon.png"), "Test plugin", self.iface.mainWindow())
    self.action.setObjectName("testAction")
    self.action.setWhatsThis("Configuration for test plugin")
    self.action.setStatusTip("This is status tip")
    QObject.connect(self.action, SIGNAL("triggered()"), self.run)
    self.menu.addAction(self.action)

    menuBar = self.iface.mainWindow().menuBar()
    menuBar.insertMenu(self.iface.firstRightStandardMenu().menuAction(), self.menu)

def unload(self):
    self.menu.deleteLater()

메뉴와 툴바의 사용자 지정 기능을 이용할 수 있도록, QActionQMenu 클래스의 objectName 을 플러그인의 고유한 명칭으로 설정하는 일을 잊지 마십시오.

리소스 파일

앞의 예시 코드에서 initGui() 함수를 보면 리소스 파일(이 경우 파일명 resources.qrc)에 있는 아이콘을 사용했다는 사실을 알 수 있습니다.

<RCC>
  <qresource prefix="/plugins/testplug" >
     <file>icon.png</file>
  </qresource>
</RCC>

It is good to use a prefix that will not collide with other plugins or any parts of QGIS, otherwise you might get resources you did not want. Now you just need to generate a Python file that will contain the resources. It’s done with pyrcc4 command:

pyrcc4 -o resources.py resources.qrc

주석

In Windows environments, attempting to run the pyrcc4 from Command Prompt or Powershell will probably result in the error “Windows cannot access the specified device, path, or file [...]”. The easiest solution is probably to use the OSGeo4W Shell but if you are comfortable modifying the PATH environment variable or specifiying the path to the executable explicitly you should be able to find it at <Your QGIS Install Directory>\bin\pyrcc4.exe.

이게 전부입니다... 복잡할 게 없죠. ^_____^

이 모든 과정을 정확히 작업했다면 플러그인 관리자가 아무 문제 없이 여러분의 플러그인을 찾아 불러올 것입니다. 그리고, 툴바 아이콘 또는 적당한 메뉴 항목을 선택하면 콘솔에 메시지가 보일 것입니다.

실제 플러그인 작업 시에는 다른 (작업용) 디렉터리에서 플러그인을 개발하고 UI 및 리소스 파일을 생성할 makefile을 작성한 다음, 그 결과물을 QGIS의 플러그인 폴더에 설치하는 것이 좋습니다.

문서화

플러그인을 위한 문서는 HTML 도움말 파일로 만들 수 있습니다. 이 파일로 다른 QGIS 도움말과 마찬가지로 도움말을 제공하는 방법을 qgis.utils 모듈의 showPluginHelp() 함수가 제공합니다.

The showPluginHelp() function looks for help files in the same directory as the calling module. It will look for, in turn, index-ll_cc.html, index-ll.html, index-en.html, index-en_us.html and index.html, displaying whichever it finds first. Here ll_cc is the QGIS locale. This allows multiple translations of the documentation to be included with the plugin.

또한 showPluginHelp() 함수는 도움말이 보여질 특정 플러그인을 지정하는 packageName 파라미터, 탐색의 대상이 될 파일명의 “index” 부분을 대체할 수 있는 filename 파라미터, 그리고 웹브라우저에서 문서의 어느 부분을 보여줄 것인지 지정하는 HTML 앵커 태그(anchor tag)의 명칭인 section 파라미터를 사용할 수 있습니다.

Translation

With a few steps you can set up the environment for the plugin localization so that depending on the locale settings of your computer the plugin will be loaded in different languages.

Software requirements

The easiest way to create and manage all the translation files is to install Qt Linguist. In a Linux like environment you can install it typing:

sudo apt-get install qt4-dev-tools

Files and directory

When you create the plugin you will find the i18n folder within the main plugin directory.

All the translation files have to be within this directory.

.pro file

First you should create a .pro file, that is a project file that can be managed by Qt Linguist.

In this .pro file you have to specify all the files and forms you want to translate. This file is used to set up the localization files and variables. An example of the pro file is:

FORMS = ../ui/*

SOURCES = ../your_plugin.py

TRANSLATIONS = your_plugin_it.ts

In this particular case all your UIs are placed in the ../ui folder and you want to translate all of them.

Furthermore, the your_plugin.py file is the file that calls all the menu and sub-menus of your plugin in the QGIS toolbar and you want to translate them all.

Finally with the TRANSLATIONS variable you can specify the translation languages you want.

경고

Be sure to name the ts file like your_plugin_ + language + .ts otherwise the language loading will fail! Use 2 letters shortcut for the language (it for Italian, de for German, etc...)

.ts file

Once you have created the .pro you are ready to generate the .ts file(s) of the language(s) of your plugin.

Open a terminal, go to your_plugin/i18n directory and type:

lupdate your_plugin.pro

you should see the your_plugin_language.ts file(s).

Open the .ts file with Qt Linguist and start to translate.

.qm file

When you finish to translate your plugin (if some strings are not completed the source language for those strings will be used) you have to create the .qm file (the compiled .ts file that will be used by QGIS).

Just open a terminal cd in your_plugin/i18n directory and type:

lrelease your_plugin.ts

now, in the i18n directory you will see the your_plugin.qm file(s).

Load the plugin

In order to see the translation of your plugin just open QGIS, change the language (Settings ‣ Options ‣ Language) and restart QGIS.

You should see your plugin in the correct language.

경고

If you change something in your plugin (new UIs, new menu, etc..) you have to generate again the update version of both .ts and .qm file, so run again the command of above.