from wx.lib import scrolledpanel
from Cura.util import profile
+from Cura.util import plugin
from Cura.util import explorer
class pluginPanel(wx.Panel):
def __init__(self, parent, callback):
wx.Panel.__init__(self, parent,-1)
#Plugin page
- self.pluginList = profile.getPluginList()
+ self.pluginList = plugin.getPluginList("postprocess")
self.callback = callback
sizer = wx.GridBagSizer(2, 2)
self.SetSizer(sizer)
- effectStringList = []
- for effect in self.pluginList:
- effectStringList.append(effect['name'])
+ pluginStringList = []
+ for p in self.pluginList:
+ pluginStringList.append(p.getName())
- self.listbox = wx.ListBox(self, -1, choices=effectStringList)
+ self.listbox = wx.ListBox(self, -1, choices=pluginStringList)
title = wx.StaticText(self, -1, _("Plugins:"))
title.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
helpButton = wx.Button(self, -1, '?', style=wx.BU_EXACTFIT)
self.updateProfileToControls()
def updateProfileToControls(self):
- self.pluginConfig = profile.getPluginConfig()
+ self.pluginConfig = plugin.getPostProcessPluginConfig()
for p in self.panelList:
p.Show(False)
self.pluginEnabledPanel.GetSizer().Detach(p)
def _buildPluginPanel(self, pluginConfig):
plugin = None
for pluginTest in self.pluginList:
- if pluginTest['filename'] == pluginConfig['filename']:
+ if pluginTest.getFilename() == pluginConfig['filename']:
plugin = pluginTest
if plugin is None:
return False
pluginPanel = wx.Panel(self.pluginEnabledPanel)
s = wx.GridBagSizer(2, 2)
pluginPanel.SetSizer(s)
- title = wx.StaticText(pluginPanel, -1, plugin['name'])
+ title = wx.StaticText(pluginPanel, -1, plugin.getName())
title.SetFont(wx.Font(wx.SystemSettings.GetFont(wx.SYS_ANSI_VAR_FONT).GetPointSize(), wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.FONTWEIGHT_BOLD))
remButton = wx.Button(pluginPanel, -1, 'X', style=wx.BU_EXACTFIT)
helpButton = wx.Button(pluginPanel, -1, '?', style=wx.BU_EXACTFIT)
s.Add(helpButton, pos=(0,0), span=(1,1), flag=wx.TOP|wx.LEFT|wx.ALIGN_RIGHT, border=5)
s.Add(remButton, pos=(0,3), span=(1,1), flag=wx.TOP|wx.RIGHT|wx.ALIGN_RIGHT, border=5)
s.Add(wx.StaticLine(pluginPanel), pos=(1,0), span=(1,4), flag=wx.EXPAND|wx.LEFT|wx.RIGHT,border=3)
- info = wx.StaticText(pluginPanel, -1, plugin['info'])
+ info = wx.StaticText(pluginPanel, -1, plugin.getInfo())
info.Wrap(300)
s.Add(info, pos=(2,0), span=(1,4), flag=wx.EXPAND|wx.LEFT|wx.RIGHT,border=3)
pluginPanel.paramCtrls = {}
i = 0
- for param in plugin['params']:
+ for param in plugin.getParams():
value = param['default']
if param['name'] in pluginConfig['params']:
value = pluginConfig['params'][param['name']]
idx = self.panelList.index(panel)
for k in panel.paramCtrls.keys():
self.pluginConfig[idx]['params'][k] = panel.paramCtrls[k].GetValue()
- profile.setPluginConfig(self.pluginConfig)
+ plugin.setPostProcessPluginConfig(self.pluginConfig)
self.callback()
def OnAdd(self, e):
if self.listbox.GetSelection() < 0:
wx.MessageBox(_("You need to select a plugin before you can add anything."), _("Error: no plugin selected"), wx.OK | wx.ICON_INFORMATION)
return
- plugin = self.pluginList[self.listbox.GetSelection()]
- newConfig = {'filename': plugin['filename'], 'params': {}}
+ p = self.pluginList[self.listbox.GetSelection()]
+ newConfig = {'filename': p.getFilename(), 'params': {}}
if not self._buildPluginPanel(newConfig):
return
self.pluginConfig.append(newConfig)
- profile.setPluginConfig(self.pluginConfig)
+ plugin.setPostProcessPluginConfig(self.pluginConfig)
self.callback()
def OnRem(self, e):
self.Layout()
self.pluginConfig.pop(idx)
- profile.setPluginConfig(self.pluginConfig)
+ plugin.setPostProcessPluginConfig(self.pluginConfig)
self.callback()
def OnHelp(self, e):
panel = e.GetEventObject().GetParent()
- sizer = self.pluginEnabledPanel.GetSizer()
idx = self.panelList.index(panel)
fname = self.pluginConfig[idx]['filename'].lower()
webbrowser.open('http://wiki.ultimaker.com/Category:CuraPlugin')
def OnOpenPluginLocation(self, e):
- if not os.path.exists(profile.getPluginBasePaths()[0]):
- os.mkdir(profile.getPluginBasePaths()[0])
- explorer.openExplorerPath(profile.getPluginBasePaths()[0])
+ if not os.path.exists(plugin.getPluginBasePaths()[0]):
+ os.mkdir(plugin.getPluginBasePaths()[0])
+ explorer.openExplorerPath(plugin.getPluginBasePaths()[0])
def script_setImage(self, guiImage, mapImage):
self._backgroundImage = wx.BitmapFromImage(wx.Image(os.path.join(self._basePath, guiImage)))
self._mapImage = wx.Image(os.path.join(self._basePath, mapImage))
- self.SetClientSize(self._backgroundImage.GetSize())
+ self.SetClientSize(self._mapImage.GetSize())
def script_addColorCommand(self, r, g, b, command, data = None):
self._colorCommandMap[(r, g, b)] = (command, data)
--- /dev/null
+"""
+The plugin module contains information about the plugins found for Cura.
+It keeps track of a list of installed plugins and the information contained within.
+"""
+__copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
+
+import os
+import sys
+import traceback
+import platform
+import glob
+import re
+import cPickle as pickle
+
+from Cura.util import profile
+from Cura.util import resources
+
+_pluginList = None
+
+class pluginInfo(object):
+ def __init__(self, dirname, filename):
+ self._dirname = dirname
+ self._filename = filename
+ self._name = os.path.splitext(os.path.basename(filename))[0]
+ self._type = 'unknown'
+ self._info = ''
+ self._params = []
+ with open(os.path.join(dirname, filename), "r") as f:
+ for line in f:
+ line = line.strip()
+ if not line.startswith('#'):
+ break
+ line = line[1:].split(':', 1)
+ if len(line) != 2:
+ continue
+ if line[0].upper() == 'NAME':
+ self._name = line[1].strip()
+ elif line[0].upper() == 'INFO':
+ self._info = line[1].strip()
+ elif line[0].upper() == 'TYPE':
+ self._type = line[1].strip()
+ elif line[0].upper() == 'DEPEND':
+ pass
+ elif line[0].upper() == 'PARAM':
+ m = re.match('([a-zA-Z][a-zA-Z0-9_]*)\(([a-zA-Z_]*)(?::([^\)]*))?\) +(.*)', line[1].strip())
+ if m is not None:
+ self._params.append({'name': m.group(1), 'type': m.group(2), 'default': m.group(3), 'description': m.group(4)})
+ # else:
+ # print "Unknown item in plugin meta data: %s %s" % (line[0], line[1])
+
+ def getFilename(self):
+ return self._filename
+
+ def getFullFilename(self):
+ return os.path.join(self._dirname, self._filename)
+
+ def getType(self):
+ return self._type
+
+ def getName(self):
+ return self._name
+
+ def getInfo(self):
+ return self._info
+
+ def getParams(self):
+ return self._params
+
+def getPostProcessPluginConfig():
+ try:
+ return pickle.loads(str(profile.getProfileSetting('plugin_config')))
+ except:
+ return []
+
+def setPostProcessPluginConfig(config):
+ profile.putProfileSetting('plugin_config', pickle.dumps(config))
+
+def getPluginBasePaths():
+ ret = []
+ if platform.system() != "Windows":
+ ret.append(os.path.expanduser('~/.cura/plugins/'))
+ if platform.system() == "Darwin" and hasattr(sys, 'frozen'):
+ ret.append(os.path.normpath(os.path.join(resources.resourceBasePath, "plugins")))
+ else:
+ ret.append(os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'plugins')))
+ return ret
+
+def getPluginList(pluginType):
+ global _pluginList
+ if _pluginList is None:
+ _pluginList = []
+ for basePath in getPluginBasePaths():
+ for filename in os.listdir(basePath):
+ if filename.startswith('.'):
+ continue
+ if filename.startswith('_'):
+ continue
+ if os.path.isdir(os.path.join(basePath, filename)):
+ if os.path.exists(os.path.join(basePath, filename, 'script.py')):
+ _pluginList.append(pluginInfo(basePath, os.path.join(filename, 'script.py')))
+ elif filename.endswith('.py'):
+ _pluginList.append(pluginInfo(basePath, filename))
+ ret = []
+ for plugin in _pluginList:
+ if plugin.getType() == pluginType:
+ ret.append(plugin)
+ return ret
+
+def runPostProcessingPlugins(engineResult):
+ pluginConfigList = getPostProcessPluginConfig()
+ pluginList = getPluginList()
+
+ for pluginConfig in pluginConfigList:
+ plugin = None
+ for pluginTest in pluginList:
+ if pluginTest['filename'] == pluginConfig['filename']:
+ plugin = pluginTest
+ if plugin is None:
+ continue
+
+ pythonFile = None
+ for basePath in getPluginBasePaths():
+ testFilename = os.path.join(basePath, pluginConfig['filename'])
+ if os.path.isfile(testFilename):
+ pythonFile = testFilename
+ if pythonFile is None:
+ continue
+
+ locals = {'filename': gcodefilename}
+ for param in plugin['params']:
+ value = param['default']
+ if param['name'] in pluginConfig['params']:
+ value = pluginConfig['params'][param['name']]
+
+ if param['type'] == 'float':
+ try:
+ value = float(value)
+ except:
+ value = float(param['default'])
+
+ locals[param['name']] = value
+ try:
+ execfile(pythonFile, locals)
+ except:
+ locationInfo = traceback.extract_tb(sys.exc_info()[2])[-1]
+ return "%s: '%s' @ %s:%s:%d" % (str(sys.exc_info()[0].__name__), str(sys.exc_info()[1]), os.path.basename(locationInfo[0]), locationInfo[2], locationInfo[1])
+ return None
from __future__ import division
__copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
-import os, traceback, math, re, zlib, base64, time, sys, platform, glob, string, stat, types
+import os
+import traceback
+import math
+import re
+import zlib
+import base64
+import time
+import sys
+import platform
+import glob
+import string
+import stat
+import types
import cPickle as pickle
import numpy
if sys.version_info[0] < 3:
else:
import configparser as ConfigParser
-from Cura.util import resources
from Cura.util import version
from Cura.util import validators
#Append the profile string to the end of the GCode, so we can load it from the GCode file later.
postfix = ';CURA_PROFILE_STRING:%s\n' % (getProfileString())
return unicode(prefix + re.sub("(.)\{([^\}]*)\}", replaceTagMatch, alterationContents).rstrip() + '\n' + postfix).strip().encode('utf-8') + '\n'
-
-###### PLUGIN #####
-
-def getPluginConfig():
- try:
- return pickle.loads(str(getProfileSetting('plugin_config')))
- except:
- return []
-
-def setPluginConfig(config):
- putProfileSetting('plugin_config', pickle.dumps(config))
-
-def getPluginBasePaths():
- ret = []
- if platform.system() != "Windows":
- ret.append(os.path.expanduser('~/.cura/plugins/'))
- if platform.system() == "Darwin" and hasattr(sys, 'frozen'):
- ret.append(os.path.normpath(os.path.join(resources.resourceBasePath, "plugins")))
- else:
- ret.append(os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'plugins')))
- return ret
-
-def getPluginList():
- ret = []
- for basePath in getPluginBasePaths():
- for filename in glob.glob(os.path.join(basePath, '*.py')):
- filename = os.path.basename(filename)
- if filename.startswith('_'):
- continue
- with open(os.path.join(basePath, filename), "r") as f:
- item = {'filename': filename, 'name': None, 'info': None, 'type': None, 'params': []}
- for line in f:
- line = line.strip()
- if not line.startswith('#'):
- break
- line = line[1:].split(':', 1)
- if len(line) != 2:
- continue
- if line[0].upper() == 'NAME':
- item['name'] = line[1].strip()
- elif line[0].upper() == 'INFO':
- item['info'] = line[1].strip()
- elif line[0].upper() == 'TYPE':
- item['type'] = line[1].strip()
- elif line[0].upper() == 'DEPEND':
- pass
- elif line[0].upper() == 'PARAM':
- m = re.match('([a-zA-Z][a-zA-Z0-9_]*)\(([a-zA-Z_]*)(?::([^\)]*))?\) +(.*)', line[1].strip())
- if m is not None:
- item['params'].append({'name': m.group(1), 'type': m.group(2), 'default': m.group(3), 'description': m.group(4)})
- else:
- print "Unknown item in effect meta data: %s %s" % (line[0], line[1])
- if item['name'] is not None and item['type'] == 'postprocess':
- ret.append(item)
- return ret
-
-def runPostProcessingPlugins(gcodefilename):
- pluginConfigList = getPluginConfig()
- pluginList = getPluginList()
-
- for pluginConfig in pluginConfigList:
- plugin = None
- for pluginTest in pluginList:
- if pluginTest['filename'] == pluginConfig['filename']:
- plugin = pluginTest
- if plugin is None:
- continue
-
- pythonFile = None
- for basePath in getPluginBasePaths():
- testFilename = os.path.join(basePath, pluginConfig['filename'])
- if os.path.isfile(testFilename):
- pythonFile = testFilename
- if pythonFile is None:
- continue
-
- locals = {'filename': gcodefilename}
- for param in plugin['params']:
- value = param['default']
- if param['name'] in pluginConfig['params']:
- value = pluginConfig['params'][param['name']]
-
- if param['type'] == 'float':
- try:
- value = float(value)
- except:
- value = float(param['default'])
-
- locals[param['name']] = value
- try:
- execfile(pythonFile, locals)
- except:
- locationInfo = traceback.extract_tb(sys.exc_info()[2])[-1]
- return "%s: '%s' @ %s:%s:%d" % (str(sys.exc_info()[0].__name__), str(sys.exc_info()[1]), os.path.basename(locationInfo[0]), locationInfo[2], locationInfo[1])
- return None