GUI Tools#
Plugins containing GUI tools will also require modifying the setup.py
as follows:
from setuptools import setup
from plover_build_utils.setup import BuildPy, BuildUi
BuildPy.build_dependencies.append("build_ui")
BuildUi.hooks = ["plover_build_utils.pyqt:fix_icons"]
CMDCLASS = {
"build_py": BuildPy,
"build_ui": BuildUi,
}
setup(cmdclass=CMDCLASS)
By making these changes, you get commands to generate Python files from your Qt Designer UI and resource files:
python3 setup.py build_py build_ui
In addition, create a file named MANIFEST.in
in your plugin directory as
follows. Change the paths as needed, but make sure to only include the Qt
Designer .ui
files and resources, and not the generated Python files.
exclude plover_my_plugin/tool/*_rc.py
exclude plover_my_plugin/tool/*_ui.py
include plover_my_plugin/tool/*.ui
recursive-include plover_my_plugin/tool/resources *
[options.entry_points]
plover.gui.qt.tool =
example_tool = plover_my_plugin.tool:Main
GUI tools are implemented as Qt widget classes inheriting from
Tool
:
# plover_my_plugin/tool.py
from plover.gui_qt.tool import Tool
# You will also want to import / inherit for your Python class generated by
# your .ui file if you are using Qt Designer for creating your UI rather
# than only from code
class Main(Tool):
TITLE = 'Example Tool'
ICON = ''
ROLE = 'example_tool'
def __init__(self, engine):
super().__init__(engine)
# If you are inheriting from your .ui generated class, also call
# self.setupUi(self) before any additional setup code
Keep in mind that when you need to make changes to the UI, you will need to generate new Python files.
See the documentation on Tool
for more
information.
Just like extension plugins, GUI tools can interact with the engine through the
StenoEngine
API, but instead of using
engine hooks directly, GUI tools should use Qt’s
signals mechanism. Plover’s Engine
class
provides Qt signals to be used as hooks.
class StrokeLogger(Tool, Ui_StrokeLogger):
def __init__(self, engine):
super().__init__(engine)
self.setupUi(self)
# Instead of engine.hook_connect
engine.signal_connect("stroked", self.on_stroked)
def on_stroked(self, stroke):
pass