16.2. コードスニペット

ヒント

pyqgisコンソールを使わない場合、このページにあるコードスニペットは次のインポートが必要です:

 1from qgis.core import (
 2    QgsProject,
 3    QgsApplication,
 4    QgsMapLayer,
 5)
 6
 7from qgis.gui import (
 8    QgsGui,
 9    QgsOptionsWidgetFactory,
10    QgsOptionsPageWidget,
11    QgsLayerTreeEmbeddedWidgetProvider,
12    QgsLayerTreeEmbeddedWidgetRegistry,
13)
14
15from qgis.PyQt.QtCore import Qt
16from qgis.PyQt.QtWidgets import (
17    QMessageBox,
18    QAction,
19    QHBoxLayout,
20    QComboBox,
21)
22from qgis.PyQt.QtGui import QIcon

このセクションでは、プラグイン開発を容易にするコードスニペットを紹介します。

16.2.1. ショートカットキーでメソッドを呼び出す方法

プラグインに initGui() に追加します

self.key_action = QAction("Test Plugin", self.iface.mainWindow())
self.iface.registerMainWindowAction(self.key_action, "Ctrl+I")  # action triggered by Ctrl+I
self.iface.addPluginToMenu("&Test plugins", self.key_action)
self.key_action.triggered.connect(self.key_action_triggered)

unload() に追加します

self.iface.unregisterMainWindowAction(self.key_action)

CTRL+Iが押されたときに呼び出されるメソッド

def key_action_triggered(self):
  QMessageBox.information(self.iface.mainWindow(),"Ok", "You pressed Ctrl+I")

また、提供されたアクションのショートカットキーをユーザーがカスタマイズできるようにすることも可能です。これをするには次を加えます:

1# in the initGui() function
2QgsGui.shortcutsManager().registerAction(self.key_action)
3
4# and in the unload() function
5QgsGui.shortcutsManager().unregisterAction(self.key_action)

16.2.2. QGISアイコンを再利用する方法

QGISのアイコンはよく知られており、ユーザーに明確なメッセージを伝えることができるため、新しいアイコンを描画して設定する代わりに、プラグイン内でQGISのアイコンを再利用したい場合があります。その場合は getThemeIcon() メソッドを使用してください。

例えば、QGISコードリポジトリで入手できる fileOpen mActionFileOpen.svg アイコンを再利用するには:

1# e.g. somewhere in the initGui
2self.file_open_action = QAction(
3    QgsApplication.getThemeIcon("/mActionFileOpen.svg"),
4    self.tr("Select a File..."),
5    self.iface.mainWindow()
6)
7self.iface.addPluginToMenu("MyPlugin", self.file_open_action)

iconPath() はQGISアイコンを呼び出すもう一つの方法です。テーマアイコンの呼び出しの例は QGIS embedded images - Cheatsheet にあります。

16.2.3. オプションダイアログのプラグインのインタフェース

設定 ► オプション にカスタムプラグインオプションタブを追加することができます。QGISアプリケーションの設定とプラグインの設定を1つの場所にまとめておくことで、ユーザーが発見しやすく誘導しやすくなるので、プラグインのオプションのために特定のメインメニュー項目を追加するよりも望ましい方法です。

以下のスニペットは、プラグインの設定のための新しい空白のタブを追加し、あなたのプラグインに固有のすべてのオプションと設定を入力できるようにします。以下のクラスを別のファイルに分割することができます。この例では、2つのクラスをメインの mainPlugin.py ファイルに追加しています。

 1class MyPluginOptionsFactory(QgsOptionsWidgetFactory):
 2
 3    def __init__(self):
 4        super().__init__()
 5
 6    def icon(self):
 7        return QIcon('icons/my_plugin_icon.svg')
 8
 9    def createWidget(self, parent):
10        return ConfigOptionsPage(parent)
11
12
13class ConfigOptionsPage(QgsOptionsPageWidget):
14
15    def __init__(self, parent):
16        super().__init__(parent)
17        layout = QHBoxLayout()
18        layout.setContentsMargins(0, 0, 0, 0)
19        self.setLayout(layout)

