← Back to team overview

kicad-developers team mailing list archive

PATCH: Python example script with and without gui.

 

Hello,

Attached there is a couple of new possible example scripts in python.
They change the reference designator text size of all the refdes in the open pcb. The scripts are: simpleSetAllReferenceSizes.py: simple text only version (as a simple example) setAllReferenceSizes.py : uses wxpython to create the dialog (KICAD_SCRIPTING_WXPYTHON must be enabled at compile time to use it) The aim of the second script is to make the user to be able to create the dialog without knowing anything about wxpython/wxwidgets. Note: The numeric fields accept also mathematical expressions (i.e. 10/2 in the field evaluates to 5)

Questions:
1) This code is not commented in doxygen style, but I've seen that this is also true for other scripts in the distribution: Should I comment it in doxygen style?
2) This is my first patch sent... if I'm doing something wrong ... tell me.

Tanks,
Dino.



=== added directory 'scripts/resize_refdes'
=== added file 'scripts/resize_refdes/setAllReferenceSizes.py'
--- scripts/resize_refdes/setAllReferenceSizes.py	1970-01-01 00:00:00 +0000
+++ scripts/resize_refdes/setAllReferenceSizes.py	2016-04-07 19:39:51 +0000
@@ -0,0 +1,270 @@
+#!/usr/bin/env python
+
+#Description:	Example and 'skeleton' code to implement a script with a dialog box and various fields to be entered. 
+#	        Note: in a string field it is forbidden to use double quotes in this script.
+#		It is possible to enter expressions in the numeric fields , i.e.: 3*10/5 it is a valid field and evaluates to 6.
+#  
+#Annoyances:    After changing something on the PCB it is not redrawn automatically. 
+#		To force a real redraw, switch canvas to some other mode in kicad.
+
+#to have eval return float values from the eval function. From python 3 it should not be needed.
+from __future__ import division
+
+from pcbnew import *
+import wx
+
+#****************************************************************************************************************************************************
+#****************************************************************************************************************************************************
+#****************************************************************************************************************************************************
+#****************************************************************************************************************************************************
+
+# First part of the code: Parametrized dialog box for the user interface.
+# If you are using this code as a starting point for your script
+# Don't change this but try to look first below, after the big comment block.
+class valuesDialog(wx.Frame):
+    userCallback="defaultCallback" #default exec callback. dummy.
+    params=[["firstParameter","0", "First item", "int"],
+	   ["secondParameter","1", "Second item", "int"]
+	]# #default argument list-list.
+    tc=[]
+    fieldHeight=45 #height of a text field.
+    buttonHeight=28 #height of the OK and CANCEL buttons.
+    buttonWidth=90 #width of the OK and CANCEL buttons.
+
+    def __init__(self, parent, title, execCallback, params):
+        super(valuesDialog, self).__init__(parent, title=title, 
+       #     size=(500, 360))
+	size=(500, 2*self.fieldHeight + 2*self.fieldHeight*len(params)))
+        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)    
+	self.userCallback=execCallback;
+	self.params=params;
+        self.InitUI()
+        self.Centre()
+        self.Show()     
+
+    def defaultCallback(first=0, second=0):
+	print "Default callback executed."
+	print "it should never be executed. It means you did not define the user callback"
+
+    def OnCloseWindow(self, e):
+        print "closing window"
+        print "self.Destroy return value: %s"%self.Destroy()
+        self.destroy();
+        e.Skip()
+
+    def OnClose(self, e):
+        #self.Close(True)  
+        self.Destroy()
+        e.Skip()
+       
+    def OnCloseOk(self, e):
+        #self.Close(True)  
+	print "------------------------------------------------------------------"
+	print " OK pressed..."
+    	parVal=[]
+	try:	
+		index=0
+		cmdString=self.userCallback+"("
+		separator=''
+		for parameter in self.params:
+			if(parameter[3]!="string"):
+				parVal.append(eval(self.tc[index].GetValue()))	
+			else:
+				parVal.append(self.tc[index].GetValue())
+			print parameter[0]," --> ", parVal[index]
+			if parameter[3]=='mm2ui':
+				parVal[index]=Millimeter2iu(parVal[index])
+			cmdString=cmdString+separator #add the parameter separator.
+			if (parameter[3]=='float'):
+				cmdString=cmdString + parameter[0]+'=%f' % parVal[index]
+			else:
+			 if (parameter[3]=='string'):
+				print "Checking String parameter"
+				if "\"" not in parVal[index]: #a double quote in the string is not allowed since would permit code injection in the script and
+							      #would generate an error in the exec statement below.
+					cmdString=cmdString + parameter[0]+"=\""+self.tc[index].GetValue()+"\""
+				else:
+					print "error in string format. Illegal character <\">"
+			 else: 
+				#defaults to int, including mm2ui case.
+				cmdString=cmdString + parameter[0]+'=%i' % parVal[index]
+			index=index+1
+			separator=', '
+		cmdString=cmdString+")"
+		print "Executing callback --->  ", cmdString
+		exec cmdString
+	except ValueError:
+		print "ERROR IN FIELDS: they should be all numeric."
+	
+	self.Destroy()
+        e.Skip()
+    
+    def InitUI(self):
+        panel = wx.Panel(self)
+        panel.Bind(wx.EVT_BUTTON, self.OnClose)
+        sizer = wx.GridBagSizer(2, 2)
+
+        text0 = wx.StaticText(panel, label="Can use expressions in fields.")
+        text0.Bind(wx.EVT_BUTTON, self.OnClose)
+        sizer.Add(text0, pos=(0, 0), flag=wx.EXPAND|wx.TOP|wx.LEFT|wx.BOTTOM, border=5)
+	
+	currentPos=1;
+	currentIndex=0;
+	for parameters in self.params:
+		#Add the text above the field.
+		newText= wx.StaticText(panel, label=parameters[2])	
+ 		newText.Bind(wx.EVT_BUTTON, self.OnClose)
+	        sizer.Add(newText, pos=(currentPos, 0), flag=wx.EXPAND|wx.TOP|wx.LEFT|wx.BOTTOM, border=5)
+		currentPos=currentPos+1
+       	
+		#Add the text field to the ui
+		self.tc.append(wx.TextCtrl(panel, value=parameters[1])) #create the text field and set to default value.
+	        self.tc[currentIndex].Bind(wx.EVT_BUTTON, self.OnClose)
+		sizer.Add(self.tc[currentIndex], pos=(currentPos, 0), span=(1, 5), 
+	            	flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=5)
+		currentPos=currentPos+1
+		currentIndex=currentIndex+1
+
+        buttonOk = wx.Button(panel, label="Ok", size=(self.buttonWidth, self.buttonHeight))
+        buttonClose = wx.Button(panel, label="Cancel", size=(self.buttonWidth, self.buttonHeight))
+
+	currentPos=currentPos+1
+        sizer.Add(buttonOk, pos=(currentPos, 2),    flag=wx.LEFT|wx.BOTTOM, border=5)
+        sizer.Add(buttonClose, pos=(currentPos, 0), flag=wx.RIGHT|wx.BOTTOM, border=5)
+
+        buttonOk.Bind(wx.EVT_BUTTON, self.OnCloseOk)
+        buttonClose.Bind(wx.EVT_BUTTON, self.OnClose)
+
+	currentPos=currentPos-1
+        sizer.AddGrowableRow(currentPos)
+        #sizer.AddGrowableCol(0)
+        sizer.AddGrowableCol(1)
+        #sizer.AddGrowableCol(1)
+        panel.SetSizerAndFit(sizer)
+#****************************************************************************************************************************************************
+#****************************************************************************************************************************************************
+#****************************************************************************************************************************************************
+#****************************************************************************************************************************************************
+
+# #########################################################################################
+#  End of fixed definitions. All the parts that you need to modify shoud follow.
+#  CHANGE THE NEXT CODE.
+# #########################################################################################
+
+# Part executed if the script is executed using execfile("name_of_the_file.py")
+# Note that if you use this method to execute a modified version of the script you do not need to restart kicad.
+if __name__ == '__main__':
+    resizeWithDialog(); #the function to be called.
+    #Now that the user interface has been set up it exits the script and shows the UI in the wxwidgets main loop
+    # that is NOT in this script, but in kicad.
+    print "Exited." #to show that it exits immediatly (before closing the dialog window)
+
+
+# Function to be called if the script is imported using 'import ...'
+# Note that if you are modifying the script, you will have to restart kicad to re-import a modified version of the script.
+# Here are set all the parameters used in the script.
+# Not included in the __main__ in order to be able to launch the script using an import from another script and calling this.
+def resizeWithDialog():
+
+# First prepare the data structure that will create the dialog for the parameter.
+
+#	List with the required parameters and parameter names and strings in user interface.
+#		+----------------------------------------------------------Name of the variable to be passed to the callback function
+#		|              +-------------------------------------------Default value (appears in the field in the user interface)
+#		|              |              +----------------------------Label above the field in the UI.
+#		|              |              |                    +-------Type of data to be passed: 	mm2ui: internal kicad units, but field in UI is in MM.
+#		|	       |	      |                    |       				int: int in the ui and int to be passed to the callback function.
+#		|	       |	      |                    |       				float: floating point number.
+#		|	       |	      |                    |    				string: text entered in the field
+	par=[["newWidth",     "2",      "New Width (in mm)", 	'mm2ui'	], 
+      	     ["newHeight",    "2",      "New Height (in mm)", 	'mm2ui'	], 
+	     ["newThickness", "0.2",    "New Thickness (in mm)",'mm2ui'	],
+	     ["textParameter", "text",  "Test field, unused", 	"string"]
+	     ]
+
+#Set the name of the function that has to be called when the OK button is pressed.
+	callback="setAllReferenceSizes" #Name of the function to be executed on OK button press. See below for the code for this function.
+
+	valuesDialog(None, title='New reference labels dimensions', execCallback=callback, params=par) #creates the user interface and connects the callback to the OK button.
+
+#Implementation: the real work on the PCB data structure.
+#This is the function that makes the real work, written and tested first without an user interface,
+#then included/moved here.
+def setAllReferenceSizes(newWidth, newHeight, newThickness, textParameter):
+    b = GetBoard() #Get the object representing the board currently open in pcbnew
+
+    modules=b.GetModules();# Get the list of all the components (modules)
+
+    verbosity=2  # chooses how verbose is the output:
+                 # set to 0 for no messages, silent mode, 
+                 #        1 to have reported only the number of changed items,
+                 #        2 for more messages and the list of changed items in the output
+                 #       10 to have all the messages (too many...).
+		 #	    the messages will appear in the terminal where kicad is executed.
+                 #
+
+    changedItems=0 #counter used to report the items that have been changed.
+    changedItemsList=[]; #list used to print all the references that have been re-sized.
+
+    for module in modules:  #iterate on all the modules.   
+        this_has_changed=False  #flag: used to build the final report.
+        reference=module.Reference() #Get the text object with the reference.
+        currentWidth=reference.GetWidth()
+        currentHeight=reference.GetHeight()
+        currentThickness=reference.GetThickness()
+
+        if verbosity>2:
+            print "Checking Module: %s"%module.GetReference() #print the TEXT of the reference
+
+        if verbosity>3: 
+            print "Ref angle:", reference.GetOrientation()
+            print "Prev. width: %s"%currentWidth
+            print "Prev. height: %s"%currentHeight
+            print "Prev. thickness:%s"%currentThickness
+        
+        if newHeight!=currentHeight:
+            reference.SetHeight(newHeight)
+            this_has_changed=True
+            if verbosity>2: #messages only if required
+                print "Changing Height from %s"%currentHeight
+                print "                  to %s"%newHeight
+
+        if newWidth!=currentWidth:
+            reference.SetWidth(newWidth)
+            this_has_changed=True
+            if verbosity>2: #messages only if required
+                print "Changing Width from %s"%currentWidth
+                print "                 to %s"%newWidth
+
+        if newThickness!=currentThickness:
+            reference.SetThickness(newThickness)
+            this_has_changed=True
+            if verbosity>2:
+                print "Changing Thickness from %s"%currentThickness
+                print "                     to %s"%newThickness
+
+        if this_has_changed:
+            changedItems+=1
+            if verbosity>2: 
+                print "     ****CHANGED****"
+            changedItemsList.append(reference)
+
+# If requested print the report on changed items.
+    if verbosity>0:
+        print 
+        print "----------------------------------------------------"
+        print "Total Items changed: %s"%changedItems
+        print
+# Verbosity >1: print the list of changed items.        
+    if verbosity>1:
+        
+        print "List of changed items:"
+        if len(changedItemsList)==0:
+            print "   ***no item has been changed***",
+        else:
+            for item in changedItemsList:
+                print "   ",item.GetText(), #use comma to suppress the newline at the end.
+        print 
+    if verbosity>0:    
+        print "----------------------------------------------------"
+

