diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:24:48 +0000 |
commit | cca66b9ec4e494c1d919bff0f71a820d8afab1fa (patch) | |
tree | 146f39ded1c938019e1ed42d30923c2ac9e86789 /share/extensions/docs/tutorial/my-first-import-extension.rst | |
parent | Initial commit. (diff) | |
download | inkscape-upstream.tar.xz inkscape-upstream.zip |
Adding upstream version 1.2.2.upstream/1.2.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'share/extensions/docs/tutorial/my-first-import-extension.rst')
-rw-r--r-- | share/extensions/docs/tutorial/my-first-import-extension.rst | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/share/extensions/docs/tutorial/my-first-import-extension.rst b/share/extensions/docs/tutorial/my-first-import-extension.rst new file mode 100644 index 0000000..6c296bd --- /dev/null +++ b/share/extensions/docs/tutorial/my-first-import-extension.rst @@ -0,0 +1,305 @@ +My first import extension +========================= + +Resources +--------- + +:download:`vanillin.smi <resources/vanillin.smi>` + +Introduction +------------ + +This article will teach you the basics of writing an Import Extension for +Inkscape using the ``inkex`` Extensions API. + +Import Extensions are used to add support for a file format that +Inkscape does not support out of the box. It is rather complex to implement an entire file format, +but often there are already tools available to convert the file to a format that Inkscape can read, +such as SVG or PDF. In this case, the extension depends on external programs that convert that +specific file format to a svg that Inkscape can then read. + +The way these extensions are used is not through the ``Extensions`` menu +but instead these provide options in\ ``File``>\ ``Open`` or +``File``>\ ``Import`` dialog. + +The general flow of a Import Extension is as follows: + +1) You select the specific file format from the File Format drop down + menu of the ``File``>\ ``Open`` or ``File``>\ ``Import``\ dialog. +2) You select one or more files of that specific file format. You click + on ``Open`` button. +3) Inkscape will then either open the svg file in a new window or will + import it depending on which dialog of ``File`` menu was used. + +.. hint:: + + You can entirely skip 1) and 2) and just double click on + the file. If your extension is set up correctly, you won’t notice the + difference between opening a regular file and your file. + +In this article we will create an extension named +``Organic Bond Visualizer``. It will produce the bond structure of an +organic compound given a +`SMILES <https://en.wikipedia.org/wiki/Simplified_molecular-input_line-entry_system>`__ +file. The extension uses an external program called ``indigo-depict`` +which has its GitHub repository +`here <https://github.com/epam/Indigo>`__. (It is a part of the +``indigo-utils`` package in Debian/Ubuntu repositories. For other +platforms you might need to build it from source.) + +.. note:: A note on **PATH** + + Since the extension depends on external programs, it is important that + these external programs can be found by our extensions. For that to + happen, either these programs **should** be on your *system PATH* or an + absolute path for the program should be used in the code. + + Depending on the operating system, the steps required for adding + programs to the PATH might vary. + + You can get away with setting the PATH variable entirely by using an + absolute path for the program but it is almost always a bad idea to + hard-code paths in the code. + +.. hint:: + + This article assumes you create all extension related files in the + User Extensions directory which is listed at + ``Edit``>\ ``Preferences``>\ ``System`` - ``User Extensions:`` in + Inkscape. + +Step 0 : The Boilerplate +------------------------ + +Like any other Inkscape extension, this extension will also have two +files. So, create a ``organic_bond_vis.inx`` file and a +``organic_bond_vis.py`` file. + +- ``organic_bond_vis.inx`` - It will have the necessary information for + Inkscape to be able to recognize your extension as a valid Inkscape + extension. It will also have the info required to present the + extension as an option in ``File``>\ ``Open`` or + ``File``>\ ``Import`` dialog. +- ``organic_bond_vis.py`` - It will have the actual Python code your + extension will execute. + +.. hint:: + + There is another file that is worth mentioning here - the **test** + file which in our case will be ``test_organic_bond_vis.py``. It is + not required to be present for an extension per se, but as a best + practice, the extension code should always be accompanied by test + code. + +Step 1 : Populate the ``*.inx`` file +------------------------------------ + +.. code:: xml + + <?xml version="1.0" encoding="UTF-8"?> + <inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension"> + <name>Organic Bond Visualizer</name> + <id>org.inkscape.input.bondvisualizer</id> + <dependency type="executable" location="path">indigo-depict</dependency> + <input> + <extension>.smi</extension> + <mimetype>chemical/x-daylight-smiles</mimetype> + <filetypename>SMILES(*.smi)</filetypename> + <filetypetooltip>SMILES</filetypetooltip> + </input> + <script> + <command location="inx" interpreter="python">organic_bond_vis.py</command> + </script> + </inkscape-extension> + +The lines below help Inkscape uniquely identify our extension. You +should modify these two lines for your own extension: + +.. code:: xml + + [...] + <name>Organic Bond Visualizer</name> + <id>org.inkscape.input.bondvisualizer</id> + [...] + +Now we declare the dependency of our extension: + +.. code:: xml + + <dependency type="executable" location="path">indigo-depict</dependency> + +The ``<input>`` tag is what specifies that this extension should add a +new format in the list of available file formats Inkscape can +open/import. + +.. code:: xml + + [...] + <input> + <extension>.smi</extension> + <mimetype>chemical/x-daylight-smiles</mimetype> + <filetypename>SMILES(*.smi)</filetypename> + <filetypetooltip>SMILES</filetypetooltip> + </input> + [...] + +Inside the ``<extension>`` tag we declare the suffix of our new format +(including ``.``) + +Some more examples of suffixes could be ``.ps`` , ``.fig``, etc. The +text inside ``<filetypename>`` is what appears in the +``File``>\ ``Open`` or ``File``>\ ``Import`` dialogs. + +Towards the end, we add the name of our ``.py`` file inside the +``<command>`` tag. + +.. code:: xml + + [...] + <script> + <command location="inx" interpreter="python">organic_bond_vis.py</command> + </script> + [...] + +Now + +- Save the file +- Close any open Inkscape windows +- Relaunch Inkscape + +You should now see a ``SMILES(*.smi)`` option in the drop down menu. + +.. figure:: resources/Smiles_Format.gif + :alt: Smiles_Format + + Smiles_Format + +If you were to select the ``vanillin.smi`` file and open it, you would +get an error saying: + +.. figure:: resources/Call_Extension_Failure.png + :alt: Call_Extension_Failure + + Call_Extension_Failure + +This is because we haven’t written anything in the ``.py`` file of our +extension. + +Step 2 : Write the code in ``*.py`` file +---------------------------------------- + +First Things First +~~~~~~~~~~~~~~~~~~ + +To be able to use any extension functionality, you need to import the +``inkex`` module. + +.. code:: python + + import inkex + +There is a specialized class for input extensions that only call an external program to +convert the file. Every Call Extension inherits from the :class:`~inkex.extensions.CallExtension` +class provided by the ``inkex`` API. Let’s name our class ``OrganicBondVisualizer`` (an +arbitrary name) and inherit the :class:`~inkex.extensions.CallExtension` class. + +.. code:: python + + import inkex + + class OrganicBondVisualizer(inkex.CallExtension): + #implement functionality here + pass + +Specify the formats +~~~~~~~~~~~~~~~~~~~ + +We now specify the input file format and output file format. (both +without the ``.``). The output file format by default is ``svg``. + +.. code:: python + + import inkex + from inkex import command + + class OrganicBondVisualizer(inkex.CallExtension): + + input_ext = 'smi' + output_ext = 'svg' + + #implement functionality here + pass + +Override +~~~~~~~~ + +To be able to call an another program, we need to override the :func:`~inkex.extensions.CallExtension.call` +function in our class. We need to import the :mod:`~inkex.command` module as it +contains the actual implementation to call external programs. Inside the +overridden method we call :mod:`~inkex.command` module’s :func:`~inkex.command.call` function. + +.. code:: python + + import inkex + from inkex import command + + class OrganicBondVisualizer(inkex.CallExtension): + + input_ext = 'smi' + output_ext = 'svg' + + def call(self, input_file, output_file): + command.call('indigo-depict', input_file, output_file) + +The first argument for :mod:`~inkex.command`\ ’s :func:`~inkex.command.call` function is the name of +the external program. It can also be a path string like +``'/usr/bin/program'``. Although internally ``inkex`` converts the names +to path strings like these, you should not use them yourself. The reason +being that the user of this extension may not have the command at the +same path as the absolute path specified by us, the extension author. + + **Note**: *Windows* users don’t need to specify ``.exe`` in the name + of the program. + +The ``input_file`` and ``output_file`` are path strings received by the +:func:`~inkex.extensions.CallExtension.call` function from inkex. We then just pass these to +:mod:`~inkex.command`\ ’s :func:`~inkex.command.call` function. + +Make it all happen +~~~~~~~~~~~~~~~~~~ + +We now just add the ``__main__`` part where the extension runs. + +.. code:: python + + import inkex + from inkex import command + + class OrganicBondVisualizer(inkex.CallExtension): + + input_ext = 'smi' + output_ext = 'svg' + + def call(self, input_file, output_file): + command.call('indigo-depict', input_file, output_file) + + if __name__ == '__main__': + OrganicBondVisualizer().run() + +Now save the file. + +Moment of Truth +--------------- + +Now, we should test our extension to see in action. + +- Open a new Inkscape window +- Click on the ``File``>\ ``Import`` dialog +- Select the ``.smi`` file (An example ``.smi`` file is attached above + under `Resources <#resources>`__) and double-click on it. You should + see the following output: + +.. figure:: resources/call_extension_success.gif + :alt: Did_It_Work + + Did_It_Work |