중요

번역은 여러분이 참여할 수 있는 커뮤니티 활동입니다. 이 페이지는 현재 100.00% 번역되었습니다.

16.1. 파이썬 플러그인 구성하기

플러그인을 생성하기 위한 주요 단계는 다음과 같습니다:

  1. 아이디어: 새로운 QGIS 플러그인으로 무엇을 하고 싶은지에 대한 아이디어를 떠올립니다.

  2. 준비(setup): 여러분의 플러그인을 위한 파일들을 생성합니다. 플러그인 유형에 따라, 몇몇 파일은 필수인 반면 몇몇 파일은 선택적입니다.

  3. 개발: 알맞은 파일에 코드를 작성합니다.

  4. 문서화: 플러그인 문서를 작성합니다.

  5. 선택적으로 번역: 여러분의 플러그인을 다른 언어로 번역합니다.

  6. 테스트: 모든 것이 괜찮은지 확인하기 위해 여러분의 플러그인을 다시 불러옵니다.

  7. 공개(publish): QGIS 저장소에 여러분의 플러그인을 공개하거나, 또는 개인적인 “GIS 무기”의 “병기고”로써 여러분 자신의 저장소를 만드십시오.

16.1.1. 시작하기

새 플러그인을 작성하기 전에, 공식 파이썬 플러그인 저장소 를 살펴보십시오. 기존 플러그인들의 소스 코드를 연구하면 프로그래밍에 대해 더 많은 것을 배울 수 있습니다. 비슷한 플러그인이 이미 존재하는지 찾아볼 수도 있고, 존재한다면 기존 플러그인을 확장하거나 또는 적어도 기존 플러그인을 바탕으로 여러분 자신의 플러그인을 작성할 수도 있습니다.

16.1.1.1. 플러그인 파일 구조 준비하기

새 플러그인을 시작하려면, 필요한 플러그인 파일들을 준비해야 합니다.

플러그인 준비를 도와줄 수 있는 플러그인 템플릿 리소스가 2개 있습니다:

  • 교육 목적인 경우 또는 미니멀리스트 접근법이 바람직할 때마다, 최소 플러그인 템플릿 이 무결한 QGIS 파이썬 플러그인을 생성하는 데 필요한 기본 (최소한의) 파일들을 제공합니다.

  • 좀 더 완전한 기능 플러그인 템플릿이 필요한 경우, 플러그인 작성자 가 현지화(번역) 및 테스트 작업 같은 기능들을 포함하는 서로 다른 여러 플러그인 유형들을 위한 템플릿들을 생성할 수 있습니다.

전형적인 플러그인 디렉터리는 다음 파일들을 포함합니다:

  • metadata.txt - 필수 - 플러그인 웹사이트와 플러그인 인프라스트럭처에서 사용하는 일반 정보, 버전, 이름, 그리고 몇몇 기타 메타데이터를 담고 있습니다.

  • __init__.py - 필수 - 플러그인의 시작점입니다. 이 파일은 classFactory() 메소드를 가지고 있어야 하며, 다른 초기 설정 코드를 가지고 있을 수도 있습니다.

  • mainPlugin.py - 핵심 코드 - 플러그인의 주요 작업 코드입니다. 플러그인과 주요 코드의 액션에 대한 모든 정보를 담고 있습니다.

  • form.ui - 사용자 정의 GUI를 가진 플러그인 용 - Qt 설계자가 생성한 GUI입니다.

  • form.py - 컴파일된 GUI - 앞에서 설명한 form.ui 를 파이썬으로 번역한 파일입니다.

  • resources.qrc - 선택적 - Qt 설계자가 생성한 .xml 문서입니다. GUI 양식에 쓰이는 리소스들을 가리키는 상대 경로를 담고 있습니다.

  • resources.py - 컴파일된 리소스, 선택적 - 앞에서 설명한 resources.qrc 를 파이썬으로 번역한 파일입니다.

경고

공식 파이썬 플러그인 저장소 에 플러그인을 업로드할 계획이 있다면 여러분의 플러그인이 플러그인 무결성 검증 에 필수적인 몇몇 추가 규칙들을 따르는지 반드시 확인해야만 합니다.

16.1.2. 플러그인 코드 작성하기

다음은 앞에서 소개한 파일들 각각에 어떤 내용을 추가해야 하는지를 설명합니다.

16.1.2.1. metadata.txt