最後に、インポートを追加して __init__ 関数を修正します:

 1from qgis.PyQt.QtWidgets import QHBoxLayout
 2from qgis.gui import QgsOptionsWidgetFactory, QgsOptionsPageWidget
 3
 4
 5class MyPlugin:
 6    """QGIS Plugin Implementation."""
 7
 8    def __init__(self, iface):
 9        """Constructor.
10
11        :param iface: An interface instance that will be passed to this class
12            which provides the hook by which you can manipulate the QGIS
13            application at run time.
14        :type iface: QgsInterface
15        """
16        # Save reference to the QGIS interface
17        self.iface = iface
18
19
20    def initGui(self):
21        self.options_factory = MyPluginOptionsFactory()
22        self.options_factory.setTitle(self.tr('My Plugin'))
23        iface.registerOptionsWidgetFactory(self.options_factory)
24
25    def unload(self):
26        iface.unregisterOptionsWidgetFactory(self.options_factory)

Tip

レイヤプロパティダイアログにカスタムタブを追加する

レイヤプロパティダイアログにプラグインのカスタムオプションを追加するには、同様のロジックを適用して、クラス QgsMapLayerConfigWidgetFactoryQgsMapLayerConfigWidget を使うことができます。

16.2.4. レイヤツリーにレイヤのカスタムウィジェットを埋め込む

レイヤ パネルでレイヤエントリの隣や下に表示される通常のレイヤシンボロジの要素の他に、独自のウィジェットを追加することができ、レイヤでよく使用されるいくつかのアクションに素早くアクセスすることができます(フィルタリング、選択、スタイルの設定、ボタンウィジェットによるレイヤの更新、レイヤ型のタイムスライダーの作成、ラベルでの追加のレイヤ情報の表示...など)。これらの レイヤツリー埋め込みウィジェット は、個々のレイヤのプロパティ 凡例 タブから利用できます。

次のコードスニペットは、レイヤに利用可能なレイヤスタイルを表示するドロップダウンを凡例に作成し、異なるレイヤースタイルを素早く切り替えられるようにします。

 1class LayerStyleComboBox(QComboBox):
 2    def __init__(self, layer):
 3        QComboBox.__init__(self)
 4        self.layer = layer
 5        for style_name in layer.styleManager().styles():
 6            self.addItem(style_name)
 7
 8        idx = self.findText(layer.styleManager().currentStyle())
 9        if idx != -1:
10          self.setCurrentIndex(idx)
11
12        self.currentIndexChanged.connect(self.on_current_changed)
13
14    def on_current_changed(self, index):
15        self.layer.styleManager().setCurrentStyle(self.itemText(index))
16
17class LayerStyleWidgetProvider(QgsLayerTreeEmbeddedWidgetProvider):
18    def __init__(self):
19        QgsLayerTreeEmbeddedWidgetProvider.__init__(self)
20
21    def id(self):
22        return "style"
23
24    def name(self):
25        return "Layer style chooser"
26
27    def createWidget(self, layer, widgetIndex):
28        return LayerStyleComboBox(layer)
29
30    def supportsLayer(self, layer):
31        return True   # any layer is fine
32
33provider = LayerStyleWidgetProvider()
34QgsGui.layerTreeEmbeddedWidgetRegistry().addProvider(provider)

レイヤの 凡例 プロパティタブから、レイヤスタイルチューザー使用可能なウィジェット` から 使用するウィジェット` にドラッグして、レイヤツリーでウィジェットを有効にします。埋め込まれたウィジェットは、関連するレイヤノードのサブアイテムの一番上に常に表示されます。

プラグインなどからウィジェットを使用したい場合は、次のように追加します:

1layer = iface.activeLayer()
2counter = int(layer.customProperty("embeddedWidgets/count", 0))
3layer.setCustomProperty("embeddedWidgets/count", counter+1)
4layer.setCustomProperty("embeddedWidgets/{}/id".format(counter), "style")
5view = self.iface.layerTreeView()
6view.layerTreeModel().refreshLayerLegend(view.currentLegendNode())
7view.currentNode().setExpanded(True)