A comprehensive template for creating QGIS plugins with dockable panels, update checker, and all the essential features needed for a professional plugin.
- Dockable Panels: Sample panels that can be docked anywhere in the QGIS interface
- Plugin Update Checker: Check for updates from GitHub and install them automatically
- About Dialog: Display version information and links
- Settings Panel: Configurable plugin options with persistent storage
- Menu & Toolbar Integration: Full integration with QGIS menu system and custom toolbar
- Clean Code Structure: Well-organized, documented, and following QGIS plugin best practices
- Packaging Scripts: Ready-to-use scripts for creating zip files for the official QGIS plugin repository
qgis-plugin-template/
├── plugin_template/
│ ├── __init__.py # Plugin entry point
│ ├── plugin_template.py # Main plugin class
│ ├── metadata.txt # Plugin metadata for QGIS
│ ├── LICENSE # Plugin license
│ ├── dialogs/
│ │ ├── __init__.py
│ │ ├── sample_dock.py # Sample dockable panel
│ │ ├── settings_dock.py # Settings panel
│ │ └── update_checker.py # Update checker dialog
│ └── icons/
│ ├── icon.svg # Main plugin icon
│ ├── settings.svg # Settings icon
│ └── about.svg # About icon
├── package_plugin.py # Python packaging script
├── package_plugin.sh # Bash packaging script
├── install.py # Python installation script
├── install.sh # Bash installation script
├── README.md # This file
└── LICENSE # Repository license
- QGIS 3.28 or later
- Python 3.10+
git clone https://github.com/opengeos/qgis-plugin-template.git
cd qgis-plugin-template-
Rename the plugin:
- Rename
plugin_template/to your plugin name - Update class names in Python files (e.g.,
PluginTemplate→YourPluginName) - Update
metadata.txtwith your plugin information
- Rename
-
Update metadata.txt:
[general] name=Your Plugin Name version=0.1.0 author=Your Name email[email protected] description=Your plugin description repository=https://github.com/opengeos/your-plugin tracker=https://github.com/opengeos/your-plugin/issues
-
Update GitHub URLs in
plugin_template/dialogs/update_checker.py:GITHUB_REPO = "opengeos/your-plugin" GITHUB_BRANCH = "main" PLUGIN_PATH = "your_plugin"
Using Python:
python install.pyUsing Bash:
./install.sh- Restart QGIS
- Go to
Plugins→Manage and Install Plugins... - Find and enable your plugin
- Create a new file in
dialogs/(e.g.,my_dock.py):
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtWidgets import QDockWidget, QWidget, QVBoxLayout, QLabel
class MyDockWidget(QDockWidget):
def __init__(self, iface, parent=None):
super().__init__("My Panel", parent)
self.iface = iface
self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
# Create widget content
widget = QWidget()
layout = QVBoxLayout(widget)
layout.addWidget(QLabel("Hello from my panel!"))
self.setWidget(widget)-
Add the import to
dialogs/__init__.py -
Add toggle method in
plugin_template.py:
def toggle_my_dock(self):
if self._my_dock is None:
from .dialogs.my_dock import MyDockWidget
self._my_dock = MyDockWidget(self.iface, self.iface.mainWindow())
self.iface.addDockWidget(Qt.RightDockWidgetArea, self._my_dock)
if self._my_dock.isVisible():
self._my_dock.hide()
else:
self._my_dock.show()self.add_action(
":/images/themes/default/mActionOptions.svg", # Icon path
"My Action", # Menu text
self.my_action_callback, # Callback function
status_tip="Description of action",
add_to_toolbar=True, # Add to toolbar
add_to_menu=True, # Add to menu
parent=self.iface.mainWindow(),
)Use QSettings for persistent configuration:
from qgis.PyQt.QtCore import QSettings
settings = QSettings()
# Save setting
settings.setValue("PluginTemplate/my_setting", value)
# Load setting
value = settings.value("PluginTemplate/my_setting", default_value, type=str)# Default packaging
python package_plugin.py
# Custom plugin name
python package_plugin.py --name my_plugin
# Custom output path
python package_plugin.py --output /path/to/my_plugin.zip
# Without version in filename
python package_plugin.py --no-version# Make executable (first time only)
chmod +x package_plugin.sh
# Default packaging
./package_plugin.sh
# Custom plugin name
./package_plugin.sh --name my_plugin
# Custom output directory
./package_plugin.sh --output /path/to/output- Create an account at plugins.qgis.org
- Go to "My plugins" and click "Add a new plugin"
- Upload the generated zip file
- Fill in the required information
- Submit for review
- Open QGIS
- Go to Plugins → Manage and Install Plugins...
- Go to the Settings tab
- Click Add... under "Plugin Repositories"
- Give a name for the repository, e.g., "OpenGeos"
- Enter the URL of the repository: https://qgis.gishub.org/plugins.xml
- Click OK
- Go to the All tab
- Search for your plugin name
- Select your plugin from the list and click Install Plugin
# Install
python install.py
# Or with bash
./install.sh
# Remove
python install.py --remove
# Install with custom name
python install.py --name my_pluginCopy the plugin folder to your QGIS plugins directory:
- Linux:
~/.local/share/QGIS/QGIS3/profiles/default/python/plugins/ - macOS:
~/Library/Application Support/QGIS/QGIS3/profiles/default/python/plugins/ - Windows:
%APPDATA%\QGIS\QGIS3\profiles\default\python\plugins\
The template includes a built-in update checker that:
- Fetches the latest version from your GitHub repository
- Compares with the currently installed version
- Downloads and installs updates automatically
- Shows changelog information
To use it:
- Go to
Plugin Template→Check for Updates... - Click "Check for Updates"
- If an update is available, click "Download and Install Update"
- Restart QGIS to apply changes
When using this template for your own plugin:
- Rename
plugin_templatefolder to your plugin name - Update
metadata.txtwith your information - Update class names in all Python files
- Update menu names and toolbar names
- Update GitHub URLs in
update_checker.py - Replace icons with your own
- Update this README
- Update LICENSE if needed
- Add your plugin functionality
- Lazy Loading: Load heavy resources only when needed
- Error Handling: Always wrap dock creation in try/except
- Cleanup: Properly unload all resources in the
unload()method - Threading: Use QThread for long-running operations
- Settings: Use QSettings for persistent configuration
- Icons: Use SVG icons for resolution independence
- Documentation: Keep docstrings updated
This template is released under the MIT License. See LICENSE for details.
When creating your own plugin, you may choose any license that suits your needs.
Contributions are welcome! Please feel free to submit a Pull Request.