Inkscape.org
Creating New Extensions [beginner's question] Some guidance on mapping a key to a custom Python function to do repetitive tasks
  1. #1
    Rodrigo Morales Rodrigo Morales @rodrigomorales
    *

    When I'm using Inkscape, there are some tasks which I frequently do. These are the tasks that I frequently do:

    1. Set the opacity of the selected path to 10%
    2. Export selection to PNG in 600 DPI and insert it to my clipboard

    I wish I could map a key to do those repetitive tasks. That is, I want to do (1) or (2) by pressing a single key in my keyboard.

    I have been searching for a while and I found out that some people have created Inkscape extensions using Python. I have never created an Inkscape extension, but I have used Python in the past and it seems that Inkscape can be widely controlled using Python so I'm planning to learn how to write my custom extensions, so that I could find a way to map a key to a Python function that do (1) and (2).

    So far, I have been able to execute this extension https://inkscapetutorial.org/hello-extension.html in my computer.

    I'm creating this post so that others can share their experiences mapping a key to a custom function which you created in Python. Any information on this topic is appreciated.

     

  2. #2
    Rodrigo Morales Rodrigo Morales @rodrigomorales
    *

    I managed to create an extension to create an extension for setting the opacity and I was able to map it to a key by going to "Preferences" > "Keyboard". Below is the code of the extension.

    Now, I need to learn how to export the selection to a PNG file and insert it to my clipboard.

    ~/.config/inkscape/extensions/my_set_opacity_to_10_percent/my_set_opacity_to_10_percent.inx

    <?xml version="1.0" encoding="UTF-8"?>
    <inkscape-extension
        xmlns="http://www.inkscape.org/namespace/inkscape/extension">
        <name>Set opacity of selection to 10%</name>
        <id>user.my_set_opacity_to_10_percent</id>
        <effect>
            <object-type>all</object-type>
            <effects-menu>
                <submenu name="Custom"/>
            </effects-menu>
        </effect>
        <script>
            <command location="inx" interpreter="python">my_set_opacity_to_10_percent.py</command>
        </script>
    </inkscape-extension>
    

    ~/.config/inkscape/extensions/my_set_opacity_to_10_percent/my_set_opacity_to_10_percent.py

    import inkex
    from inkex import TextElement
    
    class Hello(inkex.EffectExtension):
        def effect(self):
            for elem in self.svg.selection:
                elem.style['opacity'] = 0.1
    
    if __name__ == '__main__':
        Hello().run()
    

     

  3. #3
    inklinea inklinea @inklinea⛰️

    It's not possible to replicate the gui export to .png function directly with pure python (inkex)

    It requires a command call to the main Inkscape program to export to a file in the system tempfolder

    You can then open the .png file with PIL (pillow) which is bundled with Inkscape on Windows.

    (Please note there was a slight issue with one of the 1.4.x releases and PIL which has been reported)

    Then you would need to go from the PIL Image to the Windows clipboard.

    I requires a pypi library to be installed, there are a couple of examples if you search

    "python 3 PIL image to clipboard"

    I think some also work with Linux.

  4. #4
    Rodrigo Morales Rodrigo Morales @rodrigomorales

    I managed to create an extension that exports the selection to a PNG file using the code below. I would appreciate some feedback from more experienced users on the code that I wrote. Any suggestion/improvement to my code is appreciated.

    ~/.config/inkscape/extensions/my_export_selection_to_png/my_export_selection_to_png.inx

    <?xml version="1.0" encoding="UTF-8"?>
    <inkscape-extension
        xmlns="http://www.inkscape.org/namespace/inkscape/extension">
        <name>Export selection to PNG</name>
        <id>user.my_export_selection_to_png</id>
        <effect>
            <object-type>all</object-type>
            <effects-menu>
                <submenu name="Custom"/>
            </effects-menu>
        </effect>
        <script>
            <command location="inx" interpreter="python">my_export_selection_to_png.py</command>
        </script>
    </inkscape-extension>

    ~/.config/inkscape/extensions/my_export_selection_to_png/my_export_selection_to_png.py

    import inkex
    import subprocess
    import copy
    
    class MyExportSelectionToPng(inkex.EffectExtension):
        def effect(self):
            # Create copy of the SVG file
            document = copy.deepcopy(self.document)
            # Get the ID of elements in the selection
            selected_elements_ids = []
            for elem in self.svg.selection:
                selected_elements_ids.append(elem.eid)
            # Remove elements that are not in the selection
            g = document.xpath('/svg:svg/svg:g', namespaces=inkex.NSS)[0]
            for element in g.getchildren():
                if element.eid not in selected_elements_ids:
                    g.remove(element)
            # Write document to a temporary file
            document.write('/tmp/a.svg')
            # Export PNG file to SVG file
            command = [
                'inkscape',
                '/tmp/a.svg',
                '--export-area-drawing',
                '--export-dpi=600',
                '--export-type', 'png',
                '--export-filename', '/tmp/a.png',
            ]
            try:
                subprocess.check_call(command)
            except Exception as e:
                raise Exception(
                    f'Failed to convert.')
            # TODO: Insert PNG file to clipboard
            #
            # Note: Calling xclip through subprocess.run makes Inkscape
            # get stuck. For the time being, I'll write a separate shell
            # scripts that inserts the image into the clipboard.
            #
            # subprocess.run(['xclip', '-selection', 'clipboard', '-t', 'image/png', '/tmp/a.png'])
    
    if __name__ == '__main__':script
        MyExportSelectionToPng().run()
    

     

    Sidenote: In Preferences, I then mapped "x" to call "Set opacity to 10%" and "c" to call "Export selection to PNG" so that I can quickly call those functions with my left hand. While I'm editing in Inkscape, I mainly use my right hand to do actions with the mouse and my left hand remains in the keyboard.

Inkscape Inkscape.org Inkscape Forum Creating New Extensions [beginner's question] Some guidance on mapping a key to a custom Python function to do repetitive tasks