먼저, 플러그인 관리자는 플러그인의 이름, 설명 등등과 같은 플러그인에 대한 몇몇 기본 정보를 검색해야 합니다. metadata.txt 파일에 이 정보들을 저장합니다.

참고

모든 메타데이터는 반드시 UTF-8으로 인코딩되어 있어야만 합니다.

메타데이터 이름

필수 여부

설명

name

플러그인의 이름을 담고 있는 짧은 문자열

qgisMinimumVersion

최저 QGIS 버전의 닷 데시멀 노테이션

qgisMaximumVersion

최고 QGIS 버전의 닷 데시멀 노테이션

description

플러그인을 설명하는 짧은 텍스트, HTML은 허용되지 않습니다

about

플러그인을 자세히 설명하는 좀 더 긴 텍스트, HTML은 허용되지 않습니다

version

버전의 닷 데시멀 노테이션을 담고 있는 짧은 문자열

author

개발자 이름

email

개발자의 이메일 주소, 웹사이트에서는 로그인한 사용자에게만 보이지만 플러그인을 설치했다면 플러그인 관리자에서 볼 수 있습니다

changelog

문자열, 여러 줄일 수 있지만 HTML은 허용되지 않습니다

experimental

불(boolean) 플래그, True 또는 False - 이 버전이 실험적 버전인 경우 True

deprecated

불(boolean) 플래그, True 또는 False - 업로드된 버전만이 아니라 전체 플러그인에 적용됩니다

tags

쉼표로 구분된 목록, 개별 태그 안에 공백이 허용됩니다

homepage

사용자 플러그인의 홈페이지를 가리키는 무결한 URL

repository

소스 코드 저장소를 가리키는 무결한 URL

tracker

티켓 및 버그 보고서를 가리키는 무결한 URL

icon

웹 친화적인 이미지(PNG, JPEG)의 파일 이름 또는 (플러그인 압축 패키지의 기반 폴더를 기준으로 하는) 상대 경로

category

Raster, Vector, Database, MeshWeb 가운데 하나

plugin_dependencies

PIP처럼 설치할 다른 플러그인들을 쉼표로 구분한 목록, 플러그인들의 메타데이터의 이름 필드에서 나오는 플러그인 이름들을 사용합니다

server

불(boolean) 플래그, True 또는 False - 플러그인이 서버 인터페이스를 가지고 있는지 여부를 결정합니다

hasProcessingProvider

불(boolean) 플래그, True 또는 False - 플러그인이 공간 처리 알고리즘을 제공하는지 여부를 결정합니다

플러그인은 기본적으로 Plugins 메뉴에 배치되지만 (다음 부분에서 여러분의 플러그인에 대한 메뉴 항목을 추가하는 방법을 배울 것입니다) Raster, Vector, Database, Mesh, 그리고 Web 메뉴에도 배치할 수 있습니다.

이를 지정하기 위한 해당 “category” 메타데이터 항목이 존재하기 때문에, 이에 맞춰 플러그인을 분류할 수 있습니다. 이 메타데이터 항목을 사용자를 위한 도움말처럼 사용해서 어디에서 (어떤 메뉴에서) 플러그인을 찾을 수 있는지 알려줄 수 있습니다. “category”에 사용할 수 있는 값은 Vector, Raster, Database, Mesh 또는 Web 가운데 하나입니다. 예를 들어 Raster 메뉴에서 여러분의 플러그인을 사용할 수 있게 하려면, metadata.txt 에 이를 추가하십시오.

category=Raster

참고

“qgisMaximumVersion”이 비어 있는 경우, 공식 파이썬 플러그인 저장소 에 업로드할 때 자동적으로 주요 버전에 .99 를 더한 값으로 설정될 것입니다.

metadata.txt 의 예시:

; the next section is mandatory

[general]
name=HelloWorld
email=me@example.com
author=Just Me
qgisMinimumVersion=3.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=https://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=3.99

; Since QGIS 3.8, a comma separated list of plugins to be installed
; (or upgraded) can be specified.
; The example below will try to install (or upgrade) "MyOtherPlugin" version 1.12
; and any version of "YetAnotherPlugin".
; Both "MyOtherPlugin" and "YetAnotherPlugin" names come from their own metadata's
; name field
plugin_dependencies=MyOtherPlugin==1.12,YetAnotherPlugin

16.1.2.2. __init__.py

