# GUI Tools Plugins containing GUI tools will also require modifying the `setup.py` as follows: ```python 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 * ```ini [options.entry_points] plover.gui.qt.tool = example_tool = plover_my_plugin.tool:Main ``` GUI tools are implemented as Qt widget **classes** inheriting from {class}`Tool`: ```python # 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 {class}`Tool` for more information. Just like extension plugins, GUI tools can interact with the engine through the {class}`StenoEngine` API, but instead of using {ref}`engine hooks` directly, GUI tools should use Qt's signals mechanism. Plover's {class}`Engine` class provides Qt signals to be used as hooks. ```python 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 ```