=== added file 'scripts/resize_refdes/simpleSetAllReferenceSizes.py'
--- scripts/resize_refdes/simpleSetAllReferenceSizes.py	1970-01-01 00:00:00 +0000
+++ scripts/resize_refdes/simpleSetAllReferenceSizes.py	2016-04-07 19:44:23 +0000
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+
+
+#Description: Changes the size and line thickness for ALL the components (modules) on the board.
+#Note: does not save anything.
+#This script can be executed using the python shell from pcbnew (Tools->Scripting Consolle)
+#   in that shell use: 
+#
+#   execfile("setAllReferenceSize.py") 
+#   AFTER changing to the right directory (with the command "cd /where/you/put/this/script")
+#
+#   or, after changing to the right directory 
+#   import setAllReferenceSizes
+#   setAllReferenceSizes (2000000, 2000000, 200000)
+#   to set all the references to 2mm width, 2mm height, 0.2mm thickness.
+
+from pcbnew import *
+
+
+def setAllReferenceSizes(newWidth, newHeight, newThickness):
+    b = GetBoard() #Get the object representing the board currently open in pcbnew
+
+    modules=b.GetModules();# Get the list of all the components (modules)
+
+    verbosity=2  # chooses how verbose is the output:
+                 # set to 0 for no messages, silent mode, 
+                 #        1 to have reported only the number of changed items,
+                 #        2 for more messages and the list of changed items in the output
+                 #       10 to have all the messages (too many...).
+                 #
+
+    changedItems=0 #counter used to report the items that have been changed.
+
+    changedItemsList=[];
+
+    for module in modules:  #iterate on all the modules.   
+        this_has_changed=False  #flag: used to build the final report.
+        reference=module.Reference() #Get the text object with the reference.
+        currentWidth=reference.GetWidth()
+        currentHeight=reference.GetHeight()
+        currentThickness=reference.GetThickness()
+
+        if verbosity>2:
+            print "Checking Module: %s"%module.GetReference() #print the TEXT of the reference
+
+        if verbosity>3: 
+            print "Ref angle:", reference.GetOrientation()
+            print "Prev. width: %s"%currentWidth
+            print "Prev. height: %s"%currentHeight
+            print "Prev. thickness:%s"%currentThickness
+        
+        if newHeight!=currentHeight:
+            reference.SetHeight(newHeight)
+            this_has_changed=True
+            if verbosity>2: #messages only if required
+                print "Changing Height from %s"%currentHeight
+                print "                  to %s"%newHeight
+
+        if newWidth!=currentWidth:
+            reference.SetWidth(newWidth)
+            this_has_changed=True
+            if verbosity>2: #messages only if required
+                print "Changing Width from %s"%currentWidth
+                print "                 to %s"%newWidth
+
+        if newThickness!=currentThickness:
+            reference.SetThickness(newThickness)
+            this_has_changed=True
+            if verbosity>2:
+                print "Changing Thickness from %s"%currentThickness
+                print "                     to %s"%newThickness
+
+
+        if this_has_changed:
+            changedItems+=1
+            if verbosity>2: 
+                print "     ****CHANGED****"
+            changedItemsList.append(reference)
+
+# If requested print the report on changed items.
+    if verbosity>0:
+        print 
+        print "----------------------------------------------------"
+        print "Total Items changed: %s"%changedItems
+        print
+# Verbosity >1: print the list of changed items.        
+    if verbosity>1:
+        
+        print "List of changed items:"
+        if len(changedItemsList)==0:
+            print "   ***no item has been changed***",
+        else:
+            for item in changedItemsList:
+                print "   ",item.GetText(), #use comma to suppress the newline at the end.
+        print 
+    if verbosity>0:    
+        print "----------------------------------------------------"
+
+# #########################################################################################
+#  End of function definition. Program entry point with default values.
+# #########################################################################################
+
+newHeight   =2270000      #new height in microns (internal units)
+newWidth    =1270000       #new width in microns
+newThickness= 227000    #new line width (thickness) in microns.
+
+setAllReferenceSizes(newWidth, newHeight, newThickness)
+