3 Helper module to get easy access to the path where resources are stored.
4 This is because the resource location is depended on the packaging method and OS
6 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
16 import ConfigParser as configparser
18 if sys.platform.startswith('darwin'):
20 #Foundation import can crash on some MacOS installs
21 from Foundation import *
25 if sys.platform.startswith('darwin'):
26 if hasattr(sys, 'frozen'):
28 resourceBasePath = NSBundle.mainBundle().resourcePath()
30 resourceBasePath = os.path.join(os.path.dirname(__file__), "../../../../../")
32 resourceBasePath = os.path.join(os.path.dirname(__file__), "../../resources")
34 resourceBasePath = os.path.join(os.path.dirname(__file__), "../../resources")
36 def getPathForResource(dir, subdir, resource_name):
37 assert os.path.isdir(dir), "{p} is not a directory".format(p=dir)
38 path = os.path.normpath(os.path.join(dir, subdir, resource_name))
39 if not os.path.isfile(path):
43 def getPathForImage(name):
44 return getPathForResource(resourceBasePath, 'images', name)
46 def getPathForMesh(name):
47 return getPathForResource(resourceBasePath, 'meshes', name)
49 def getPathForFirmware(name):
50 return getPathForResource(resourceBasePath, 'firmware', name)
52 def getDefaultMachineProfiles():
53 path = os.path.normpath(os.path.join(resourceBasePath, 'machine_profiles', '*.ini'))
54 return glob.glob(path)
56 def setupLocalization(selectedLanguage = None):
60 if selectedLanguage is not None:
61 for item in getLanguageOptions():
62 if item[1] == selectedLanguage and item[0] is not None:
65 if languages[0] == 'AUTO':
67 defaultLocale = getDefaultLocale()
68 if defaultLocale is not None:
69 for item in getLanguageOptions():
72 if item[0] is not None and defaultLocale.startswith(item[0]):
75 locale_path = os.path.normpath(os.path.join(resourceBasePath, 'locale'))
76 translation = gettext.translation('Cura', locale_path, languages, fallback=True)
77 #translation.ugettext = lambda message: u'#' + message
78 translation.install(unicode=True)
80 def getLanguageOptions():
82 ['AUTO', 'Autodetect'],
90 # ['nl', 'Nederlands'],
95 def getDefaultLocale():
98 # On Windows, we look for the actual UI language, as someone could have
99 # an english windows but use a non-english locale.
100 if platform.system() == "Windows":
104 windll = ctypes.windll.kernel32
105 defaultLocale = locale.windows_locale[windll.GetUserDefaultUILanguage()]
109 if defaultLocale is None:
111 defaultLocale = locale.getdefaultlocale()[0]
117 class ProfileIni(object):
120 return False if str is None else str.lower() in ['true', 'yes', '1', 'y', 't']
122 def __init__(self, ini_file):
124 self.path = os.path.split(self.ini)[0]
125 self.base_name = os.path.splitext(os.path.basename(self.ini))[0]
126 if self.base_name == 'profile' or self.base_name == 'material':
127 self.base_name = os.path.basename(self.path)
128 # Name to show in the UI
129 self.name = self._getProfileInfo(ini_file, 'name')
130 if self.name is None:
131 self.name = self.base_name
132 self.full_name = self._getProfileInfo(ini_file, 'full_name')
133 if self.full_name is None:
134 self.full_name = self.name
135 # URL for the profile
136 self.url = self._getProfileInfo(ini_file, 'url')
137 # Finds the full path to the real profile_file
138 self.profile_file = self._findProfileFile()
139 # default = The default profile to select
140 self.default = self.str2bool(self._getProfileInfo(self.ini, 'default'))
141 # disabled = do not make available in the UI
142 self.disabled = self.str2bool(self._getProfileInfo(self.ini, 'disabled'))
143 # always_visible = Always display in the UI even if it's the only available option
144 if self._getProfileInfo(self.ini, 'always_visible') is None:
145 self.always_visible = True
147 self.always_visible = self.str2bool(self._getProfileInfo(self.ini, 'always_visible'))
149 self.order = int(self._getProfileInfo(self.ini, 'order'))
153 def _findProfileFile(self):
154 profile_file = self._getProfileInfo(self.ini, 'profile_file')
155 if profile_file is None:
158 if os.path.exists(profile_file):
160 elif os.path.exists(os.path.join(self.path, profile_file)):
161 return os.path.join(self.path, profile_file)
165 def _getProfileInfo(self, ini_file, key):
166 cp = configparser.ConfigParser()
169 if cp.has_option('info', key):
170 return cp.get('info', key)
173 def _isInList(self, list):
174 """ Check if an option with the same base name already exists in the list """
176 if ini.base_name == self.base_name:
180 def getProfileDict(self):
182 cp = configparser.ConfigParser()
183 cp.read(self.profile_file)
184 for setting in profile.settingsList:
185 section = 'profile' if setting.isProfile() else 'alterations'
186 if setting.isProfile() or setting.isAlteration():
187 if cp.has_option(section, setting.getName()):
188 profile_dict[setting.getName()] = cp.get(section, setting.getName())
192 def __cmp__(self, cmp):
193 if self.order < cmp.order:
195 elif self.order == cmp.order:
201 return "%s%s: %d" % (self.name, "(disabled)" if self.disabled else "", self.order)
206 class PrintMaterial(ProfileIni):
207 def __init__(self, ini_file):
208 super(PrintMaterial, self).__init__(ini_file)
213 types = self._getProfileInfo(self.ini, 'material_types')
216 for type in types.split('|'):
217 self.types.append(type.strip())
218 # Comment for the profile
219 self.description = self._getProfileInfo(ini_file, 'description')
221 self.parseDirectory(self.path)
223 def parseDirectory(self, path):
224 profile_files = sorted(glob.glob(os.path.join(path, '*/profile.ini')))
225 if len(profile_files) > 0:
226 for profile_file in profile_files:
227 profile_ini = ProfileIni(profile_file)
228 if not profile_ini._isInList(self.profiles):
229 self.profiles.append(profile_ini)
231 option_files = sorted(glob.glob(os.path.join(path, 'option_*.ini')))
232 for option_file in option_files:
233 option = ProfileIni(option_file)
234 if not option._isInList(self.options):
235 self.options.append(option)
240 def addGlobalOptions(self, global_options):
241 for option in global_options:
242 if not option._isInList(self.options):
243 self.options.append(option)
247 return "%s%s: %d - Profiles : %s - Options - %s\n" % (self.name, "(disabled)" if self.disabled else "",
248 self.order, self.profiles, self.options)
251 def getSimpleModeMaterials():
252 machine_type = profile.getMachineSetting('machine_type')
254 paths.append(os.path.normpath(os.path.expanduser(os.path.join('~', '.Cura', 'quickprint', machine_type))))
255 paths.append(os.path.normpath(os.path.expanduser(os.path.join('~', '.Cura', 'quickprint'))))
256 paths.append(os.path.normpath(os.path.join(resourceBasePath, 'quickprint', machine_type)))
257 paths.append(os.path.normpath(os.path.join(resourceBasePath, 'quickprint')))
262 if os.path.isdir(path):
263 option_files = sorted(glob.glob(os.path.join(path, 'option_*.ini')))
264 for option_file in option_files:
265 option = ProfileIni(option_file)
266 if not option._isInList(global_options):
267 global_options.append(option)
269 material_files = sorted(glob.glob(os.path.join(path, '*/material.ini')))
270 if len(material_files) > 0:
271 for material_file in material_files:
272 material = PrintMaterial(material_file)
273 if not material._isInList(materials):
274 materials.append(material)
276 for ini in materials:
277 if ini.base_name == material.base_name:
278 ini.parseDirectory(os.path.split(material_file)[0])
282 for material in materials:
283 material.addGlobalOptions(global_options)
285 #print "Materials found for %s :\n%s" % (machine_type, materials)