home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2012 January / maximum-cd-2012-01.iso / DiscContents / digsby_setup.exe / lib / gui / skin / skintree.pyo (.txt) < prev   
Encoding:
Python Compiled Bytecode  |  2011-10-05  |  14.1 KB  |  471 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. SKIN_FILENAME = 'skin.yaml'
  6. VARIANT_DIR = 'Variants'
  7. SKIN_NAME_KEY = 'name'
  8. VARIANT_NAME_KEY = 'variant'
  9. alternating_keys = [
  10.     'buddiespanel.backgrounds.buddy',
  11.     'filetransfers.backgrounds.normal']
  12. FONT_MULTIPLY_KEY = 'FontPlatform'
  13. FONT_MULTIPLY = {
  14.     'windows_mac': 4 / 3,
  15.     'mac_windows': 3 / 4 }
  16. __metaclass__ = type
  17. from operator import isMappingType
  18. from util.primitives import Storage, traceguard, dictrecurse
  19. S = Storage
  20. from path import path
  21. from copy import deepcopy
  22. import syck
  23. import sys
  24. import os
  25. import wx
  26. from wx import GetTopLevelWindows, GetApp, MessageBox
  27. from traceback import print_exc
  28. from gui.toolbox import colorfor
  29. from types import FunctionType
  30. from util.merge import merge, merge_keys, tolower
  31. from util.primitives import syck_error_message
  32. from util.introspect import funcinfo
  33. from gui.skin.skintransform import transform
  34. from gui.skin import SkinException
  35. from peak.util.plugins import Hook
  36. from logging import getLogger
  37. log = getLogger('skin')
  38. info = log.info
  39. import stdpaths
  40. activeTree = None
  41. resource_paths = [
  42.     path('res').abspath(),
  43.     path('res/skins/default').abspath()]
  44.  
  45. try:
  46.     userdata = stdpaths.userdata
  47. except AttributeError:
  48.     log.warning('not including stdpaths.userdata in skin lookup paths')
  49.  
  50. resource_paths.append(userdata / 'skins')
  51. del userdata
  52.  
  53. def get(dottedpath, default = sentinel):
  54.     
  55.     try:
  56.         return lookup(activeTree, dottedpath.lower().split('.'))
  57.     except (KeyError, TypeError):
  58.         if default is sentinel:
  59.             raise SkinException('not found: ' + dottedpath)
  60.         default is sentinel
  61.         return default
  62.     except:
  63.         print_exc()
  64.         print >>sys.stderr, 'exception for "%s"' % dottedpath
  65.  
  66.  
  67.  
  68. def refresh_wx_tree():
  69.     UMenu = UMenu
  70.     import gui.uberwidgets.umenu
  71.     skip = (UMenu,)
  72.     for window in GetTopLevelWindows():
  73.         window.FrozenQuick().__enter__()
  74.         
  75.         try:
  76.             _updateskin(window, skip)
  77.         finally:
  78.             pass
  79.  
  80.     
  81.     UMenu.CallAll(UMenu.UpdateSkin)
  82.  
  83.  
  84. def _updateskin(window, skip):
  85.     
  86.     try:
  87.         update = window.UpdateSkin
  88.     except AttributeError:
  89.         pass
  90.  
  91.     if not isinstance(window, skip):
  92.         
  93.         try:
  94.             update()
  95.         print_exc()
  96.  
  97.     
  98.     for c in window.Children:
  99.         _updateskin(c, skip)
  100.     
  101.  
  102.  
  103. def alternating(tree):
  104.     SkinList = SkinList
  105.     import gui.skin.skinobjects
  106.     for k in alternating_keys:
  107.         spath = k.split('.')
  108.         
  109.         try:
  110.             val = lookup(tree, spath)
  111.         except AttributeError:
  112.             continue
  113.  
  114.         if isinstance(val, list):
  115.             lookup(tree, spath[:-1])[spath[-1]] = SkinList(val)
  116.             continue
  117.     
  118.  
  119.  
  120. def fontplatform(finaltree):
  121.     skin = skin
  122.     import gui
  123.     platformName = platformName
  124.     import config
  125.     platform_aliases = {
  126.         'win': 'windows',
  127.         'mac': 'mac' }
  128.     fontplatform = finaltree.get(FONT_MULTIPLY_KEY.lower(), None)
  129.     fp = '%s_%s' % (fontplatform, platform_aliases.get(platformName))
  130.     factor = FONT_MULTIPLY.get(fp, 1)
  131.     log.info('new font multiply factor: %s -> %s', fp, factor)
  132.     skin.font_multiply_factor = factor
  133.  
  134. pretransforms = [
  135.     fontplatform]
  136. posttransforms = [
  137.     alternating]
  138. _loaded_fonts = set()
  139.  
  140. def skin_font_files(paths):
  141.     fonts = []
  142.     for p in paths:
  143.         fontsdir = p.parent / 'fonts'
  144.         if fontsdir.isdir():
  145.             for ext in ('ttf', 'fon'):
  146.                 fonts.extend(fontsdir.files('*.' + ext))
  147.             
  148.     
  149.     return [ f.abspath().normpath() for f in fonts ]
  150.  
  151.  
  152. def load_skinfonts(paths):
  153.     global _loaded_fonts
  154.     import config
  155.     if not config.platform == 'win':
  156.         return None
  157.     loadfont = loadfont
  158.     unloadfont = unloadfont
  159.     import gui.native.win.winfonts
  160.     fonts = set(skin_font_files(paths))
  161.     if _loaded_fonts == fonts:
  162.         return None
  163.     for fontfile in _loaded_fonts - fonts:
  164.         traceguard.__enter__()
  165.         
  166.         try:
  167.             res = unloadfont(fontfile, enumerable = True)
  168.             log.debug('unloaded font %r: %r', fontfile, res)
  169.         finally:
  170.             pass
  171.  
  172.     
  173.     for fontfile in fonts - _loaded_fonts:
  174.         traceguard.__enter__()
  175.         
  176.         try:
  177.             res = loadfont(fontfile, enumerable = True)
  178.             log.debug('loading font %r: %r', fontfile, res)
  179.         finally:
  180.             pass
  181.  
  182.     
  183.     _loaded_fonts = fonts
  184.     import wx.webview as wx
  185.  
  186.  
  187. def set_active(skin, variant = None, update_gui = False, callback = None):
  188.     global activeTree
  189.     log.info('set_active(%r, %r)', skin, variant)
  190.     app = GetApp()
  191.     skinname = skin
  192.     for rp in resource_paths:
  193.         skin = path(rp) / 'skins' / skinname
  194.         skinpath = skin / SKIN_FILENAME
  195.         if skinpath.isfile():
  196.             break
  197.             continue
  198.     
  199.     import hooks
  200.     hooks.notify('skin.set.pre', skin, variant)
  201.     if variant is not None:
  202.         variant = skin / VARIANT_DIR / variant + '.yaml'
  203.     
  204.     default_path = resource_paths[0] / 'skins' / 'default' / SKIN_FILENAME
  205.     paths = [
  206.         default_path]
  207.     insert_position = 1
  208.     if os.path.basename(skin) == 'native':
  209.         paths.append(resource_paths[0] / path('skins') / 'silverblue' / SKIN_FILENAME)
  210.     
  211.     if not skinpath.isfile():
  212.         log.critical('cannot find %r (%r.isfile() == False, defaulting to silverblue', skin, skinpath)
  213.         skin = resource_paths[0] / path('skins') / 'silverblue'
  214.         skinpath = skin / SKIN_FILENAME
  215.         variant = None
  216.     
  217.     if default_path.abspath() != skinpath.abspath():
  218.         paths.append(skinpath)
  219.     
  220.     if variant is not None:
  221.         if variant.isfile():
  222.             paths.append(variant)
  223.         else:
  224.             log.warning('cannot find variant %r for skin %r', variant, skin)
  225.     
  226.     if not update_gui and hasattr(app, 'skin') and app.skin.paths == paths:
  227.         log.info('skin did not change, returning')
  228.     
  229.     traceguard.__enter__()
  230.     
  231.     try:
  232.         load_skinfonts(paths)
  233.     finally:
  234.         pass
  235.  
  236.     log.info('loading YAML from %d path(s):\n  %r', len(paths), '\n  '.join(paths))
  237.     trees = get_skintrees(skin, paths, insert_position)
  238.     for tree in trees[1:]:
  239.         tree.pop('appdefaults', None)
  240.     
  241.     default_tree = deepcopy(trees[0])
  242.     combined_tree = merge(*trees, **dict(keytransform = (lambda k: getattr(k, 'lower', (lambda k: k))()
  243. )))
  244.     app.skin.update(path = skinpath.parent, paths = get_image_load_paths(paths))
  245.     for pretransform in pretransforms:
  246.         pretransform(combined_tree)
  247.     
  248.     
  249.     try:
  250.         finaltree = transform(combined_tree)
  251.     except Exception:
  252.         None if not hasattr(app, 'skin') else traceguard
  253.         e = None if not hasattr(app, 'skin') else traceguard
  254.         MessageBox('There was an error processing skin "%s":\n\n%s' % (skin, str(e)), 'Skin Error')
  255.         print_exc()
  256.         finaltree = transform(default_tree)
  257.     except:
  258.         None if not hasattr(app, 'skin') else traceguard
  259.  
  260.     for posttransform in posttransforms:
  261.         posttransform(finaltree)
  262.     
  263.     activeTree = finaltree
  264.     app.skin.update(tree = finaltree)
  265.     
  266.     def done():
  267.         if update_gui:
  268.             refresh_wx_tree()
  269.         
  270.         import gc
  271.         gc.collect()
  272.  
  273.     wx.CallAfter(done)
  274.     return app.skin
  275.  
  276.  
  277. def list_skins():
  278.     resource_paths = sys.modules['gui.skin.skintree'].resource_paths
  279.     skins = []
  280.     for res in resource_paths:
  281.         skinrootdir = res / 'skins'
  282.         if skinrootdir.isdir():
  283.             for skindir in skinrootdir.dirs():
  284.                 if skindir.name.startswith('.'):
  285.                     continue
  286.                 
  287.                 rootfile = skindir / SKIN_FILENAME
  288.                 if rootfile.isfile() and skindir.name != 'default':
  289.                     skins.append(skindesc(rootfile))
  290.                     continue
  291.             
  292.     
  293.     return skins
  294.  
  295.  
  296. def get_skintrees(skin, paths, insert_position):
  297.     trees = []
  298.     errors = []
  299.     successful = False
  300.     for f in paths:
  301.         
  302.         try:
  303.             trees.append(load_skinfile(f))
  304.         except Exception:
  305.             e = None
  306.             errors.append(e)
  307.             del e
  308.             continue
  309.  
  310.         successful = True
  311.     
  312.     if not successful:
  313.         MessageBox('There was an error loading skin "%s":\n\n%s' % (skin, '\n'.join((lambda .0: for e in .0:
  314. str(e))(errors))), 'Skin Error')
  315.     
  316.     SkinStorage = SkinStorage
  317.     import gui.skin
  318.     to_skinstorage = dictrecurse(SkinStorage)
  319.     for hook in Hook('digsby.skin.load.trees'):
  320.         hook_trees = hook()
  321.         if hook_trees is not None:
  322.             trees[insert_position:insert_position] = (lambda .0: for t in .0:
  323. to_skinstorage(deepcopy(t)))(hook_trees)
  324.             continue
  325.         (None,)
  326.     
  327.     return trees
  328.  
  329.  
  330. def get_image_load_paths(paths):
  331.     image_load_paths = [ p.parent for p in paths ]
  332.     for pathhook in Hook('digsby.skin.load.skinpaths'):
  333.         hook_paths = pathhook()
  334.         if hook_paths is not None:
  335.             image_load_paths.extend(hook_paths)
  336.             continue
  337.         []
  338.     
  339.     return image_load_paths
  340.  
  341.  
  342. def quick_name_lookup(p, **names):
  343.     names = dict((lambda .0: for key, name in .0:
  344. (name.lower(), key))(names.iteritems()))
  345.     vals = { }
  346.     
  347.     try:
  348.         f = _[1]
  349.         s = syck.load(f)
  350.         for k, name in getattr(s, ('iteritems',), (lambda : s))():
  351.             
  352.             try:
  353.                 k = k.lower()
  354.             except AttributeError:
  355.                 p.open('r').__exit__
  356.                 p.open('r').__exit__
  357.                 p.open('r')
  358.                 continue
  359.  
  360.             if k in names and isinstance(name, basestring):
  361.                 vals[k] = name
  362.                 if len(vals) == len(names):
  363.                     break
  364.                 
  365.             len(vals) == len(names)
  366.     finally:
  367.         pass
  368.  
  369.     return vals
  370.  
  371.  
  372. def skindesc(rootfile):
  373.     rootfile = path(rootfile)
  374.     aliases = quick_name_lookup(rootfile, skin_alias = SKIN_NAME_KEY, novariant_alias = VARIANT_NAME_KEY)
  375.     variants = []
  376.     vardir = rootfile.parent / VARIANT_DIR
  377.     if vardir.isdir():
  378.         for variant in vardir.files('*.yaml'):
  379.             if variant != rootfile:
  380.                 valias = quick_name_lookup(variant, variant_alias = VARIANT_NAME_KEY).get('variant_alias', variant.namebase)
  381.                 variants.append(S(path = variant, alias = valias))
  382.                 continue
  383.         
  384.     
  385.     return S(name = rootfile.parent.name, alias = aliases.get(SKIN_NAME_KEY, rootfile.parent.name), novariant_alias = aliases.get(VARIANT_NAME_KEY, _('(none)')), base = rootfile, variants = variants)
  386.  
  387.  
  388. def lookup(root, pathseq):
  389.     elem = root
  390.     for p in pathseq:
  391.         elem = elem[p]
  392.     
  393.     return elem
  394.  
  395.  
  396. def load_skinfile(filepath):
  397.     if not filepath.isfile():
  398.         raise ValueError('file %s does not exist' % filepath)
  399.     filepath.isfile()
  400.     return globals()['load_%s' % filepath.ext[1:]](filepath)
  401.  
  402.  
  403. def load_yaml(str_or_path):
  404.     SkinStorage = SkinStorage
  405.     import gui.skin
  406.     (bytes, fpath) = getcontent(str_or_path)
  407.     if isinstance(bytes, unicode):
  408.         bytes = bytes.encode('utf-8')
  409.     
  410.     if not bytes:
  411.         raise SkinException('no bytes in ' + str_or_path)
  412.     bytes
  413.     content = load_yaml_content(bytes)
  414.     
  415.     try:
  416.         root = syck.load(content)
  417.     except syck.error:
  418.         e = None
  419.         raise SkinException(syck_error_message(e, fpath))
  420.  
  421.     return merge_keys(root, maptype = SkinStorage)
  422.  
  423.  
  424. def load_yaml_content(bytes, included_paths = None):
  425.     if included_paths is None:
  426.         included_paths = []
  427.     
  428.     lines = []
  429.     for line in bytes.split('\n'):
  430.         if line.lower().startswith('include:'):
  431.             include_path = line[line.index(':') + 1:].strip()
  432.             line = load_yaml_include(include_path, included_paths)
  433.         
  434.         lines.append(line)
  435.     
  436.     return '\n'.join(lines)
  437.  
  438.  
  439. def load_yaml_include(incpath, included_paths):
  440.     incpath = path(incpath).abspath()
  441.     if incpath not in included_paths:
  442.         bytes = load_yaml_content(incpath.bytes(), included_paths)
  443.         included_paths += [
  444.             incpath]
  445.         return bytes
  446.     return ''
  447.  
  448. from util.data_importer import zipopen
  449. from contextlib import closing
  450.  
  451. def getcontent(str_or_path):
  452.     
  453.     try:
  454.         if str_or_path.isfile():
  455.             return (str_or_path.bytes(), str_or_path)
  456.         
  457.         try:
  458.             f = _[1]
  459.             return (f.read(), str_or_path)
  460.         finally:
  461.             pass
  462.  
  463.     except AttributeError:
  464.         return (str_or_path, '<String Input>')
  465.  
  466.  
  467. if __name__ == '__main__':
  468.     s = 'common:\n- &mycolor red\n\nmenu:\n  color: *mycolor\n\ncommon:\n- &mycolor blue'
  469.     print load_yaml(s)
  470.  
  471.