Load a sif sif file- beginning write a plugin


#1

I try to create a simple plugin to load a sif file. I took the skeleton simple plugin example and I made a few changes. But the file don’t be loaded. where I’m wrong?
I put the test.sif in the same plugin folder. The xml file is loaded into the menu

#!/usr/bin/env python

import os
import sys
import codecs

def process(filename):
	
	template_filename = os.path.join(os.path.dirname(sys.argv[0]), 'test.sif')

	template_f = codecs.open(template_filename, 'r', encoding='utf-8')
	template_contents = template_f.readlines()
	template_f.close()
	
	# Read the input file
	inputfile_f = codecs.open(filename, 'r', encoding='utf-8')
	inputfile_contents = inputfile_f.readlines()
	inputfile_f.close()
	
	# Now write results to the same file
	inputfile_f = open(filename, 'w', encoding='utf-8')
	inputfile_f.close()


#2

Hello quadrochave,

I don’t see you calling process(sys.argv[1]) after having declared your process function… and it is thus never executed.

Moreover I’d recommend

  1. using xml parsing instead of plain text… that will ensure the proper formatting of the resulting document.
  2. using a logging mechanism, to get feedback on how your plugin behaved if it encounters a problem

Below is code that works for me with these 2 elements, to copy elements of a template into the current synfig file.

#!/usr/bin/env python

import os
import sys
import xml.etree.ElementTree as ET  # common Python xml implementation
import logging


def process(filename):
   
   # setup logging
   log = os.path.join(os.path.dirname(sys.argv[0]), 'plugin.log')
   logging.basicConfig(filename='plugin.log',level=logging.DEBUG)
   logging.info('running plugin "test"')
   
   template_filename = os.path.join(os.path.dirname(sys.argv[0]), 'test.sif')
  
   # read template sif file as xml (TODO consider SAX 'parse' instead, for very big xml files)
   logging.debug('loading template file %s'%template_filename)
   tree = ET.parse(template_filename)
   template_canvas = tree.getroot()
    
   # Read the input file
   logging.debug('loading current file %s'%filename)
   tree = ET.parse(filename)
   canvas = tree.getroot()
  
   # copy canvas/defs/* and canvas/layer from template to file 
   for layer_t in template_canvas.findall("./layer"):
      logging.debug('copying layer %s from template to file'%layer_t.get('desc'))
      canvas.append(layer_t)
  
   defs_nodes_t = template_canvas.findall("./defs/*")
   if defs_nodes_t:
      defs = canvas.find("./defs")
      if defs is None:
         logging.debug('creating node for exported values in file')      
         defs = ET.Element('defs')           
         canvas.insert(1,k) # insert <defs /> after <name>.                  
      defs.extend(defs_nodes_t) # append all template defs children to file defs
      logging.debug('added %d exported values in file'%len(defs_nodes_t))      

   # write modified xml tree to the same sif file
   tree.write(filename, encoding="UTF-8", xml_declaration=True)
   logging.info('call to plugin "test" successfully completed. Synfig will now reload your file.')
  
   

#run process() on call
if len(sys.argv) < 2:
   sys.exit("Missing synfig filename as argument")
else:
   sifin_filename = sys.argv[1]
   #make sure the plugin is called on sif, and not sifz
   if not (os.path.splitext(sifin_filename)[-2].lower().endswith('.sif') or os.path.splitext(sifin_filename)[-1].lower().endswith('.sif')):
      sys.exit("Synfig plug-ins only work on sif file, not sifz.\n\nPlease save your Synfig project (%s) as sif, then try again." % sifin_filename)
   process(sifin_filename)

I would add additional arguments to enable a more customized use of the plugin from the command line as well… If interested see the code of plugin to import keyframes from Audacity. You could, a.o., add the template name as a parameter.

hope this helps.
B.