svghmi/ui.py
changeset 3482 31f6d7221f60
parent 3466 eadb3a85ceb7
child 3526 074046800624
equal deleted inserted replaced
3481:563996733dba 3482:31f6d7221f60
     9 from __future__ import absolute_import
     9 from __future__ import absolute_import
    10 import os
    10 import os
    11 import hashlib
    11 import hashlib
    12 import weakref
    12 import weakref
    13 import re
    13 import re
       
    14 import tempfile
    14 from threading import Thread, Lock
    15 from threading import Thread, Lock
    15 from functools import reduce
    16 from functools import reduce
    16 from itertools import izip
    17 from itertools import izip
    17 from operator import or_
    18 from operator import or_
    18 from tempfile import NamedTemporaryFile
    19 from tempfile import NamedTemporaryFile
    24 from lxml.etree import XSLTApplyError
    25 from lxml.etree import XSLTApplyError
    25 from XSLTransform import XSLTransform
    26 from XSLTransform import XSLTransform
    26 
    27 
    27 import util.paths as paths
    28 import util.paths as paths
    28 from IDEFrame import EncodeFileSystemPath, DecodeFileSystemPath
    29 from IDEFrame import EncodeFileSystemPath, DecodeFileSystemPath
    29 from docutil import get_inkscape_path
    30 from docutil import get_inkscape_path, get_inkscape_version
    30 
    31 
    31 from util.ProcessLogger import ProcessLogger
    32 from util.ProcessLogger import ProcessLogger
    32 
    33 
    33 ScriptDirectory = paths.AbsDir(__file__)
    34 ScriptDirectory = paths.AbsDir(__file__)
    34 
    35 
   274         txt.split("\n\n")))
   275         txt.split("\n\n")))
   275 
   276 
   276 _conf_key = "SVGHMIWidgetLib"
   277 _conf_key = "SVGHMIWidgetLib"
   277 _preview_height = 200
   278 _preview_height = 200
   278 _preview_margin = 5
   279 _preview_margin = 5
       
   280 thumbnail_temp_path = None
       
   281 
   279 class WidgetLibBrowser(wx.SplitterWindow):
   282 class WidgetLibBrowser(wx.SplitterWindow):
   280     def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
   283     def __init__(self, parent, controler, id=wx.ID_ANY, pos=wx.DefaultPosition,
   281                  size=wx.DefaultSize):
   284                  size=wx.DefaultSize):
   282 
   285 
   283         wx.SplitterWindow.__init__(self, parent,
   286         wx.SplitterWindow.__init__(self, parent,
   284                                    style=wx.SUNKEN_BORDER | wx.SP_3D)
   287                                    style=wx.SUNKEN_BORDER | wx.SP_3D)
   285 
   288 
   286         self.bmp = None
   289         self.bmp = None
   287         self.msg = None
   290         self.msg = None
   288         self.hmitree_nodes = []
   291         self.hmitree_nodes = []
   289         self.selected_SVG = None
   292         self.selected_SVG = None
       
   293         self.Controler = controler
   290 
   294 
   291         self.Config = wx.ConfigBase.Get()
   295         self.Config = wx.ConfigBase.Get()
   292         self.libdir = self.RecallLibDir()
   296         self.libdir = self.RecallLibDir()
   293         if self.libdir is None:
   297         if self.libdir is None:
   294             self.libdir = os.path.join(ScriptDirectory, "widgetlib") 
   298             self.libdir = os.path.join(ScriptDirectory, "widgetlib") 
   453     def GenThumbnail(self, svgpath, thumbpath):
   457     def GenThumbnail(self, svgpath, thumbpath):
   454         inkpath = get_inkscape_path()
   458         inkpath = get_inkscape_path()
   455         if inkpath is None:
   459         if inkpath is None:
   456             self.msg = _("Inkscape is not installed.")
   460             self.msg = _("Inkscape is not installed.")
   457             return False
   461             return False
       
   462 
       
   463         export_opt = "-o" if get_inkscape_version()[0] > 0 else "-e"
       
   464 
   458         # TODO: spawn a thread, to decouple thumbnail gen
   465         # TODO: spawn a thread, to decouple thumbnail gen
   459         status, result, _err_result = ProcessLogger(
   466         status, result, _err_result = ProcessLogger(
   460             None,
   467             self.Controler.GetCTRoot().logger,
   461             '"' + inkpath + '" "' + svgpath + '" -e "' + thumbpath +
   468             '"' + inkpath + '" "' + svgpath + '" ' +
       
   469             export_opt + ' "' + thumbpath +
   462             '" -D -h ' + str(_preview_height)).spin()
   470             '" -D -h ' + str(_preview_height)).spin()
   463         if status != 0:
   471         if status != 0:
   464             self.msg = _("Inkscape couldn't generate thumbnail.")
   472             self.msg = _("Inkscape couldn't generate thumbnail.")
   465             return False
   473             return False
   466         return True
   474         return True
   468     def OnWidgetSelection(self, event):
   476     def OnWidgetSelection(self, event):
   469         """
   477         """
   470         Called when tree item is selected
   478         Called when tree item is selected
   471         @param event: wx.TreeEvent
   479         @param event: wx.TreeEvent
   472         """
   480         """
       
   481         global thumbnail_temp_path
       
   482         event.Skip()
   473         item_pydata = self.widgetpicker.GetPyData(event.GetItem())
   483         item_pydata = self.widgetpicker.GetPyData(event.GetItem())
   474         if item_pydata is not None:
   484         if item_pydata is not None:
   475             svgpath = item_pydata
   485             svgpath = item_pydata
   476             dname = os.path.dirname(svgpath)
   486 
       
   487             if thumbnail_temp_path is None:
       
   488                 try:
       
   489                     dname = os.path.dirname(svgpath)
       
   490                     thumbdir = os.path.join(dname, ".svghmithumbs") 
       
   491                     if not os.path.exists(thumbdir):
       
   492                         os.mkdir(thumbdir)
       
   493                 except Exception :
       
   494                     # library not writable : use temp dir
       
   495                     thumbnail_temp_path = os.path.join(
       
   496                         tempfile.gettempdir(), "svghmithumbs")
       
   497                     thumbdir = thumbnail_temp_path
       
   498                     if not os.path.exists(thumbdir):
       
   499                         os.mkdir(thumbdir)
       
   500             else:
       
   501                 thumbdir = thumbnail_temp_path
       
   502 
   477             fname = os.path.basename(svgpath)
   503             fname = os.path.basename(svgpath)
   478             hasher = hashlib.new('md5')
   504             hasher = hashlib.new('md5')
   479             with open(svgpath, 'rb') as afile:
   505             with open(svgpath, 'rb') as afile:
   480                 while True:
   506                 while True:
   481                     buf = afile.read(65536)
   507                     buf = afile.read(65536)
   483                         hasher.update(buf)
   509                         hasher.update(buf)
   484                     else:
   510                     else:
   485                         break
   511                         break
   486             digest = hasher.hexdigest()
   512             digest = hasher.hexdigest()
   487             thumbfname = os.path.splitext(fname)[0]+"_"+digest+".png"
   513             thumbfname = os.path.splitext(fname)[0]+"_"+digest+".png"
   488             thumbdir = os.path.join(dname, ".svghmithumbs") 
       
   489             thumbpath = os.path.join(thumbdir, thumbfname) 
   514             thumbpath = os.path.join(thumbdir, thumbfname) 
   490 
   515 
   491             have_thumb = os.path.exists(thumbpath)
   516             have_thumb = os.path.exists(thumbpath)
   492 
   517 
   493             try:
   518             if not have_thumb:
   494                 if not have_thumb:
   519                 self.Controler.GetCTRoot().logger.write(
   495                     if not os.path.exists(thumbdir):
   520                     "Rendering preview of " + fname + " widget.\n")
   496                         os.mkdir(thumbdir)
   521                 have_thumb = self.GenThumbnail(svgpath, thumbpath)
   497                     have_thumb = self.GenThumbnail(svgpath, thumbpath)
   522 
   498 
   523             self.bmp = wx.Bitmap(thumbpath) if have_thumb else None
   499                 self.bmp = wx.Bitmap(thumbpath) if have_thumb else None
   524 
   500 
   525             self.selected_SVG = svgpath if have_thumb else None
   501                 self.selected_SVG = svgpath if have_thumb else None
   526 
   502 
   527             self.AnalyseWidgetAndUpdateUI(fname)
   503                 self.AnalyseWidgetAndUpdateUI(fname)
   528 
   504 
   529             self.SetMessage(self.msg)
   505                 self.SetMessage(self.msg)
       
   506 
       
   507             except IOError:
       
   508                 self.msg = _("Widget library must be writable")
       
   509 
   530 
   510             self.Refresh()
   531             self.Refresh()
   511         event.Skip()
       
   512 
   532 
   513     def OnHMITreeNodeSelection(self, hmitree_nodes):
   533     def OnHMITreeNodeSelection(self, hmitree_nodes):
   514         self.hmitree_nodes = hmitree_nodes
   534         self.hmitree_nodes = hmitree_nodes
   515 
   535 
   516     def OnLeftDown(self, evt):
   536     def OnLeftDown(self, evt):
   685         if self.tempf is not None:
   705         if self.tempf is not None:
   686             os.unlink(self.tempf.name)
   706             os.unlink(self.tempf.name)
   687 
   707 
   688 class SVGHMI_UI(wx.SplitterWindow):
   708 class SVGHMI_UI(wx.SplitterWindow):
   689 
   709 
   690     def __init__(self, parent, register_for_HMI_tree_updates):
   710     def __init__(self, parent, controler, register_for_HMI_tree_updates):
   691         wx.SplitterWindow.__init__(self, parent,
   711         wx.SplitterWindow.__init__(self, parent,
   692                                    style=wx.SUNKEN_BORDER | wx.SP_3D)
   712                                    style=wx.SUNKEN_BORDER | wx.SP_3D)
   693 
   713 
   694         self.SelectionTree = HMITreeSelector(self)
   714         self.SelectionTree = HMITreeSelector(self)
   695         self.Staging = WidgetLibBrowser(self)
   715         self.Staging = WidgetLibBrowser(self, controler)
   696         self.SplitVertically(self.SelectionTree, self.Staging, 300)
   716         self.SplitVertically(self.SelectionTree, self.Staging, 300)
   697         register_for_HMI_tree_updates(weakref.ref(self))
   717         register_for_HMI_tree_updates(weakref.ref(self))
   698 
   718 
   699     def HMITreeUpdate(self, hmi_tree_root):
   719     def HMITreeUpdate(self, hmi_tree_root):
   700         self.SelectionTree.MakeTree(hmi_tree_root)
   720         self.SelectionTree.MakeTree(hmi_tree_root)