Commit 56415f0ed79f7b5e686f125e817273231ab1b616

Authored by Thiago Franco de Moraes
Committed by GitHub
1 parent f30a57f6
Exists in master

Encoding Errors in Windows (#110)

Fix the above unicode related errors:
- InVesalius was not starting in Windows with users with non ascii chars.
- Not opening dicom files from path with non ascii chars.
- Not opening bitmap files from path with non ascii chars.
- Not opening Analyze, Nifti with filename with non ascii chars.
- Not exporting surface when the path has non ascii chars.
- Not exporting picture when the path has non ascii chars.
- Not importing surface when the path has non ascii chars.
- Strange chars when showing developers and translators with non ascii chars.

To fix that errors we are convert all paths and filenames to unicode. wxPythons eases this, since it gives the paths and filenames as unicode. When using VTK to save or open a file we encode the filename to sys.getfilesystemencoding. In Windows it is necessary an additional step, convert the filename to an short representation using [win32api](http://docs.activestate.com/activepython/2.6/pywin32/win32api__GetShortPathName_meth.html).
@@ -54,6 +54,22 @@ import invesalius.i18n as i18n @@ -54,6 +54,22 @@ import invesalius.i18n as i18n
54 import invesalius.session as ses 54 import invesalius.session as ses
55 import invesalius.utils as utils 55 import invesalius.utils as utils
56 56
  57 +FS_ENCODE = sys.getfilesystemencoding()
  58 +
  59 +if sys.platform == 'win32':
  60 + from invesalius.expanduser import expand_user
  61 + try:
  62 + USER_DIR = expand_user()
  63 + except:
  64 + USER_DIR = os.path.expanduser('~').decode(FS_ENCODE)
  65 +else:
  66 + USER_DIR = os.path.expanduser('~').decode(FS_ENCODE)
  67 +
  68 +USER_INV_DIR = os.path.join(USER_DIR, u'.invesalius')
  69 +USER_PRESET_DIR = os.path.join(USER_INV_DIR, u'presets')
  70 +USER_RAYCASTING_PRESETS_DIRECTORY = os.path.join(USER_PRESET_DIR, u'raycasting')
  71 +USER_LOG_DIR = os.path.join(USER_INV_DIR, u'logs')
  72 +
57 # ------------------------------------------------------------------ 73 # ------------------------------------------------------------------
58 74
59 75
@@ -157,7 +173,7 @@ class SplashScreen(wx.SplashScreen): @@ -157,7 +173,7 @@ class SplashScreen(wx.SplashScreen):
157 # Only after language was defined, splash screen will be 173 # Only after language was defined, splash screen will be
158 # shown 174 # shown
159 if lang: 175 if lang:
160 - print "LANG", lang, _, wx.Locale(), wx.GetLocale() 176 + # print "LANG", lang, _, wx.Locale(), wx.GetLocale()
161 import locale 177 import locale
162 locale.setlocale(locale.LC_ALL, '') 178 locale.setlocale(locale.LC_ALL, '')
163 # For pt_BR, splash_pt.png should be used 179 # For pt_BR, splash_pt.png should be used
@@ -237,6 +253,8 @@ def parse_comand_line(): @@ -237,6 +253,8 @@ def parse_comand_line():
237 """ 253 """
238 session = ses.Session() 254 session = ses.Session()
239 255
  256 + print ">>>> stdin encoding", sys.stdin.encoding
  257 +
240 # Parse command line arguments 258 # Parse command line arguments
241 parser = op.OptionParser() 259 parser = op.OptionParser()
242 260
@@ -269,7 +287,7 @@ def parse_comand_line(): @@ -269,7 +287,7 @@ def parse_comand_line():
269 i = len(args) 287 i = len(args)
270 while i: 288 while i:
271 i -= 1 289 i -= 1
272 - file = args[i] 290 + file = args[i].decode(sys.stdin.encoding)
273 if os.path.isfile(file): 291 if os.path.isfile(file):
274 path = os.path.abspath(file) 292 path = os.path.abspath(file)
275 Publisher.sendMessage('Open project', path) 293 Publisher.sendMessage('Open project', path)
@@ -308,22 +326,16 @@ if __name__ == '__main__': @@ -308,22 +326,16 @@ if __name__ == '__main__':
308 os.chdir(path) 326 os.chdir(path)
309 327
310 # Create raycasting presets' folder, if it doens't exist 328 # Create raycasting presets' folder, if it doens't exist
311 - dirpath = os.path.join(os.path.expanduser('~'),  
312 - ".invesalius",  
313 - "presets")  
314 - if not os.path.isdir(dirpath):  
315 - os.makedirs(dirpath) 329 + if not os.path.isdir(USER_RAYCASTING_PRESETS_DIRECTORY):
  330 + os.makedirs(USER_RAYCASTING_PRESETS_DIRECTORY)
316 331
317 # Create logs' folder, if it doesn't exist 332 # Create logs' folder, if it doesn't exist
318 - dirpath = os.path.join(os.path.expanduser('~'),  
319 - ".invesalius",  
320 - "logs")  
321 - if not os.path.isdir(dirpath):  
322 - os.makedirs(dirpath) 333 + if not os.path.isdir(USER_LOG_DIR):
  334 + os.makedirs(USER_LOG_DIR)
323 335
324 if hasattr(sys,"frozen") and sys.frozen == "windows_exe": 336 if hasattr(sys,"frozen") and sys.frozen == "windows_exe":
325 # Set system standard error output to file 337 # Set system standard error output to file
326 - path = os.path.join(dirpath, "stderr.log") 338 + path = os.path.join(USER_LOG_DIR, u"stderr.log")
327 sys.stderr = open(path, "w") 339 sys.stderr = open(path, "w")
328 340
329 # Add current directory to PYTHONPATH, so other classes can 341 # Add current directory to PYTHONPATH, so other classes can
invesalius/constants.py
@@ -320,46 +320,63 @@ WINDOW_LEVEL = {_("Abdomen"):(350,50), @@ -320,46 +320,63 @@ WINDOW_LEVEL = {_("Abdomen"):(350,50),
320 320
321 REDUCE_IMAGEDATA_QUALITY = 0 321 REDUCE_IMAGEDATA_QUALITY = 0
322 322
323 -FILE_PATH = os.path.split(__file__)[0] 323 +
  324 +# PATHS
  325 +FS_ENCODE = sys.getfilesystemencoding()
  326 +
  327 +if sys.platform == 'win32':
  328 + from invesalius.expanduser import expand_user
  329 + try:
  330 + USER_DIR = expand_user()
  331 + except:
  332 + USER_DIR = os.path.expanduser('~').decode(FS_ENCODE)
  333 +else:
  334 + USER_DIR = os.path.expanduser('~').decode(FS_ENCODE)
  335 +
  336 +USER_INV_DIR = os.path.join(USER_DIR, u'.invesalius')
  337 +USER_PRESET_DIR = os.path.join(USER_INV_DIR, u'presets')
  338 +USER_LOG_DIR = os.path.join(USER_INV_DIR, u'logs')
  339 +
  340 +FILE_PATH = os.path.split(__file__)[0].decode(FS_ENCODE)
324 341
325 if hasattr(sys,"frozen") and (sys.frozen == "windows_exe"\ 342 if hasattr(sys,"frozen") and (sys.frozen == "windows_exe"\
326 or sys.frozen == "console_exe"): 343 or sys.frozen == "console_exe"):
327 - abs_path = os.path.abspath(FILE_PATH + os.sep + ".." + os.sep + ".." + os.sep + "..")  
328 - ICON_DIR = os.path.join(abs_path, "icons")  
329 - SAMPLE_DIR = os.path.join(FILE_PATH, 'samples')  
330 - DOC_DIR = os.path.join(FILE_PATH, 'docs')  
331 - folder=RAYCASTING_PRESETS_DIRECTORY= os.path.join(abs_path, "presets", "raycasting")  
332 - RAYCASTING_PRESETS_COLOR_DIRECTORY = os.path.join(abs_path, "presets", "raycasting", "color_list") 344 + abs_path = os.path.abspath(FILE_PATH, u'..', u'..', u'..')
  345 + ICON_DIR = os.path.join(abs_path, u"icons")
  346 + SAMPLE_DIR = os.path.join(FILE_PATH, u'samples')
  347 + DOC_DIR = os.path.join(FILE_PATH, u'docs')
  348 + folder=RAYCASTING_PRESETS_DIRECTORY= os.path.join(abs_path, u"presets", u"raycasting")
  349 + RAYCASTING_PRESETS_COLOR_DIRECTORY = os.path.join(abs_path, u"presets", u"raycasting", u"color_list")
333 350
334 else: 351 else:
335 - ICON_DIR = os.path.abspath(os.path.join(FILE_PATH, '..', 'icons'))  
336 - SAMPLE_DIR = os.path.abspath(os.path.join(FILE_PATH,'..', 'samples'))  
337 - DOC_DIR = os.path.abspath(os.path.join(FILE_PATH,'..', 'docs')) 352 + ICON_DIR = os.path.abspath(os.path.join(FILE_PATH, u'..', u'icons'))
  353 + SAMPLE_DIR = os.path.abspath(os.path.join(FILE_PATH, u'..', u'samples'))
  354 + DOC_DIR = os.path.abspath(os.path.join(FILE_PATH, u'..', u'docs'))
338 355
339 - folder=RAYCASTING_PRESETS_DIRECTORY= os.path.abspath(os.path.join(".",  
340 - "presets",  
341 - "raycasting")) 356 + folder=RAYCASTING_PRESETS_DIRECTORY= os.path.abspath(os.path.join(u".",
  357 + u"presets",
  358 + u"raycasting"))
342 359
343 - RAYCASTING_PRESETS_COLOR_DIRECTORY = os.path.abspath(os.path.join(".",  
344 - "presets",  
345 - "raycasting",  
346 - "color_list")) 360 + RAYCASTING_PRESETS_COLOR_DIRECTORY = os.path.abspath(os.path.join(u".",
  361 + u"presets",
  362 + u"raycasting",
  363 + u"color_list"))
347 364
348 365
349 # MAC App 366 # MAC App
350 if not os.path.exists(ICON_DIR): 367 if not os.path.exists(ICON_DIR):
351 - ICON_DIR = os.path.abspath(os.path.join(FILE_PATH, '..', '..', '..', '..', 'icons'))  
352 - SAMPLE_DIR = os.path.abspath(os.path.join(FILE_PATH,'..', '..', '..', '..', 'samples'))  
353 - DOC_DIR = os.path.abspath(os.path.join(FILE_PATH,'..', '..', '..', '..', 'docs'))  
354 -  
355 -  
356 -ID_TO_BMP = {VOL_FRONT: [_("Front"), os.path.join(ICON_DIR, "view_front.png")],  
357 - VOL_BACK: [_("Back"), os.path.join(ICON_DIR, "view_back.png")],  
358 - VOL_TOP: [_("Top"), os.path.join(ICON_DIR, "view_top.png")],  
359 - VOL_BOTTOM: [_("Bottom"), os.path.join(ICON_DIR, "view_bottom.png")],  
360 - VOL_RIGHT: [_("Right"), os.path.join(ICON_DIR, "view_right.png")],  
361 - VOL_LEFT: [_("Left"), os.path.join(ICON_DIR, "view_left.png")],  
362 - VOL_ISO:[_("Isometric"), os.path.join(ICON_DIR,"view_isometric.png")] 368 + ICON_DIR = os.path.abspath(os.path.join(FILE_PATH, u'..', u'..', u'..', u'..', u'icons'))
  369 + SAMPLE_DIR = os.path.abspath(os.path.join(FILE_PATH, u'..', u'..', u'..', u'..', u'samples'))
  370 + DOC_DIR = os.path.abspath(os.path.join(FILE_PATH, u'..', u'..', u'..', u'..', u'docs'))
  371 +
  372 +
  373 +ID_TO_BMP = {VOL_FRONT: [_("Front"), os.path.join(ICON_DIR, u"view_front.png")],
  374 + VOL_BACK: [_("Back"), os.path.join(ICON_DIR, u"view_back.png")],
  375 + VOL_TOP: [_("Top"), os.path.join(ICON_DIR, u"view_top.png")],
  376 + VOL_BOTTOM: [_("Bottom"), os.path.join(ICON_DIR, u"view_bottom.png")],
  377 + VOL_RIGHT: [_("Right"), os.path.join(ICON_DIR, u"view_right.png")],
  378 + VOL_LEFT: [_("Left"), os.path.join(ICON_DIR, u"view_left.png")],
  379 + VOL_ISO:[_("Isometric"), os.path.join(ICON_DIR, u"view_isometric.png")]
363 } 380 }
364 381
365 # if 1, use vtkVolumeRaycastMapper, if 0, use vtkFixedPointVolumeRayCastMapper 382 # if 1, use vtkVolumeRaycastMapper, if 0, use vtkFixedPointVolumeRayCastMapper
@@ -405,19 +422,10 @@ RAYCASTING_FILES = {_("Airways"): "Airways.plist", @@ -405,19 +422,10 @@ RAYCASTING_FILES = {_("Airways"): "Airways.plist",
405 # os.path.isfile(os.path.join(folder,filename))] 422 # os.path.isfile(os.path.join(folder,filename))]
406 423
407 424
408 -LOG_FOLDER = os.path.join(os.path.expanduser('~'), '.invesalius', 'logs')  
409 -if not os.path.isdir(LOG_FOLDER):  
410 - os.makedirs(LOG_FOLDER)  
411 -  
412 -folder = os.path.join(os.path.expanduser('~'), '.invesalius', 'presets')  
413 -if not os.path.isdir(folder):  
414 - os.makedirs(folder)  
415 -  
416 -  
417 -USER_RAYCASTING_PRESETS_DIRECTORY = folder 425 +USER_RAYCASTING_PRESETS_DIRECTORY = os.path.join(USER_PRESET_DIR, u'raycasting')
418 RAYCASTING_TYPES = [_(filename.split(".")[0]) for filename in 426 RAYCASTING_TYPES = [_(filename.split(".")[0]) for filename in
419 - os.listdir(folder) if  
420 - os.path.isfile(os.path.join(folder,filename))] 427 + os.listdir(USER_RAYCASTING_PRESETS_DIRECTORY) if
  428 + os.path.isfile(os.path.join(USER_RAYCASTING_PRESETS_DIRECTORY, filename))]
421 RAYCASTING_TYPES += RAYCASTING_FILES.keys() 429 RAYCASTING_TYPES += RAYCASTING_FILES.keys()
422 RAYCASTING_TYPES.append(_(' Off')) 430 RAYCASTING_TYPES.append(_(' Off'))
423 RAYCASTING_TYPES.sort() 431 RAYCASTING_TYPES.sort()
invesalius/control.py
@@ -338,6 +338,9 @@ class Controller(): @@ -338,6 +338,9 @@ class Controller():
338 else: 338 else:
339 dirpath, filename = session.project_path 339 dirpath, filename = session.project_path
340 340
  341 + if isinstance(filename, str):
  342 + filename = filename.decode(const.FS_ENCODE)
  343 +
341 proj = prj.Project() 344 proj = prj.Project()
342 prj.Project().SavePlistProject(dirpath, filename) 345 prj.Project().SavePlistProject(dirpath, filename)
343 346
invesalius/data/imagedata_utils.py
@@ -227,7 +227,7 @@ def CreateImageData(filelist, zspacing, xyspacing,size, @@ -227,7 +227,7 @@ def CreateImageData(filelist, zspacing, xyspacing,size,
227 message = _("Generating multiplanar visualization...") 227 message = _("Generating multiplanar visualization...")
228 228
229 if not const.VTK_WARNING: 229 if not const.VTK_WARNING:
230 - log_path = os.path.join(const.LOG_FOLDER, 'vtkoutput.txt') 230 + log_path = os.path.join(const.USER_LOG_DIR, 'vtkoutput.txt')
231 fow = vtk.vtkFileOutputWindow() 231 fow = vtk.vtkFileOutputWindow()
232 fow.SetFileName(log_path) 232 fow.SetFileName(log_path)
233 ow = vtk.vtkOutputWindow() 233 ow = vtk.vtkOutputWindow()
@@ -332,7 +332,7 @@ class ImageCreator: @@ -332,7 +332,7 @@ class ImageCreator:
332 message = _("Generating multiplanar visualization...") 332 message = _("Generating multiplanar visualization...")
333 333
334 if not const.VTK_WARNING: 334 if not const.VTK_WARNING:
335 - log_path = os.path.join(const.LOG_FOLDER, 'vtkoutput.txt') 335 + log_path = os.path.join(const.USER_LOG_DIR, 'vtkoutput.txt')
336 fow = vtk.vtkFileOutputWindow() 336 fow = vtk.vtkFileOutputWindow()
337 fow.SetFileName(log_path) 337 fow.SetFileName(log_path)
338 ow = vtk.vtkOutputWindow() 338 ow = vtk.vtkOutputWindow()
invesalius/data/mask.py
@@ -245,7 +245,7 @@ class Mask(): @@ -245,7 +245,7 @@ class Mask():
245 mask['mask_shape'] = self.matrix.shape 245 mask['mask_shape'] = self.matrix.shape
246 mask['edited'] = self.was_edited 246 mask['edited'] = self.was_edited
247 247
248 - plist_filename = filename + '.plist' 248 + plist_filename = filename + u'.plist'
249 #plist_filepath = os.path.join(dir_temp, plist_filename) 249 #plist_filepath = os.path.join(dir_temp, plist_filename)
250 250
251 temp_plist = tempfile.mktemp() 251 temp_plist = tempfile.mktemp()
invesalius/data/polydata_utils.py
@@ -23,7 +23,18 @@ import vtk @@ -23,7 +23,18 @@ import vtk
23 import wx 23 import wx
24 from wx.lib.pubsub import pub as Publisher 24 from wx.lib.pubsub import pub as Publisher
25 25
  26 +import invesalius.constants as const
26 import invesalius.data.vtk_utils as vu 27 import invesalius.data.vtk_utils as vu
  28 +from invesalius.utils import touch
  29 +
  30 +if sys.platform == 'win32':
  31 + try:
  32 + import win32api
  33 + _has_win32api = True
  34 + except ImportError:
  35 + _has_win32api = False
  36 +else:
  37 + _has_win32api = False
27 38
28 # Update progress value in GUI 39 # Update progress value in GUI
29 UpdateProgress = vu.ShowProgress() 40 UpdateProgress = vu.ShowProgress()
@@ -109,8 +120,10 @@ def Merge(polydata_list): @@ -109,8 +120,10 @@ def Merge(polydata_list):
109 120
110 def Export(polydata, filename, bin=False): 121 def Export(polydata, filename, bin=False):
111 writer = vtk.vtkXMLPolyDataWriter() 122 writer = vtk.vtkXMLPolyDataWriter()
112 - print filename, type(filename)  
113 - writer.SetFileName(filename.encode('utf-8')) 123 + if _has_win32api:
  124 + touch(filename)
  125 + filename = win32api.GetShortPathName(filename)
  126 + writer.SetFileName(filename.encode(const.FS_ENCODE))
114 if bin: 127 if bin:
115 writer.SetDataModeToBinary() 128 writer.SetDataModeToBinary()
116 else: 129 else:
invesalius/data/surface.py
@@ -21,6 +21,8 @@ import multiprocessing @@ -21,6 +21,8 @@ import multiprocessing
21 import os 21 import os
22 import plistlib 22 import plistlib
23 import random 23 import random
  24 +import shutil
  25 +import sys
24 import tempfile 26 import tempfile
25 import weakref 27 import weakref
26 28
@@ -28,6 +30,15 @@ import vtk @@ -28,6 +30,15 @@ import vtk
28 import wx 30 import wx
29 from wx.lib.pubsub import pub as Publisher 31 from wx.lib.pubsub import pub as Publisher
30 32
  33 +if sys.platform == 'win32':
  34 + try:
  35 + import win32api
  36 + _has_win32api = True
  37 + except ImportError:
  38 + _has_win32api = False
  39 +else:
  40 + _has_win32api = False
  41 +
31 import invesalius.constants as const 42 import invesalius.constants as const
32 import invesalius.data.imagedata_utils as iu 43 import invesalius.data.imagedata_utils as iu
33 import invesalius.data.polydata_utils as pu 44 import invesalius.data.polydata_utils as pu
@@ -64,8 +75,8 @@ class Surface(): @@ -64,8 +75,8 @@ class Surface():
64 self.name = name 75 self.name = name
65 76
66 def SavePlist(self, dir_temp, filelist): 77 def SavePlist(self, dir_temp, filelist):
67 - filename = 'surface_%d' % self.index  
68 - vtp_filename = filename + '.vtp' 78 + filename = u'surface_%d' % self.index
  79 + vtp_filename = filename + u'.vtp'
69 vtp_filepath = os.path.join(dir_temp, vtp_filename) 80 vtp_filepath = os.path.join(dir_temp, vtp_filename)
70 pu.Export(self.polydata, vtp_filepath, bin=True) 81 pu.Export(self.polydata, vtp_filepath, bin=True)
71 82
@@ -80,7 +91,7 @@ class Surface(): @@ -80,7 +91,7 @@ class Surface():
80 'volume': self.volume, 91 'volume': self.volume,
81 'area': self.area, 92 'area': self.area,
82 } 93 }
83 - plist_filename = filename + '.plist' 94 + plist_filename = filename + u'.plist'
84 #plist_filepath = os.path.join(dir_temp, filename + '.plist') 95 #plist_filepath = os.path.join(dir_temp, filename + '.plist')
85 temp_plist = tempfile.mktemp() 96 temp_plist = tempfile.mktemp()
86 plistlib.writePlist(surface, temp_plist) 97 plistlib.writePlist(surface, temp_plist)
@@ -263,7 +274,11 @@ class SurfaceManager(): @@ -263,7 +274,11 @@ class SurfaceManager():
263 wx.MessageBox(_("File format not reconized by InVesalius"), _("Import surface error")) 274 wx.MessageBox(_("File format not reconized by InVesalius"), _("Import surface error"))
264 return 275 return
265 276
266 - reader.SetFileName(filename) 277 + if _has_win32api:
  278 + reader.SetFileName(win32api.GetShortPathName(filename).encode(const.FS_ENCODE))
  279 + else:
  280 + reader.SetFileName(filename.encode(const.FS_ENCODE))
  281 +
267 reader.Update() 282 reader.Update()
268 polydata = reader.GetOutput() 283 polydata = reader.GetOutput()
269 284
@@ -869,11 +884,31 @@ class SurfaceManager(): @@ -869,11 +884,31 @@ class SurfaceManager():
869 884
870 def OnExportSurface(self, pubsub_evt): 885 def OnExportSurface(self, pubsub_evt):
871 filename, filetype = pubsub_evt.data 886 filename, filetype = pubsub_evt.data
872 - if (filetype == const.FILETYPE_STL) or\  
873 - (filetype == const.FILETYPE_VTP) or\  
874 - (filetype == const.FILETYPE_PLY) or\  
875 - (filetype == const.FILETYPE_STL_ASCII):  
876 - 887 + ftype_prefix = {
  888 + const.FILETYPE_STL: '.stl',
  889 + const.FILETYPE_VTP: '.vtp',
  890 + const.FILETYPE_PLY: '.ply',
  891 + const.FILETYPE_STL_ASCII: '.stl',
  892 + }
  893 + if filetype in ftype_prefix:
  894 + temp_file = tempfile.mktemp(suffix=ftype_prefix[filetype])
  895 +
  896 + if _has_win32api:
  897 + utl.touch(temp_file)
  898 + _temp_file = temp_file
  899 + temp_file = win32api.GetShortPathName(temp_file)
  900 + os.remove(_temp_file)
  901 +
  902 + temp_file = temp_file.decode(const.FS_ENCODE)
  903 + self._export_surface(temp_file, filetype)
  904 +
  905 + shutil.move(temp_file, filename)
  906 +
  907 + def _export_surface(self, filename, filetype):
  908 + if filetype in (const.FILETYPE_STL,
  909 + const.FILETYPE_VTP,
  910 + const.FILETYPE_PLY,
  911 + const.FILETYPE_STL_ASCII):
877 # First we identify all surfaces that are selected 912 # First we identify all surfaces that are selected
878 # (if any) 913 # (if any)
879 proj = prj.Project() 914 proj = prj.Project()
@@ -912,7 +947,9 @@ class SurfaceManager(): @@ -912,7 +947,9 @@ class SurfaceManager():
912 #writer.SetColorModeToUniformCellColor() 947 #writer.SetColorModeToUniformCellColor()
913 #writer.SetColor(255, 0, 0) 948 #writer.SetColor(255, 0, 0)
914 949
915 - if filetype in (const.FILETYPE_STL, const.FILETYPE_PLY): 950 + if filetype in (const.FILETYPE_STL,
  951 + const.FILETYPE_STL_ASCII,
  952 + const.FILETYPE_PLY):
916 # Invert normals 953 # Invert normals
917 normals = vtk.vtkPolyDataNormals() 954 normals = vtk.vtkPolyDataNormals()
918 normals.SetInputData(polydata) 955 normals.SetInputData(polydata)
@@ -923,7 +960,7 @@ class SurfaceManager(): @@ -923,7 +960,7 @@ class SurfaceManager():
923 normals.Update() 960 normals.Update()
924 polydata = normals.GetOutput() 961 polydata = normals.GetOutput()
925 962
926 - filename = filename.encode(wx.GetDefaultPyEncoding()) 963 + filename = filename.encode(const.FS_ENCODE)
927 writer.SetFileName(filename) 964 writer.SetFileName(filename)
928 writer.SetInputData(polydata) 965 writer.SetInputData(polydata)
929 writer.Write() 966 writer.Write()
invesalius/data/viewer_slice.py
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 21
22 import collections 22 import collections
23 import itertools 23 import itertools
  24 +import os
24 import tempfile 25 import tempfile
25 26
26 import numpy as np 27 import numpy as np
@@ -49,6 +50,15 @@ import invesalius.session as ses @@ -49,6 +50,15 @@ import invesalius.session as ses
49 import invesalius.data.converters as converters 50 import invesalius.data.converters as converters
50 import invesalius.data.measures as measures 51 import invesalius.data.measures as measures
51 52
  53 +if sys.platform == 'win32':
  54 + try:
  55 + import win32api
  56 + _has_win32api = True
  57 + except ImportError:
  58 + _has_win32api = False
  59 +else:
  60 + _has_win32api = False
  61 +
52 ID_TO_TOOL_ITEM = {} 62 ID_TO_TOOL_ITEM = {}
53 STR_WL = "WL: %d WW: %d" 63 STR_WL = "WL: %d WW: %d"
54 64
@@ -1250,12 +1260,27 @@ class Viewer(wx.Panel): @@ -1250,12 +1260,27 @@ class Viewer(wx.Panel):
1250 self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_SIZING)) 1260 self.interactor.SetCursor(wx.StockCursor(wx.CURSOR_SIZING))
1251 1261
1252 def OnExportPicture(self, pubsub_evt): 1262 def OnExportPicture(self, pubsub_evt):
1253 - Publisher.sendMessage('Begin busy cursor') 1263 + id, filename, filetype = pubsub_evt.data
  1264 +
  1265 + dict = {"AXIAL": const.AXIAL,
  1266 + "CORONAL": const.CORONAL,
  1267 + "SAGITAL": const.SAGITAL}
  1268 +
  1269 + if id == dict[self.orientation]:
  1270 + Publisher.sendMessage('Begin busy cursor')
  1271 + if _has_win32api:
  1272 + utils.touch(filename)
  1273 + win_filename = win32api.GetShortPathName(filename)
  1274 + self._export_picture(id, win_filename, filetype)
  1275 + else:
  1276 + self._export_picture(id, filename, filetype)
  1277 + Publisher.sendMessage('End busy cursor')
  1278 +
  1279 + def _export_picture(self, id, filename, filetype):
1254 view_prop_list = [] 1280 view_prop_list = []
1255 view_prop_list.append(self.slice_data.box_actor) 1281 view_prop_list.append(self.slice_data.box_actor)
1256 self.slice_data.renderer.RemoveViewProp(self.slice_data.box_actor) 1282 self.slice_data.renderer.RemoveViewProp(self.slice_data.box_actor)
1257 1283
1258 - id, filename, filetype = pubsub_evt.data  
1259 dict = {"AXIAL": const.AXIAL, 1284 dict = {"AXIAL": const.AXIAL,
1260 "CORONAL": const.CORONAL, 1285 "CORONAL": const.CORONAL,
1261 "SAGITAL": const.SAGITAL} 1286 "SAGITAL": const.SAGITAL}
@@ -1294,9 +1319,12 @@ class Viewer(wx.Panel): @@ -1294,9 +1319,12 @@ class Viewer(wx.Panel):
1294 filename = "%s.tif"%filename.strip(".tif") 1319 filename = "%s.tif"%filename.strip(".tif")
1295 1320
1296 writer.SetInputData(image) 1321 writer.SetInputData(image)
1297 - writer.SetFileName(filename) 1322 + writer.SetFileName(filename.encode(const.FS_ENCODE))
1298 writer.Write() 1323 writer.Write()
1299 1324
  1325 + if not os.path.exists(filename):
  1326 + wx.MessageBox(_("InVesalius was not able to export this picture"), _("Export picture error"))
  1327 +
1300 for actor in view_prop_list: 1328 for actor in view_prop_list:
1301 self.slice_data.renderer.AddViewProp(actor) 1329 self.slice_data.renderer.AddViewProp(actor)
1302 1330
@@ -1321,9 +1349,10 @@ class Viewer(wx.Panel): @@ -1321,9 +1349,10 @@ class Viewer(wx.Panel):
1321 del self.slice_data 1349 del self.slice_data
1322 self.slice_data = None 1350 self.slice_data = None
1323 1351
1324 - self.canvas.draw_list = []  
1325 - self.canvas.remove_from_renderer()  
1326 - self.canvas = None 1352 + if self.canvas:
  1353 + self.canvas.draw_list = []
  1354 + self.canvas.remove_from_renderer()
  1355 + self.canvas = None
1327 1356
1328 self.orientation_texts = [] 1357 self.orientation_texts = []
1329 1358
invesalius/data/viewer_volume.py
@@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
20 # detalhes. 20 # detalhes.
21 #-------------------------------------------------------------------------- 21 #--------------------------------------------------------------------------
22 22
  23 +import os
23 import sys 24 import sys
24 25
25 import numpy as np 26 import numpy as np
@@ -37,6 +38,15 @@ import invesalius.style as st @@ -37,6 +38,15 @@ import invesalius.style as st
37 import invesalius.utils as utils 38 import invesalius.utils as utils
38 import invesalius.data.measures as measures 39 import invesalius.data.measures as measures
39 40
  41 +if sys.platform == 'win32':
  42 + try:
  43 + import win32api
  44 + _has_win32api = True
  45 + except ImportError:
  46 + _has_win32api = False
  47 +else:
  48 + _has_win32api = False
  49 +
40 PROP_MEASURE = 0.8 50 PROP_MEASURE = 0.8
41 51
42 class Viewer(wx.Panel): 52 class Viewer(wx.Panel):
@@ -314,15 +324,24 @@ class Viewer(wx.Panel): @@ -314,15 +324,24 @@ class Viewer(wx.Panel):
314 self.seed_points) 324 self.seed_points)
315 325
316 def OnExportPicture(self, pubsub_evt): 326 def OnExportPicture(self, pubsub_evt):
317 - Publisher.sendMessage('Begin busy cursor')  
318 id, filename, filetype = pubsub_evt.data 327 id, filename, filetype = pubsub_evt.data
319 if id == const.VOLUME: 328 if id == const.VOLUME:
  329 + Publisher.sendMessage('Begin busy cursor')
  330 + if _has_win32api:
  331 + utils.touch(filename)
  332 + win_filename = win32api.GetShortPathName(filename)
  333 + self._export_picture(id, win_filename, filetype)
  334 + else:
  335 + self._export_picture(id, filename, filetype)
  336 + Publisher.sendMessage('End busy cursor')
  337 +
  338 + def _export_picture(self, id, filename, filetype):
320 if filetype == const.FILETYPE_POV: 339 if filetype == const.FILETYPE_POV:
321 renwin = self.interactor.GetRenderWindow() 340 renwin = self.interactor.GetRenderWindow()
322 image = vtk.vtkWindowToImageFilter() 341 image = vtk.vtkWindowToImageFilter()
323 image.SetInput(renwin) 342 image.SetInput(renwin)
324 writer = vtk.vtkPOVExporter() 343 writer = vtk.vtkPOVExporter()
325 - writer.SetFileName(filename) 344 + writer.SetFileName(filename.encode(const.FS_ENCODE))
326 writer.SetRenderWindow(renwin) 345 writer.SetRenderWindow(renwin)
327 writer.Write() 346 writer.Write()
328 else: 347 else:
@@ -345,12 +364,15 @@ class Viewer(wx.Panel): @@ -345,12 +364,15 @@ class Viewer(wx.Panel):
345 writer = vtk.vtkPostScriptWriter() 364 writer = vtk.vtkPostScriptWriter()
346 elif (filetype == const.FILETYPE_TIF): 365 elif (filetype == const.FILETYPE_TIF):
347 writer = vtk.vtkTIFFWriter() 366 writer = vtk.vtkTIFFWriter()
348 - filename = "%s.tif"%filename.strip(".tif") 367 + filename = u"%s.tif"%filename.strip(".tif")
349 368
350 writer.SetInputData(image) 369 writer.SetInputData(image)
351 - writer.SetFileName(filename) 370 + writer.SetFileName(filename.encode(const.FS_ENCODE))
352 writer.Write() 371 writer.Write()
353 - Publisher.sendMessage('End busy cursor') 372 +
  373 + if not os.path.exists(filename):
  374 + wx.MessageBox(_("InVesalius was not able to export this picture"), _("Export picture error"))
  375 +
354 376
355 def OnCloseProject(self, pubsub_evt): 377 def OnCloseProject(self, pubsub_evt):
356 if self.raycasting_volume: 378 if self.raycasting_volume:
@@ -764,6 +786,18 @@ class Viewer(wx.Panel): @@ -764,6 +786,18 @@ class Viewer(wx.Panel):
764 786
765 def OnExportSurface(self, pubsub_evt): 787 def OnExportSurface(self, pubsub_evt):
766 filename, filetype = pubsub_evt.data 788 filename, filetype = pubsub_evt.data
  789 + if filetype not in (const.FILETYPE_STL,
  790 + const.FILETYPE_VTP,
  791 + const.FILETYPE_PLY,
  792 + const.FILETYPE_STL_ASCII):
  793 + if _has_win32api:
  794 + utils.touch(filename)
  795 + win_filename = win32api.GetShortPathName(filename)
  796 + self._export_surface(win_filename.encode(const.FS_ENCODE), filetype)
  797 + else:
  798 + self._export_surface(filename.encode(const.FS_ENCODE), filetype)
  799 +
  800 + def _export_surface(self, filename, filetype):
767 fileprefix = filename.split(".")[-2] 801 fileprefix = filename.split(".")[-2]
768 renwin = self.interactor.GetRenderWindow() 802 renwin = self.interactor.GetRenderWindow()
769 803
invesalius/expanduser.py 0 → 100644
@@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
  1 +#!/usr/bin/python
  2 +# -*- coding: utf-8 -*-
  3 +# From http://bugs.python.org/file23442/expanduser.py
  4 +
  5 +import ctypes
  6 +from ctypes import windll, wintypes
  7 +
  8 +class GUID(ctypes.Structure):
  9 + _fields_ = [
  10 + ('Data1', wintypes.DWORD),
  11 + ('Data2', wintypes.WORD),
  12 + ('Data3', wintypes.WORD),
  13 + ('Data4', wintypes.BYTE * 8)
  14 + ]
  15 +
  16 + def __init__(self, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8):
  17 + """Create a new GUID."""
  18 + self.Data1 = l
  19 + self.Data2 = w1
  20 + self.Data3 = w2
  21 + self.Data4[:] = (b1, b2, b3, b4, b5, b6, b7, b8)
  22 +
  23 + def __repr__(self):
  24 + b1, b2, b3, b4, b5, b6, b7, b8 = self.Data4
  25 + return 'GUID(%x-%x-%x-%x%x%x%x%x%x%x%x)' % (
  26 + self.Data1, self.Data2, self.Data3, b1, b2, b3, b4, b5, b6, b7, b8)
  27 +
  28 +# constants to be used according to the version on shell32
  29 +CSIDL_PROFILE = 40
  30 +FOLDERID_Profile = GUID(0x5E6C858F, 0x0E22, 0x4760, 0x9A, 0xFE, 0xEA, 0x33, 0x17, 0xB6, 0x71, 0x73)
  31 +
  32 +def expand_user():
  33 + # get the function that we can find from Vista up, not the one in XP
  34 + get_folder_path = getattr(windll.shell32, 'SHGetKnownFolderPath', None)
  35 + #import pdb; pdb.set_trace()
  36 + if get_folder_path is not None:
  37 + # ok, we can use the new function which is recomended by the msdn
  38 + ptr = ctypes.c_wchar_p()
  39 + get_folder_path(ctypes.byref(FOLDERID_Profile), 0, 0, ctypes.byref(ptr))
  40 + return ptr.value
  41 + else:
  42 + # use the deprecated one found in XP and on for compatibility reasons
  43 + get_folder_path = getattr(windll.shell32, 'SHGetSpecialFolderPathW', None)
  44 + buf = ctypes.create_unicode_buffer(300)
  45 + get_folder_path(None, buf, CSIDL_PROFILE, False)
  46 + return buf.value
invesalius/gui/dialogs.py
@@ -323,10 +323,7 @@ def ShowImportBitmapDirDialog(): @@ -323,10 +323,7 @@ def ShowImportBitmapDirDialog():
323 if dlg.ShowModal() == wx.ID_OK: 323 if dlg.ShowModal() == wx.ID_OK:
324 # GetPath returns in unicode, if a path has non-ascii characters a 324 # GetPath returns in unicode, if a path has non-ascii characters a
325 # UnicodeEncodeError is raised. To avoid this, path is encoded in utf-8 325 # UnicodeEncodeError is raised. To avoid this, path is encoded in utf-8
326 - if sys.platform == "win32":  
327 - path = dlg.GetPath()  
328 - else:  
329 - path = dlg.GetPath().encode('utf-8') 326 + path = dlg.GetPath()
330 327
331 except(wx._core.PyAssertionError): #TODO: error win64 328 except(wx._core.PyAssertionError): #TODO: error win64
332 if (dlg.GetPath()): 329 if (dlg.GetPath()):
@@ -398,12 +395,7 @@ def ShowImportMeshFilesDialog(): @@ -398,12 +395,7 @@ def ShowImportMeshFilesDialog():
398 filename = None 395 filename = None
399 try: 396 try:
400 if dlg.ShowModal() == wx.ID_OK: 397 if dlg.ShowModal() == wx.ID_OK:
401 - # GetPath returns in unicode, if a path has non-ascii characters a  
402 - # UnicodeEncodeError is raised. To avoid this, path is encoded in utf-8  
403 - if sys.platform == "win32":  
404 - filename = dlg.GetPath()  
405 - else:  
406 - filename = dlg.GetPath().encode('utf-8') 398 + filename = dlg.GetPath()
407 399
408 except(wx._core.PyAssertionError): # TODO: error win64 400 except(wx._core.PyAssertionError): # TODO: error win64
409 if (dlg.GetPath()): 401 if (dlg.GetPath()):
@@ -1058,52 +1050,52 @@ def ShowAboutDialog(parent): @@ -1058,52 +1050,52 @@ def ShowAboutDialog(parent):
1058 info.WebSite = ("https://www.cti.gov.br/invesalius") 1050 info.WebSite = ("https://www.cti.gov.br/invesalius")
1059 info.License = _("GNU GPL (General Public License) version 2") 1051 info.License = _("GNU GPL (General Public License) version 2")
1060 1052
1061 - info.Developers = ["Paulo Henrique Junqueira Amorim",  
1062 - "Thiago Franco de Moraes",  
1063 - "Hélio Pedrini",  
1064 - "Jorge Vicente Lopes da Silva",  
1065 - "Victor Hugo de Oliveira e Souza (navigator)",  
1066 - "Renan Hiroshi Matsuda (navigator)",  
1067 - "André Salles Cunha Peres (navigator)",  
1068 - "Oswaldo Baffa Filho (navigator)",  
1069 - "Tatiana Al-Chueyr (former)",  
1070 - "Guilherme Cesar Soares Ruppert (former)",  
1071 - "Fabio de Souza Azevedo (former)",  
1072 - "Bruno Lara Bottazzini (contributor)",  
1073 - "Olly Betts (patches to support wxPython3)"]  
1074 -  
1075 - info.Translators = ["Alex P. Natsios",  
1076 - "Alicia Perez",  
1077 - "Anderson Antonio Mamede da Silva",  
1078 - "Andreas Loupasakis",  
1079 - "Angelo Pucillo",  
1080 - "Annalisa Manenti",  
1081 - "Cheng-Chia Tseng",  
1082 - "Dan",  
1083 - "DCamer",  
1084 - "Dimitris Glezos",  
1085 - "Eugene Liscio", 1053 + info.Developers = [u"Paulo Henrique Junqueira Amorim",
  1054 + u"Thiago Franco de Moraes",
  1055 + u"Hélio Pedrini",
  1056 + u"Jorge Vicente Lopes da Silva",
  1057 + u"Victor Hugo de Oliveira e Souza (navigator)",
  1058 + u"Renan Hiroshi Matsuda (navigator)",
  1059 + u"André Salles Cunha Peres (navigator)",
  1060 + u"Oswaldo Baffa Filho (navigator)",
  1061 + u"Tatiana Al-Chueyr (former)",
  1062 + u"Guilherme Cesar Soares Ruppert (former)",
  1063 + u"Fabio de Souza Azevedo (former)",
  1064 + u"Bruno Lara Bottazzini (contributor)",
  1065 + u"Olly Betts (patches to support wxPython3)"]
  1066 +
  1067 + info.Translators = [u"Alex P. Natsios",
  1068 + u"Alicia Perez",
  1069 + u"Anderson Antonio Mamede da Silva",
  1070 + u"Andreas Loupasakis",
  1071 + u"Angelo Pucillo",
  1072 + u"Annalisa Manenti",
  1073 + u"Cheng-Chia Tseng",
  1074 + u"Dan",
  1075 + u"DCamer",
  1076 + u"Dimitris Glezos",
  1077 + u"Eugene Liscio",
1086 u"Frédéric Lopez", 1078 u"Frédéric Lopez",
1087 - "Florin Putura",  
1088 - "Fri",  
1089 - "Jangblue",  
1090 - "Javier de Lima Moreno",  
1091 - "Kensey Okinawa",  
1092 - "Maki Sugimoto",  
1093 - "Mario Regino Moreno Guerra",  
1094 - "Massimo Crisantemo",  
1095 - "Nikos Korkakakis",  
1096 - "Raul Bolliger Neto",  
1097 - "Sebastian Hilbert",  
1098 - "Semarang Pari",  
1099 - "Silvério Santos",  
1100 - "Vasily Shishkin",  
1101 - "Yohei Sotsuka",  
1102 - "Yoshihiro Sato"] 1079 + u"Florin Putura",
  1080 + u"Fri",
  1081 + u"Jangblue",
  1082 + u"Javier de Lima Moreno",
  1083 + u"Kensey Okinawa",
  1084 + u"Maki Sugimoto",
  1085 + u"Mario Regino Moreno Guerra",
  1086 + u"Massimo Crisantemo",
  1087 + u"Nikos Korkakakis",
  1088 + u"Raul Bolliger Neto",
  1089 + u"Sebastian Hilbert",
  1090 + u"Semarang Pari",
  1091 + u"Silvério Santos",
  1092 + u"Vasily Shishkin",
  1093 + u"Yohei Sotsuka",
  1094 + u"Yoshihiro Sato"]
1103 1095
1104 #info.DocWriters = ["Fabio Francisco da Silva (PT)"] 1096 #info.DocWriters = ["Fabio Francisco da Silva (PT)"]
1105 1097
1106 - info.Artists = ["Otavio Henrique Junqueira Amorim"] 1098 + info.Artists = [u"Otavio Henrique Junqueira Amorim"]
1107 1099
1108 # Then we call wx.AboutBox providing its info object 1100 # Then we call wx.AboutBox providing its info object
1109 wx.AboutBox(info) 1101 wx.AboutBox(info)
invesalius/gui/dicom_preview_panel.py
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 # -*- coding: UTF-8 -*- 21 # -*- coding: UTF-8 -*-
22 22
23 #TODO: To create a beautiful API 23 #TODO: To create a beautiful API
  24 +import sys
24 import time 25 import time
25 import tempfile 26 import tempfile
26 27
@@ -37,6 +38,14 @@ import invesalius.data.vtk_utils as vtku @@ -37,6 +38,14 @@ import invesalius.data.vtk_utils as vtku
37 import invesalius.utils as utils 38 import invesalius.utils as utils
38 import vtkgdcm 39 import vtkgdcm
39 40
  41 +if sys.platform == 'win32':
  42 + try:
  43 + import win32api
  44 + _has_win32api = True
  45 + except ImportError:
  46 + _has_win32api = False
  47 +else:
  48 + _has_win32api = False
40 49
41 NROWS = 3 50 NROWS = 3
42 NCOLS = 6 51 NCOLS = 6
@@ -837,7 +846,10 @@ class SingleImagePreview(wx.Panel): @@ -837,7 +846,10 @@ class SingleImagePreview(wx.Panel):
837 self.text_acquisition.SetValue(value) 846 self.text_acquisition.SetValue(value)
838 847
839 rdicom = vtkgdcm.vtkGDCMImageReader() 848 rdicom = vtkgdcm.vtkGDCMImageReader()
840 - rdicom.SetFileName(dicom.image.file) 849 + if _has_win32api:
  850 + rdicom.SetFileName(win32api.GetShortPathName(dicom.image.file).encode(const.FS_ENCODE))
  851 + else:
  852 + rdicom.SetFileName(dicom.image.file)
841 rdicom.Update() 853 rdicom.Update()
842 854
843 # ADJUST CONTRAST 855 # ADJUST CONTRAST
invesalius/gui/task_exporter.py
@@ -331,6 +331,13 @@ class InnerTaskPanel(wx.Panel): @@ -331,6 +331,13 @@ class InnerTaskPanel(wx.Panel):
331 filename = filename + "."+ extension 331 filename = filename + "."+ extension
332 Publisher.sendMessage('Export surface to file', 332 Publisher.sendMessage('Export surface to file',
333 (filename, filetype)) 333 (filename, filetype))
  334 + if not os.path.exists(filename):
  335 + dlg = wx.MessageDialog(None,
  336 + _("It was not possible to save the surface."),
  337 + _("Error saving surface"),
  338 + wx.OK | wx.ICON_ERROR)
  339 + dlg.ShowModal()
  340 + dlg.Destroy()
334 else: 341 else:
335 dlg = wx.MessageDialog(None, 342 dlg = wx.MessageDialog(None,
336 _("You need to create a surface and make it ") + 343 _("You need to create a surface and make it ") +
invesalius/project.py
@@ -22,6 +22,7 @@ import glob @@ -22,6 +22,7 @@ import glob
22 import os 22 import os
23 import plistlib 23 import plistlib
24 import shutil 24 import shutil
  25 +import sys
25 import tarfile 26 import tarfile
26 import tempfile 27 import tempfile
27 28
@@ -32,9 +33,18 @@ import vtk @@ -32,9 +33,18 @@ import vtk
32 import invesalius.constants as const 33 import invesalius.constants as const
33 import invesalius.data.polydata_utils as pu 34 import invesalius.data.polydata_utils as pu
34 from invesalius.presets import Presets 35 from invesalius.presets import Presets
35 -from invesalius.utils import Singleton, debug 36 +from invesalius.utils import Singleton, debug, touch
36 import invesalius.version as version 37 import invesalius.version as version
37 38
  39 +if sys.platform == 'win32':
  40 + try:
  41 + import win32api
  42 + _has_win32api = True
  43 + except ImportError:
  44 + _has_win32api = False
  45 +else:
  46 + _has_win32api = False
  47 +
38 class Project(object): 48 class Project(object):
39 # Only one project will be initialized per time. Therefore, we use 49 # Only one project will be initialized per time. Therefore, we use
40 # Singleton design pattern for implementing it 50 # Singleton design pattern for implementing it
@@ -193,10 +203,14 @@ class Project(object): @@ -193,10 +203,14 @@ class Project(object):
193 return measures 203 return measures
194 204
195 def SavePlistProject(self, dir_, filename): 205 def SavePlistProject(self, dir_, filename):
196 - dir_temp = tempfile.mkdtemp()  
197 - filename_tmp = os.path.join(dir_temp, 'matrix.dat') 206 + dir_temp = tempfile.mkdtemp().decode(const.FS_ENCODE)
  207 +
  208 + filename_tmp = os.path.join(dir_temp, u'matrix.dat')
198 filelist = {} 209 filelist = {}
199 210
  211 + print type(dir_temp), type(filename)
  212 + print filename.encode('utf8'), dir_.encode('utf8'), type(filename), type(dir_)
  213 +
200 project = { 214 project = {
201 # Format info 215 # Format info
202 "format_version": 1, 216 "format_version": 1,
@@ -214,10 +228,11 @@ class Project(object): @@ -214,10 +228,11 @@ class Project(object):
214 } 228 }
215 229
216 # Saving the matrix containing the slices 230 # Saving the matrix containing the slices
217 - matrix = {'filename': u'matrix.dat',  
218 - 'shape': self.matrix_shape,  
219 - 'dtype': self.matrix_dtype,  
220 - } 231 + matrix = {
  232 + 'filename': u'matrix.dat',
  233 + 'shape': self.matrix_shape,
  234 + 'dtype': self.matrix_dtype,
  235 + }
221 project['matrix'] = matrix 236 project['matrix'] = matrix
222 filelist[self.matrix_filename] = 'matrix.dat' 237 filelist[self.matrix_filename] = 'matrix.dat'
223 #shutil.copyfile(self.matrix_filename, filename_tmp) 238 #shutil.copyfile(self.matrix_filename, filename_tmp)
@@ -270,9 +285,9 @@ class Project(object): @@ -270,9 +285,9 @@ class Project(object):
270 import invesalius.data.surface as srf 285 import invesalius.data.surface as srf
271 286
272 if not const.VTK_WARNING: 287 if not const.VTK_WARNING:
273 - log_path = os.path.join(const.LOG_FOLDER, 'vtkoutput.txt') 288 + log_path = os.path.join(const.USER_LOG_DIR, 'vtkoutput.txt')
274 fow = vtk.vtkFileOutputWindow() 289 fow = vtk.vtkFileOutputWindow()
275 - fow.SetFileName(log_path) 290 + fow.SetFileName(log_path.encode(const.FS_ENCODE))
276 ow = vtk.vtkOutputWindow() 291 ow = vtk.vtkOutputWindow()
277 ow.SetInstance(fow) 292 ow.SetInstance(fow)
278 293
@@ -328,29 +343,37 @@ class Project(object): @@ -328,29 +343,37 @@ class Project(object):
328 def Compress(folder, filename, filelist): 343 def Compress(folder, filename, filelist):
329 tmpdir, tmpdir_ = os.path.split(folder) 344 tmpdir, tmpdir_ = os.path.split(folder)
330 current_dir = os.path.abspath(".") 345 current_dir = os.path.abspath(".")
  346 + temp_inv3 = tempfile.mktemp()
  347 + if _has_win32api:
  348 + touch(temp_inv3)
  349 + temp_inv3 = win32api.GetShortPathName(temp_inv3)
  350 +
  351 + temp_inv3 = temp_inv3.decode(const.FS_ENCODE)
331 #os.chdir(tmpdir) 352 #os.chdir(tmpdir)
332 #file_list = glob.glob(os.path.join(tmpdir_,"*")) 353 #file_list = glob.glob(os.path.join(tmpdir_,"*"))
333 - tar_filename = tmpdir_ + ".inv3"  
334 - tar = tarfile.open(filename.encode(wx.GetDefaultPyEncoding()), "w:gz") 354 + print "Tar file", temp_inv3, type(temp_inv3), filename.encode('utf8'), type(filename)
  355 + tar = tarfile.open(temp_inv3, "w:gz")
335 for name in filelist: 356 for name in filelist:
336 tar.add(name, arcname=os.path.join(tmpdir_, filelist[name])) 357 tar.add(name, arcname=os.path.join(tmpdir_, filelist[name]))
337 tar.close() 358 tar.close()
338 - #shutil.move(tmpdir_+ ".inv3", filename) 359 + shutil.move(temp_inv3, filename)
339 #os.chdir(current_dir) 360 #os.chdir(current_dir)
340 361
  362 +
341 def Extract(filename, folder): 363 def Extract(filename, folder):
  364 + if _has_win32api:
  365 + folder = win32api.GetShortPathName(folder)
  366 + folder = folder.decode(const.FS_ENCODE)
  367 +
342 tar = tarfile.open(filename, "r:gz") 368 tar = tarfile.open(filename, "r:gz")
343 - idir = os.path.split(tar.getnames()[0])[0]  
344 - os.mkdir(os.path.join(folder, idir.decode('utf8'))) 369 + idir = os.path.split(tar.getnames()[0])[0].decode('utf8')
  370 + os.mkdir(os.path.join(folder, idir))
345 filelist = [] 371 filelist = []
346 for t in tar.getmembers(): 372 for t in tar.getmembers():
347 fsrc = tar.extractfile(t) 373 fsrc = tar.extractfile(t)
348 -  
349 fname = os.path.join(folder, t.name.decode('utf-8')) 374 fname = os.path.join(folder, t.name.decode('utf-8'))
350 fdst = file(fname, 'wb') 375 fdst = file(fname, 'wb')
351 -  
352 shutil.copyfileobj(fsrc, fdst) 376 shutil.copyfileobj(fsrc, fdst)
353 -  
354 filelist.append(fname) 377 filelist.append(fname)
355 fsrc.close() 378 fsrc.close()
356 fdst.close() 379 fdst.close()
@@ -359,7 +382,7 @@ def Extract(filename, folder): @@ -359,7 +382,7 @@ def Extract(filename, folder):
359 tar.close() 382 tar.close()
360 return filelist 383 return filelist
361 384
362 - 385 +
363 def Extract_(filename, folder): 386 def Extract_(filename, folder):
364 tar = tarfile.open(filename, "r:gz") 387 tar = tarfile.open(filename, "r:gz")
365 #tar.list(verbose=True) 388 #tar.list(verbose=True)
invesalius/reader/bitmap_reader.py
@@ -40,6 +40,15 @@ import invesalius.data.converters as converters @@ -40,6 +40,15 @@ import invesalius.data.converters as converters
40 no_error = True 40 no_error = True
41 vtk_error = False 41 vtk_error = False
42 42
  43 +if sys.platform == 'win32':
  44 + try:
  45 + import win32api
  46 + _has_win32api = True
  47 + except ImportError:
  48 + _has_win32api = False
  49 +else:
  50 + _has_win32api = False
  51 +
43 class Singleton: 52 class Singleton:
44 53
45 def __init__(self,klass): 54 def __init__(self,klass):
@@ -127,10 +136,7 @@ class LoadBitmap: @@ -127,10 +136,7 @@ class LoadBitmap:
127 136
128 def __init__(self, bmp_file, filepath): 137 def __init__(self, bmp_file, filepath):
129 self.bmp_file = bmp_file 138 self.bmp_file = bmp_file
130 - if sys.platform == 'win32':  
131 - self.filepath = filepath.encode(utils.get_system_encoding())  
132 - else:  
133 - self.filepath = filepath 139 + self.filepath = filepath
134 140
135 self.run() 141 self.run()
136 142
@@ -294,9 +300,9 @@ def ScipyRead(filepath): @@ -294,9 +300,9 @@ def ScipyRead(filepath):
294 300
295 def VtkRead(filepath, t): 301 def VtkRead(filepath, t):
296 if not const.VTK_WARNING: 302 if not const.VTK_WARNING:
297 - log_path = os.path.join(const.LOG_FOLDER, 'vtkoutput.txt') 303 + log_path = os.path.join(const.USER_LOG_DIR, 'vtkoutput.txt')
298 fow = vtk.vtkFileOutputWindow() 304 fow = vtk.vtkFileOutputWindow()
299 - fow.SetFileName(log_path) 305 + fow.SetFileName(log_path.encode(const.FS_ENCODE))
300 ow = vtk.vtkOutputWindow() 306 ow = vtk.vtkOutputWindow()
301 ow.SetInstance(fow) 307 ow.SetInstance(fow)
302 308
@@ -317,8 +323,10 @@ def VtkRead(filepath, t): @@ -317,8 +323,10 @@ def VtkRead(filepath, t):
317 else: 323 else:
318 return False 324 return False
319 325
  326 + print ">>>> bmp reader", type(filepath)
  327 +
320 reader.AddObserver("ErrorEvent", VtkErrorToPy) 328 reader.AddObserver("ErrorEvent", VtkErrorToPy)
321 - reader.SetFileName(filepath) 329 + reader.SetFileName(filepath.encode(const.FS_ENCODE))
322 reader.Update() 330 reader.Update()
323 331
324 if no_error: 332 if no_error:
@@ -345,6 +353,9 @@ def VtkRead(filepath, t): @@ -345,6 +353,9 @@ def VtkRead(filepath, t):
345 def ReadBitmap(filepath): 353 def ReadBitmap(filepath):
346 t = VerifyDataType(filepath) 354 t = VerifyDataType(filepath)
347 355
  356 + if _has_win32api:
  357 + filepath = win32api.GetShortPathName(filepath)
  358 +
348 if t == False: 359 if t == False:
349 measures_info = GetPixelSpacingFromInfoFile(filepath) 360 measures_info = GetPixelSpacingFromInfoFile(filepath)
350 361
@@ -368,7 +379,6 @@ def ReadBitmap(filepath): @@ -368,7 +379,6 @@ def ReadBitmap(filepath):
368 379
369 380
370 def GetPixelSpacingFromInfoFile(filepath): 381 def GetPixelSpacingFromInfoFile(filepath):
371 -  
372 fi = open(filepath, 'r') 382 fi = open(filepath, 'r')
373 lines = fi.readlines() 383 lines = fi.readlines()
374 measure_scale = 'mm' 384 measure_scale = 'mm'
invesalius/reader/dicom_grouper.py
@@ -51,9 +51,23 @@ @@ -51,9 +51,23 @@
51 # <dicom.image.number> and <dicom.acquisition.series_number> 51 # <dicom.image.number> and <dicom.acquisition.series_number>
52 # were swapped 52 # were swapped
53 53
  54 +import sys
  55 +
54 import gdcm 56 import gdcm
55 57
  58 +if sys.platform == 'win32':
  59 + try:
  60 + import win32api
  61 + _has_win32api = True
  62 + except ImportError:
  63 + _has_win32api = False
  64 +else:
  65 + _has_win32api = False
  66 +
56 import invesalius.utils as utils 67 import invesalius.utils as utils
  68 +import invesalius.constants as const
  69 +
  70 +
57 ORIENT_MAP = {"SAGITTAL":0, "CORONAL":1, "AXIAL":2, "OBLIQUE":2} 71 ORIENT_MAP = {"SAGITTAL":0, "CORONAL":1, "AXIAL":2, "OBLIQUE":2}
58 72
59 73
@@ -109,8 +123,13 @@ class DicomGroup: @@ -109,8 +123,13 @@ class DicomGroup:
109 # This list will be used to create the vtkImageData 123 # This list will be used to create the vtkImageData
110 # (interpolated) 124 # (interpolated)
111 125
112 - filelist = [dicom.image.file for dicom in  
113 - self.slices_dict.values()] 126 + if _has_win32api:
  127 + filelist = [win32api.GetShortPathName(dicom.image.file).encode(const.FS_ENCODE)
  128 + for dicom in
  129 + self.slices_dict.values()]
  130 + else:
  131 + filelist = [dicom.image.file for dicom in
  132 + self.slices_dict.values()]
114 133
115 # Sort slices using GDCM 134 # Sort slices using GDCM
116 if (self.dicom.image.orientation_label <> "CORONAL"): 135 if (self.dicom.image.orientation_label <> "CORONAL"):
invesalius/reader/dicom_reader.py
@@ -38,6 +38,15 @@ import invesalius.utils as utils @@ -38,6 +38,15 @@ import invesalius.utils as utils
38 38
39 import plistlib 39 import plistlib
40 40
  41 +if sys.platform == 'win32':
  42 + try:
  43 + import win32api
  44 + _has_win32api = True
  45 + except ImportError:
  46 + _has_win32api = False
  47 +else:
  48 + _has_win32api = False
  49 +
41 def ReadDicomGroup(dir_): 50 def ReadDicomGroup(dir_):
42 51
43 patient_group = GetDicomGroups(dir_) 52 patient_group = GetDicomGroups(dir_)
@@ -88,18 +97,18 @@ class LoadDicom: @@ -88,18 +97,18 @@ class LoadDicom:
88 97
89 def __init__(self, grouper, filepath): 98 def __init__(self, grouper, filepath):
90 self.grouper = grouper 99 self.grouper = grouper
91 - if sys.platform == 'win32':  
92 - self.filepath = filepath.encode(utils.get_system_encoding())  
93 - else:  
94 - self.filepath = filepath 100 + self.filepath = filepath
95 101
96 self.run() 102 self.run()
97 103
98 def run(self): 104 def run(self):
99 -  
100 grouper = self.grouper 105 grouper = self.grouper
101 reader = gdcm.ImageReader() 106 reader = gdcm.ImageReader()
102 - reader.SetFileName(self.filepath) 107 + if _has_win32api:
  108 + reader.SetFileName(win32api.GetShortPathName(self.filepath).encode(const.FS_ENCODE))
  109 + else:
  110 + reader.SetFileName(self.filepath)
  111 +
103 if (reader.Read()): 112 if (reader.Read()):
104 file = reader.GetFile() 113 file = reader.GetFile()
105 114
@@ -180,7 +189,12 @@ class LoadDicom: @@ -180,7 +189,12 @@ class LoadDicom:
180 189
181 # -------------- To Create DICOM Thumbnail ----------- 190 # -------------- To Create DICOM Thumbnail -----------
182 rvtk = vtkgdcm.vtkGDCMImageReader() 191 rvtk = vtkgdcm.vtkGDCMImageReader()
183 - rvtk.SetFileName(self.filepath) 192 +
  193 + if _has_win32api:
  194 + print 'dicom', win32api.GetShortPathName(self.filepath)
  195 + rvtk.SetFileName(win32api.GetShortPathName(self.filepath).encode(const.FS_ENCODE))
  196 + else:
  197 + rvtk.SetFileName(self.filepath)
184 rvtk.Update() 198 rvtk.Update()
185 199
186 try: 200 try:
@@ -341,7 +355,7 @@ class ProgressDicomReader: @@ -341,7 +355,7 @@ class ProgressDicomReader:
341 def GetDicomGroups(self, path, recursive): 355 def GetDicomGroups(self, path, recursive):
342 356
343 if not const.VTK_WARNING: 357 if not const.VTK_WARNING:
344 - log_path = os.path.join(const.LOG_FOLDER, 'vtkoutput.txt') 358 + log_path = os.path.join(const.USER_LOG_DIR, 'vtkoutput.txt').encode(const.FS_ENCODE)
345 fow = vtk.vtkFileOutputWindow() 359 fow = vtk.vtkFileOutputWindow()
346 fow.SetFileName(log_path) 360 fow.SetFileName(log_path)
347 ow = vtk.vtkOutputWindow() 361 ow = vtk.vtkOutputWindow()
invesalius/reader/others_reader.py
@@ -38,9 +38,9 @@ def ReadOthers(dir_): @@ -38,9 +38,9 @@ def ReadOthers(dir_):
38 """ 38 """
39 39
40 if not const.VTK_WARNING: 40 if not const.VTK_WARNING:
41 - log_path = os.path.join(const.LOG_FOLDER, 'vtkoutput.txt') 41 + log_path = os.path.join(const.USER_LOG_DIR, 'vtkoutput.txt')
42 fow = vtk.vtkFileOutputWindow() 42 fow = vtk.vtkFileOutputWindow()
43 - fow.SetFileName(log_path) 43 + fow.SetFileName(log_path.encode(const.FS_ENCODE))
44 ow = vtk.vtkOutputWindow() 44 ow = vtk.vtkOutputWindow()
45 ow.SetInstance(fow) 45 ow.SetInstance(fow)
46 46
invesalius/session.py
@@ -36,7 +36,24 @@ import wx @@ -36,7 +36,24 @@ import wx
36 from invesalius.utils import Singleton, debug 36 from invesalius.utils import Singleton, debug
37 from random import randint 37 from random import randint
38 38
39 -ENCODE=wx.GetDefaultPyEncoding() 39 +FS_ENCODE = sys.getfilesystemencoding()
  40 +
  41 +if sys.platform == 'win32':
  42 + from invesalius.expanduser import expand_user
  43 + try:
  44 + USER_DIR = expand_user()
  45 + except:
  46 + USER_DIR = os.path.expanduser('~').decode(FS_ENCODE)
  47 +else:
  48 + USER_DIR = os.path.expanduser('~').decode(FS_ENCODE)
  49 +
  50 +USER_INV_DIR = os.path.join(USER_DIR, u'.invesalius')
  51 +USER_PRESET_DIR = os.path.join(USER_INV_DIR, u'presets')
  52 +USER_LOG_DIR = os.path.join(USER_INV_DIR, u'logs')
  53 +USER_INV_CFG_PATH = os.path.join(USER_INV_DIR, 'config.cfg')
  54 +
  55 +SESSION_ENCODING = 'utf8'
  56 +
40 57
41 class Session(object): 58 class Session(object):
42 # Only one session will be initialized per time. Therefore, we use 59 # Only one session will be initialized per time. Therefore, we use
@@ -62,7 +79,7 @@ class Session(object): @@ -62,7 +79,7 @@ class Session(object):
62 # const.MODE_ODONTOLOGY 79 # const.MODE_ODONTOLOGY
63 80
64 # InVesalius default projects' directory 81 # InVesalius default projects' directory
65 - homedir = self.homedir = os.path.expanduser('~').decode(ENCODE) 82 + homedir = self.homedir = USER_DIR
66 tempdir = os.path.join(homedir, u".invesalius", u"temp") 83 tempdir = os.path.join(homedir, u".invesalius", u"temp")
67 if not os.path.isdir(tempdir): 84 if not os.path.isdir(tempdir):
68 os.makedirs(tempdir) 85 os.makedirs(tempdir)
@@ -72,10 +89,9 @@ class Session(object): @@ -72,10 +89,9 @@ class Session(object):
72 self.language = "" # "pt_BR", "es" 89 self.language = "" # "pt_BR", "es"
73 90
74 self.random_id = randint(0,pow(10,16)) 91 self.random_id = randint(0,pow(10,16))
75 - #print self.random_id  
76 92
77 # Recent projects list 93 # Recent projects list
78 - self.recent_projects = [(const.SAMPLE_DIR, "Cranium.inv3")] 94 + self.recent_projects = [(const.SAMPLE_DIR, u"Cranium.inv3")]
79 self.last_dicom_folder = '' 95 self.last_dicom_folder = ''
80 self.surface_interpolation = 1 96 self.surface_interpolation = 1
81 self.slice_interpolation = 0 97 self.slice_interpolation = 0
@@ -88,18 +104,18 @@ class Session(object): @@ -88,18 +104,18 @@ class Session(object):
88 104
89 def SaveConfigFileBackup(self): 105 def SaveConfigFileBackup(self):
90 path = os.path.join(self.homedir , 106 path = os.path.join(self.homedir ,
91 - '.invesalius', 'config.cfg') 107 + u'.invesalius', u'config.cfg')
92 path_dst = os.path.join(self.homedir , 108 path_dst = os.path.join(self.homedir ,
93 - '.invesalius', 'config.backup') 109 + u'.invesalius', u'config.backup')
94 shutil.copy(path, path_dst) 110 shutil.copy(path, path_dst)
95 111
96 def RecoveryConfigFile(self): 112 def RecoveryConfigFile(self):
97 homedir = self.homedir = os.path.expanduser('~') 113 homedir = self.homedir = os.path.expanduser('~')
98 try: 114 try:
99 path = os.path.join(self.homedir , 115 path = os.path.join(self.homedir ,
100 - '.invesalius', 'config.backup') 116 + u'.invesalius', u'config.backup')
101 path_dst = os.path.join(self.homedir , 117 path_dst = os.path.join(self.homedir ,
102 - '.invesalius', 'config.cfg') 118 + u'.invesalius', u'config.cfg')
103 shutil.copy(path, path_dst) 119 shutil.copy(path, path_dst)
104 return True 120 return True
105 except(IOError): 121 except(IOError):
@@ -163,10 +179,6 @@ class Session(object): @@ -163,10 +179,6 @@ class Session(object):
163 def WriteSessionFile(self): 179 def WriteSessionFile(self):
164 config = ConfigParser.RawConfigParser() 180 config = ConfigParser.RawConfigParser()
165 181
166 - print ">>>", type(self.homedir), self.homedir, repr(self.homedir)  
167 - print ">>>", type(self.tempdir), self.tempdir, repr(self.tempdir)  
168 - print ">>>", type(self.language), self.language, repr(self.language)  
169 -  
170 config.add_section('session') 182 config.add_section('session')
171 config.set('session', 'mode', self.mode) 183 config.set('session', 'mode', self.mode)
172 config.set('session', 'status', self.project_status) 184 config.set('session', 'status', self.project_status)
@@ -185,18 +197,10 @@ class Session(object): @@ -185,18 +197,10 @@ class Session(object):
185 config.set('paths','tempdir',self.tempdir) 197 config.set('paths','tempdir',self.tempdir)
186 config.set('paths','last_dicom_folder',self.last_dicom_folder) 198 config.set('paths','last_dicom_folder',self.last_dicom_folder)
187 199
188 - print config.items('session')  
189 - print config.items('project')  
190 - print config.items('paths')  
191 -  
192 path = os.path.join(self.homedir , 200 path = os.path.join(self.homedir ,
193 '.invesalius', 'config.cfg') 201 '.invesalius', 'config.cfg')
194 202
195 - if sys.platform == 'win32':  
196 - configfile = codecs.open(path, 'wb', 'utf8')  
197 - else:  
198 - configfile = open(path, 'wb')  
199 - 203 + configfile = codecs.open(path, 'wb', SESSION_ENCODING)
200 config.write(configfile) 204 config.write(configfile)
201 configfile.close() 205 configfile.close()
202 206
@@ -238,12 +242,15 @@ class Session(object): @@ -238,12 +242,15 @@ class Session(object):
238 242
239 def ReadLanguage(self): 243 def ReadLanguage(self):
240 config = ConfigParser.ConfigParser() 244 config = ConfigParser.ConfigParser()
241 - home_path = os.path.expanduser('~')  
242 - path = os.path.join(home_path ,'.invesalius', 'config.cfg') 245 + path = os.path.join(USER_INV_DIR, 'config.cfg')
243 try: 246 try:
244 - config.read(path) 247 + f = codecs.open(path, 'rb', SESSION_ENCODING)
  248 + config.readfp(f)
  249 + f.close()
245 self.language = config.get('session','language') 250 self.language = config.get('session','language')
246 return self.language 251 return self.language
  252 + except IOError:
  253 + return False
247 except (ConfigParser.NoSectionError, 254 except (ConfigParser.NoSectionError,
248 ConfigParser.NoOptionError, 255 ConfigParser.NoOptionError,
249 ConfigParser.MissingSectionHeaderError): 256 ConfigParser.MissingSectionHeaderError):
@@ -251,12 +258,15 @@ class Session(object): @@ -251,12 +258,15 @@ class Session(object):
251 258
252 def ReadRandomId(self): 259 def ReadRandomId(self):
253 config = ConfigParser.ConfigParser() 260 config = ConfigParser.ConfigParser()
254 - home_path = os.path.expanduser('~')  
255 - path = os.path.join(home_path ,'.invesalius', 'config.cfg') 261 + path = os.path.join(USER_INV_DIR, 'config.cfg')
256 try: 262 try:
257 - config.read(path) 263 + f = codecs.open(path, 'rb', SESSION_ENCODING)
  264 + config.readfp(f)
  265 + f.close()
258 self.random_id = config.get('session','random_id') 266 self.random_id = config.get('session','random_id')
259 return self.random_id 267 return self.random_id
  268 + except IOError:
  269 + return False
260 except (ConfigParser.NoSectionError, 270 except (ConfigParser.NoSectionError,
261 ConfigParser.NoOptionError, 271 ConfigParser.NoOptionError,
262 ConfigParser.MissingSectionHeaderError): 272 ConfigParser.MissingSectionHeaderError):
@@ -264,10 +274,11 @@ class Session(object): @@ -264,10 +274,11 @@ class Session(object):
264 274
265 def ReadSession(self): 275 def ReadSession(self):
266 config = ConfigParser.ConfigParser() 276 config = ConfigParser.ConfigParser()
267 - home_path = os.path.expanduser('~').decode(ENCODE)  
268 - path = os.path.join(home_path ,'.invesalius', 'config.cfg') 277 + path = USER_INV_CFG_PATH
269 try: 278 try:
270 - config.readfp(codecs.open(path, 'rb', 'utf8')) 279 + f = codecs.open(path, 'rb', SESSION_ENCODING)
  280 + config.readfp(f)
  281 + f.close()
271 self.mode = config.get('session', 'mode') 282 self.mode = config.get('session', 'mode')
272 # Do not reading project status from the config file, since there 283 # Do not reading project status from the config file, since there
273 # isn't a recover sessession tool in InVesalius 284 # isn't a recover sessession tool in InVesalius
@@ -295,7 +306,6 @@ class Session(object): @@ -295,7 +306,6 @@ class Session(object):
295 except(ConfigParser.NoSectionError, ConfigParser.MissingSectionHeaderError, 306 except(ConfigParser.NoSectionError, ConfigParser.MissingSectionHeaderError,
296 ConfigParser.ParsingError): 307 ConfigParser.ParsingError):
297 308
298 - print 'Error 1'  
299 if (self.RecoveryConfigFile()): 309 if (self.RecoveryConfigFile()):
300 self.ReadSession() 310 self.ReadSession()
301 return True 311 return True
@@ -303,7 +313,6 @@ class Session(object): @@ -303,7 +313,6 @@ class Session(object):
303 return False 313 return False
304 314
305 except(ConfigParser.NoOptionError): 315 except(ConfigParser.NoOptionError):
306 - print 'Error 2'  
307 #Added to fix new version compatibility 316 #Added to fix new version compatibility
308 self.surface_interpolation = 0 317 self.surface_interpolation = 0
309 self.slice_interpolation = 0 318 self.slice_interpolation = 0
@@ -312,6 +321,5 @@ class Session(object): @@ -312,6 +321,5 @@ class Session(object):
312 try: 321 try:
313 self.WriteSessionFile() 322 self.WriteSessionFile()
314 except AttributeError: 323 except AttributeError:
315 - print 'Error 3'  
316 return False 324 return False
317 return True 325 return True
invesalius/utils.py
@@ -436,3 +436,8 @@ def vtkarray_to_numpy(m): @@ -436,3 +436,8 @@ def vtkarray_to_numpy(m):
436 for j in xrange(4): 436 for j in xrange(4):
437 nm[i, j] = m.GetElement(i, j) 437 nm[i, j] = m.GetElement(i, j)
438 return nm 438 return nm
  439 +
  440 +
  441 +def touch(fname):
  442 + with open(fname, 'a'):
  443 + pass