파이썬의 가져오기 시스템이 이 파일을 필요로 합니다. 또 QGIS도 이 파일이 classFactory() 함수를 담고 있을 것을 요구합니다. 이 함수는 QGIS에 플러그인을 불러왔을 때 호출되어, QgisInterface 클래스의 인스턴스를 받아서 mainplugin.py 파일로부터 플러그인의 클래스 객체를 반환해야만 합니다 — 이 경우 TestPlugin 이라는 플러그인입니다. (다음을 참조하세요.) __init__.py 의 내용은 다음과 같이 보여야 합니다:

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

# any other initialisation needed

16.1.2.3. mainPlugin.py

이 파일에서 마법이 벌어지는데, 이 마법은 다음과 같이 보일 것입니다: (mainPlugin.py 파일의 예시)

from qgis.PyQt.QtGui import *
from qgis.PyQt.QtWidgets import *

# initialize Qt resources from file resources.py
from . 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("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")
    self.action.triggered.connect(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
    self.iface.mapCanvas().renderComplete.connect(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
    self.iface.mapCanvas().renderComplete.disconnect(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 메뉴에 해당 메뉴 액션을 추가할 것입니다. 다른 메뉴에 액션을 추가하는 대체 메소드들이 존재합니다. 다음은 대체 메소드 목록입니다:

이 대체 메소드들은 모두 addPluginToMenu() 메소드와 동일한 문법(syntax)을 사용합니다.

플러그인 항목들을 정리하는 방식의 일관성을 유지하기 위해 이 사전 정의 메소드들 가운데 하나에 여러분의 플러그인 메뉴를 추가할 것을 권장합니다. 하지만, 다음 예시에서처럼 여러분이 메뉴 바에 사용자 정의 메뉴 그룹을 직접 추가할 수도 있습니다:

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

    self.action = QAction(QIcon("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")
    self.action.triggered.connect(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()

여러분의 플러그인에 QActionQMenuobjectName 을 특정 이름으로 설정해서 사용자 정의할 수 있도록 만드는 일을 잊지 마십시오.

사용자 정의 메뉴에 도움말(help) 및 정보(about) 액션도 추가할 수 있지만, 이 액션들을 사용할 수 있게 해주는 편리한 장소는 QGIS의 Help ► Plugins 메뉴입니다. pluginHelpMenu() 메소드를 사용하면 됩니다.

def initGui(self):

    self.help_action = QAction(
        QIcon("testplug:icon.png"),
        self.tr("Test Plugin..."),
        self.iface.mainWindow()
    )
    # Add the action to the Help menu
    self.iface.pluginHelpMenu().addAction(self.help_action)

    self.help_action.triggered.connect(self.show_help)

@staticmethod
def show_help():
    """ Open the online help. """
    QDesktopServices.openUrl(QUrl('https://docs.qgis.org'))

def unload(self):

    self.iface.pluginHelpMenu().removeAction(self.help_action)
    del self.help_action

실제 플러그인을 작업하는 경우 또다른 (작업) 디렉터리에 플러그인을 작성하고, UI와 리소스 파일을 생성할 makefile 을 생성해서 QGIS 설치본에 플러그인을 설치하는 편이 좋습니다.

16.1.3. 플러그인 문서화하기

플러그인에 대한 문서는 HTML 도움말 파일로 작성할 수 있습니다. qgis.utils 모듈이 다른 QGIS 도움말과 동일한 방식으로 도움말 파일 탐색기를 여는 showPluginHelp() 함수를 제공합니다.

showPluginHelp() 함수는 호출한 모듈과 동일한 디렉터리에서 도움말 파일을 검색합니다. 이 함수는 index-ll_cc.html, index-ll.html, index-en.html, index-en_us.html, 그리고 index.html 순서대로 파일을 검색해서 첫 번째로 찾은 파일을 표시합니다. 이때 ll_cc 는 QGIS 로케일로, 플러그인에 문서를 여러 언어로 번역한 파일들을 포함시킬 수 있게 해줍니다.

showPluginHelp() 함수는 도움말이 표시될 특정 플러그인을 식별하는 packageName 파라미터, 검색 중인 파일들의 이름에서 “index”를 대체할 수 있는 filename 파라미터, 그리고 문서 안에서 탐색기가 배치될 위치를 결정하는 HTML 앵커 태그의 이름인 section 파라미터도 받을 수 있습니다.

16.1.4. 플러그인 번역하기

몇 단계만 거치면 여러분의 컴퓨터의 로케일 설정에 따라 플러그인을 서로 다른 언어들로 불러오게 만들 플러그인 현지화를 위한 환경을 준비할 수 있습니다.

16.1.4.1. 소프트웨어 요구 사항

모든 번역 파일들을 생성하고 관리할 수 있는 가장 쉬운 방법은 Qt Linguist 를 설치하는 것입니다. 데비안 기반 GNU/리눅스 환경에서는 다음과 같이 입력해서 설치할 수 있습니다:

sudo apt install qttools5-dev-tools

16.1.4.2. 파일과 디렉터리

플러그인을 생성했을 때 주 플러그인 디렉터리 안에 i18n 폴더가 있을 것입니다.

모든 번역 파일은 이 디렉터리 안에 있어야 합니다.

16.1.4.2.1. .pro 파일

먼저 Qt Linguist 가 관리할 수 있는 프로젝트 파일인 .pro 파일을 생성해야 합니다.

.pro 파일에 번역하고자 하는 모든 파일과 양식을 지정해야 합니다. 이 파일은 현지화 파일들과 변수들을 준비하는 데 쓰입니다. 다음은 예제 플러그인 의 구성과 일치하는 프로젝트 파일의 예시입니다:

FORMS = ../form.ui
SOURCES = ../your_plugin.py
TRANSLATIONS = your_plugin_it.ts

여러분의 플러그인이 좀 더 복잡한 구성을 따를 수도 있고, 파일 여러 개로 배포될 수도 있습니다. 이런 경우, .pro 파일을 읽고 번역할 수 있는 문자열을 업데이트하는 데 사용하는 pylupdate5 프로그램이 와일드카드 문자들을 지원하지 않기 때문에 .pro 파일에 모든 파일을 명확하게 배치해야 한다는 사실을 기억하십시오. 이때 프로젝트 파일은 다음과 같이 보일 수도 있습니다:

FORMS = ../ui/about.ui ../ui/feedback.ui \
        ../ui/main_dialog.ui
SOURCES = ../your_plugin.py ../computation.py \
          ../utils.py

이에 더해, your_plugin.py 파일이 QGIS 툴바에서 플러그인의 모든 메뉴와 하위 메뉴를 호출하는 파일이기 때문에, 이들도 전부 번역해야 합니다.

마지막으로 TRANSLATIONS 변수를 사용해서 원하는 번역 언어를 지정할 수 있습니다.

경고

.ts 파일의 이름을 your_plugin_ + language + .ts 형식으로 붙여야 한다는 사실을 기억하십시오. 그러지 않으면 언어를 불러오지 못할 것입니다! 언어의 2문자 단축 이름을 (이탈리아어의 경우 it, 독일어의 경우 de, …) 사용하십시오.

16.1.4.2.2. .ts 파일

.pro 파일을 생성하고 나면 플러그인의 언어(들)를 위한 .ts 파일(들)을 생성할 준비가 된 것입니다.

터미널을 열고, your_plugin/i18n 디렉터리로 가서 다음을 입력하십시오:

pylupdate5 your_plugin.pro

your_plugin_language.ts 파일(들)을 볼 수 있을 것입니다.

Qt Linguist.ts 파일을 열고 번역을 시작하십시오.

16.1.4.2.3. .qm 파일

플러그인 번역을 끝내고 나면 (번역이 완료되지 않은 일부 문자열의 경우 해당 문자열의 소스 언어를 사용할 것입니다) .qm 파일을 생성해야 합니다. (QGIS가 사용하게 될, 컴파일된 .ts 파일입니다.)

터미널을 열고, your_plugin/i18n 디렉터리로 가서 다음을 입력하십시오:

lrelease your_plugin.ts

이제 i18n 디렉터리 안에서 your_plugin.qm 파일(들)을 볼 수 있을 것입니다.

16.1.4.3. Makefile을 사용해서 번역하기

다른 방법으로는 여러분이 플러그인 작성자를 사용해서 플러그인을 생성한 경우, 파이썬 코드와 Qt 대화창으로부터 메시지를 makefile 을 사용해서 추출할 수 있습니다. Makefile의 첫머리에 LOCALES 변수가 있습니다:

LOCALES = en

이 변수에 언어의 단축 이름을 추가하십시오. 예를 들어 헝가리어를 추가한다면:

LOCALES = en hu

이제 다음 명령어를 실행하면 소스로부터 (en.ts 파일은 물론) hu.ts 파일을 생성하거나 업데이트할 수 있습니다:

make transup

이 명령어를 실행하고 나면 LOCALES 변수에 설정된 모든 언어에 대한 .ts 파일이 업데이트됩니다. Qt Linguist 를 사용해서 프로그램 메시지를 번역하십시오. 번역을 완료하면 transcompile.qm 파일을 생성할 수 있습니다:

make transcompile

.ts 파일을 여러분의 플러그인과 함께 배포해야 합니다.

16.1.4.4. 플러그인 불러오기

플러그인의 번역을 보려면, QGIS를 열어서 언어를 변경한 다음 (Settings ► Options ► General) QGIS를 다시 시작하십시오.

여러분의 플러그인을 정확한 언어로 보게 될 것입니다.

경고

플러그인에서 무언가를 (새로운 UI, 새로운 메뉴 등등) 변경하는 경우 .ts.qm 파일 둘 다 업데이트 버전을 다시 생성 해야 하기 때문에, 앞의 명령어를 다시 실행하십시오.

16.1.5. 사용자 플러그인 공유하기

QGIS는 플러그인 저장소에 수백 개의 플러그인을 호스팅하고 있습니다. 여러분의 플러그인을 공유해보십시오! 그러면 QGIS의 가능성이 확장되는 것은 물론 사람들이 여러분의 코드로부터 배울 수 있을 것입니다. QGIS에서 호스팅하고 있는 모든 플러그인을 플러그인 관리자를 통해 검색하고 설치할 수 있습니다.

plugins.qgis.org 에서 관련 정보와 요구 사항을 찾아볼 수 있습니다.

16.1.6. 도움말 및 꼼수

16.1.6.1. 플러그인 다시 불러오기

여러분이 플러그인을 개발하는 동안 테스트를 위해 QGIS에 플러그인을 자주 다시 불러와야 할 것입니다. 이때 플러그인 다시 불러오기(Plugin Reloader) 플러그인을 사용하면 플러그인을 매우 쉽게 다시 불러올 수 있습니다. 이 플러그인은 플러그인 관리자 를 통해 찾을 수 있습니다.

16.1.6.2. qgis-plugin-ci를 사용한 자동 패키지 작업, 배포 및 번역

qgis-plugin-ci 는 여러분의 컴퓨터에서 QGIS 플러그인을 자동으로 패키징하고 배포하기 위한, 또 GitHub 워크플로 또는 Gitlab-CI 같은 지속적 통합(continuous integration)을 사용하기 위한, 그리고 번역을 위해 Transifex 를 사용하기 위한 명령줄 인터페이스를 제공합니다.

이 파이썬 프로그램은 CLI(명령 줄 인터페이스)를 통해 또는 CI(지속적 통합)에서의 액션으로 XML 플러그인 저장소 파일을 배포하고, 번역하고, 공개하고, 또는 생성할 수 있게 해줍니다.

16.1.6.3. 플러그인에 접근하기

QGIS 안에서, 설치된 플러그인의 모든 클래스에 접근할 수 있습니다. 디버그 작업을 수행하는 경우에 편리합니다.

my_plugin = qgis.utils.plugins['My Plugin']

16.1.6.4. 로그 메시지

로그 메시지 패널 안에 플러그인 전용 탭이 있습니다.

16.1.6.5. 리소스 파일

일부 플러그인은 리소스 파일을 사용합니다. 예를 들어 resources.qrc 파일은 아이콘 같은 GUI 용 리소스를 정의합니다:

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

다른 플러그인들 또는 QGIS의 어떤 부분과도 충돌하지 않을 접두어를 사용하는 편이 좋습니다. 그러지 않으면 원하지 않는 리소스를 얻게 될 수도 있습니다. 이제 리소스를 담게 될 파이썬 파일을 pyrcc5 명령어를 사용해서 생성해야 합니다:

pyrcc5 -o resources.py resources.qrc

참고

윈도우 환경에서 명령 프롬프트 또는 파워셸에서 pyrcc5 를 실행하려 하면 아마도 “지정한 장치, 경로 또는 파일에 액세스할 수 없습니다. […]” 오류가 발생할 것입니다. 가장 쉬운 해결책은 OSGeo4W 셸을 사용하는 것일 테지만, 여러분이 PATH 환경 변수를 수정하는 데 또는 실행 파일을 명확하게 가리키는 경로를 지정하는 데 익숙하다면 그 실행 파일은 <QGIS 설치 디렉터리>\bin\pyrcc5.exe 입니다.