home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_1391 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  31.3 KB  |  834 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. __license__ = 'GPL v3'
  6. __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
  7. __docformat__ = 'restructuredtext en'
  8. import os
  9. import re
  10. import cPickle
  11. import textwrap
  12. import traceback
  13. import plistlib
  14. import json
  15. import base64
  16. import datetime
  17. from copy import deepcopy
  18. from functools import partial
  19. from optparse import OptionParser as _OptionParser
  20. from optparse import IndentedHelpFormatter
  21. from collections import defaultdict
  22. from calibre.constants import terminal_controller, config_dir, __appname__, __version__, __author__
  23. from calibre.utils.lock import LockError, ExclusiveFile
  24. plugin_dir = os.path.join(config_dir, 'plugins')
  25. CONFIG_DIR_MODE = 448
  26.  
  27. def make_config_dir():
  28.     if not os.path.exists(plugin_dir):
  29.         os.makedirs(plugin_dir, mode = CONFIG_DIR_MODE)
  30.     
  31.  
  32.  
  33. def check_config_write_access():
  34.     if os.access(config_dir, os.W_OK):
  35.         pass
  36.     return os.access(config_dir, os.X_OK)
  37.  
  38.  
  39. class CustomHelpFormatter(IndentedHelpFormatter):
  40.     
  41.     def format_usage(self, usage):
  42.         return _('%sUsage%s: %s\n') % (terminal_controller.BLUE, terminal_controller.NORMAL, usage)
  43.  
  44.     
  45.     def format_heading(self, heading):
  46.         return '%*s%s%s%s:\n' % (self.current_indent, terminal_controller.BLUE, '', heading, terminal_controller.NORMAL)
  47.  
  48.     
  49.     def format_option(self, option):
  50.         result = []
  51.         opts = self.option_strings[option]
  52.         opt_width = self.help_position - self.current_indent - 2
  53.         if len(opts) > opt_width:
  54.             opts = '%*s%s\n' % (self.current_indent, '', terminal_controller.GREEN + opts + terminal_controller.NORMAL)
  55.             indent_first = self.help_position
  56.         else:
  57.             opts = '%*s%-*s  ' % (self.current_indent, '', opt_width + len(terminal_controller.GREEN + terminal_controller.NORMAL), terminal_controller.GREEN + opts + terminal_controller.NORMAL)
  58.             indent_first = 0
  59.         result.append(opts)
  60.         if option.help:
  61.             help_text = self.expand_default(option).split('\n')
  62.             help_lines = []
  63.             for line in help_text:
  64.                 help_lines.extend(textwrap.wrap(line, self.help_width))
  65.             
  66.             result.append('%*s%s\n' % (indent_first, '', help_lines[0]))
  67.             []([ '%*s%s\n' % (self.help_position, '', line) for line in help_lines[1:] ])
  68.         elif opts[-1] != '\n':
  69.             result.append('\n')
  70.         
  71.         return ''.join(result) + '\n'
  72.  
  73.  
  74.  
  75. class OptionParser(_OptionParser):
  76.     
  77.     def __init__(self, usage = '%prog [options] filename', version = '%%prog (%s %s)' % (__appname__, __version__), epilog = None, gui_mode = False, conflict_handler = 'resolve', **kwds):
  78.         usage = textwrap.dedent(usage)
  79.         if epilog is None:
  80.             epilog = _('Created by ') + terminal_controller.RED + __author__ + terminal_controller.NORMAL
  81.         
  82.         usage += '\n\n' + _('Whenever you pass arguments to %prog that have spaces in them, enclose the arguments in quotation marks.')
  83.         _OptionParser.__init__(self, usage = usage, version = version, epilog = epilog, formatter = CustomHelpFormatter(), conflict_handler = conflict_handler, **kwds)
  84.         self.gui_mode = gui_mode
  85.  
  86.     
  87.     def error(self, msg):
  88.         if self.gui_mode:
  89.             raise Exception(msg)
  90.         self.gui_mode
  91.         _OptionParser.error(self, msg)
  92.  
  93.     
  94.     def merge(self, parser):
  95.         opts = list(parser.option_list)
  96.         groups = list(parser.option_groups)
  97.         
  98.         def merge_options(options, container):
  99.             for opt in deepcopy(options):
  100.                 if not self.has_option(opt.get_opt_string()):
  101.                     container.add_option(opt)
  102.                     continue
  103.             
  104.  
  105.         merge_options(opts, self)
  106.         for group in groups:
  107.             g = self.add_option_group(group.title)
  108.             merge_options(group.option_list, g)
  109.         
  110.  
  111.     
  112.     def subsume(self, group_name, msg = ''):
  113.         opts = _[1]
  114.         self.option_groups = []
  115.         subgroup = self.add_option_group(group_name, msg)
  116.         for opt in opts:
  117.             self.remove_option(opt.get_opt_string())
  118.             subgroup.add_option(opt)
  119.         
  120.  
  121.     
  122.     def options_iter(self):
  123.         for opt in self.option_list:
  124.             if str(opt).strip():
  125.                 yield opt
  126.                 continue
  127.         
  128.         for gr in self.option_groups:
  129.             for opt in gr.option_list:
  130.                 if str(opt).strip():
  131.                     yield opt
  132.                     continue
  133.             
  134.         
  135.  
  136.     
  137.     def option_by_dest(self, dest):
  138.         for opt in self.options_iter():
  139.             if opt.dest == dest:
  140.                 return opt
  141.         
  142.  
  143.     
  144.     def merge_options(self, lower, upper):
  145.         for dest in lower.__dict__.keys():
  146.             if not upper.__dict__.has_key(dest):
  147.                 continue
  148.             
  149.             opt = self.option_by_dest(dest)
  150.             if lower.__dict__[dest] != opt.default and upper.__dict__[dest] == opt.default:
  151.                 upper.__dict__[dest] = lower.__dict__[dest]
  152.                 continue
  153.         
  154.  
  155.  
  156.  
  157. class Option(object):
  158.     
  159.     def __init__(self, name, switches = [], help = '', type = None, choices = None, check = None, group = None, default = None, action = None, metavar = None):
  160.         if choices:
  161.             type = 'choice'
  162.         
  163.         self.name = name
  164.         self.switches = switches
  165.         self.help = None if help else None
  166.         self.type = type
  167.         if self.type is None and action is None and choices is None:
  168.             if isinstance(default, float):
  169.                 self.type = 'float'
  170.             elif isinstance(default, int) and not isinstance(default, bool):
  171.                 self.type = 'int'
  172.             
  173.         
  174.         self.choices = choices
  175.         self.check = check
  176.         self.group = group
  177.         self.default = default
  178.         self.action = action
  179.         self.metavar = metavar
  180.  
  181.     
  182.     def __eq__(self, other):
  183.         return self.name == getattr(other, 'name', other)
  184.  
  185.     
  186.     def __repr__(self):
  187.         return 'Option: ' + self.name
  188.  
  189.     
  190.     def __str__(self):
  191.         return repr(self)
  192.  
  193.  
  194.  
  195. class OptionValues(object):
  196.     
  197.     def copy(self):
  198.         return deepcopy(self)
  199.  
  200.  
  201.  
  202. class OptionSet(object):
  203.     OVERRIDE_PAT = re.compile('#{3,100} Override Options #{15}(.*?)#{3,100} End Override #{3,100}', re.DOTALL | re.IGNORECASE)
  204.     
  205.     def __init__(self, description = ''):
  206.         self.description = description
  207.         self.preferences = []
  208.         self.group_list = []
  209.         self.groups = { }
  210.         self.set_buffer = { }
  211.  
  212.     
  213.     def has_option(self, name_or_option_object):
  214.         if name_or_option_object in self.preferences:
  215.             return True
  216.         for p in self.preferences:
  217.             if p.name == name_or_option_object:
  218.                 return True
  219.         
  220.         return False
  221.  
  222.     
  223.     def get_option(self, name_or_option_object):
  224.         idx = self.preferences.index(name_or_option_object)
  225.         if idx > -1:
  226.             return self.preferences[idx]
  227.         for p in self.preferences:
  228.             if p.name == name_or_option_object:
  229.                 return p
  230.         
  231.  
  232.     
  233.     def add_group(self, name, description = ''):
  234.         if name in self.group_list:
  235.             raise ValueError('A group by the name %s already exists in this set' % name)
  236.         name in self.group_list
  237.         self.groups[name] = description
  238.         self.group_list.append(name)
  239.         return partial(self.add_opt, group = name)
  240.  
  241.     
  242.     def update(self, other):
  243.         for name in other.groups.keys():
  244.             self.groups[name] = other.groups[name]
  245.             if name not in self.group_list:
  246.                 self.group_list.append(name)
  247.                 continue
  248.         
  249.         for pref in other.preferences:
  250.             if pref in self.preferences:
  251.                 self.preferences.remove(pref)
  252.             
  253.             self.preferences.append(pref)
  254.         
  255.  
  256.     
  257.     def smart_update(self, opts1, opts2):
  258.         for pref in self.preferences:
  259.             new = getattr(opts2, pref.name, pref.default)
  260.             if new != pref.default:
  261.                 setattr(opts1, pref.name, new)
  262.                 continue
  263.         
  264.  
  265.     
  266.     def remove_opt(self, name):
  267.         if name in self.preferences:
  268.             self.preferences.remove(name)
  269.         
  270.  
  271.     
  272.     def add_opt(self, name, switches = [], help = None, type = None, choices = None, group = None, default = None, action = None, metavar = None):
  273.         pref = Option(name, switches = switches, help = help, type = type, choices = choices, group = group, default = default, action = action, metavar = None)
  274.         if group is not None and group not in self.groups.keys():
  275.             raise ValueError('Group %s has not been added to this section' % group)
  276.         group not in self.groups.keys()
  277.         if pref in self.preferences:
  278.             raise ValueError('An option with the name %s already exists in this set.' % name)
  279.         pref in self.preferences
  280.         self.preferences.append(pref)
  281.  
  282.     
  283.     def option_parser(self, user_defaults = None, usage = '', gui_mode = False):
  284.         parser = OptionParser(usage, gui_mode = gui_mode)
  285.         groups = (defaultdict,)((lambda : parser))
  286.         for group, desc in self.groups.items():
  287.             groups[group] = parser.add_option_group(group.upper(), desc)
  288.         
  289.         for pref in self.preferences:
  290.             if not pref.switches:
  291.                 continue
  292.             
  293.             g = groups[pref.group]
  294.             action = pref.action
  295.             if action is None:
  296.                 action = 'store'
  297.                 if pref.default is True or pref.default is False:
  298.                     action = None + 'store_' if pref.default else 'true'
  299.                 
  300.             
  301.             args = dict(dest = pref.name, help = pref.help, metavar = pref.metavar, type = pref.type, choices = pref.choices, default = getattr(user_defaults, pref.name, pref.default), action = action)
  302.             g.add_option(*pref.switches, **args)
  303.         
  304.         return parser
  305.  
  306.     
  307.     def get_override_section(self, src):
  308.         match = self.OVERRIDE_PAT.search(src)
  309.         if match:
  310.             return match.group()
  311.         return ''
  312.  
  313.     
  314.     def parse_string(self, src):
  315.         options = {
  316.             'cPickle': cPickle }
  317.         if src is not None:
  318.             
  319.             try:
  320.                 if not isinstance(src, unicode):
  321.                     src = src.decode('utf-8')
  322.                 
  323.                 exec src in options
  324.             print 'Failed to parse options string:'
  325.             print repr(src)
  326.             traceback.print_exc()
  327.  
  328.         
  329.         opts = OptionValues()
  330.         for pref in self.preferences:
  331.             val = options.get(pref.name, pref.default)
  332.             formatter = __builtins__.get(pref.type, None)
  333.             if callable(formatter):
  334.                 val = formatter(val)
  335.             
  336.             setattr(opts, pref.name, val)
  337.         
  338.         return opts
  339.  
  340.     
  341.     def render_group(self, name, desc, opts):
  342.         prefs = _[1]
  343.         lines = [
  344.             [] % '### Begin group: %s' if name else 'DEFAULT']
  345.         if desc:
  346.             lines += map((lambda x: '# ' + x), desc.split('\n'))
  347.         
  348.         lines.append(' ')
  349.         for pref in prefs:
  350.             lines.append('# ' + pref.name.replace('_', ' '))
  351.             if pref.help:
  352.                 lines += map((lambda x: '# ' + x), pref.help.split('\n'))
  353.             
  354.             lines.append('%s = %s' % (pref.name, self.serialize_opt(getattr(opts, pref.name, pref.default))))
  355.             lines.append(' ')
  356.         
  357.         return '\n'.join(lines)
  358.  
  359.     
  360.     def serialize_opt(self, val):
  361.         if val is val:
  362.             pass
  363.         elif val is True and val is False and val is None or isinstance(val, (int, float, long, basestring)):
  364.             return repr(val)
  365.         QString = QString
  366.         import PyQt4.QtCore
  367.         if isinstance(val, QString):
  368.             return repr(unicode(val))
  369.         pickle = cPickle.dumps(val, -1)
  370.         return 'cPickle.loads(%s)' % repr(pickle)
  371.  
  372.     
  373.     def serialize(self, opts):
  374.         src = '# %s\n\n' % self.description.replace('\n', '\n# ')
  375.         groups = [ self.render_group(name, self.groups.get(name, ''), opts) for name in [
  376.             None] + self.group_list ]
  377.         return src + '\n\n'.join(groups)
  378.  
  379.  
  380.  
  381. class ConfigInterface(object):
  382.     
  383.     def __init__(self, description):
  384.         self.option_set = OptionSet(description = description)
  385.         self.add_opt = self.option_set.add_opt
  386.         self.add_group = self.option_set.add_group
  387.         self.remove_opt = self.remove = self.option_set.remove_opt
  388.         self.parse_string = self.option_set.parse_string
  389.         self.get_option = self.option_set.get_option
  390.         self.preferences = self.option_set.preferences
  391.  
  392.     
  393.     def update(self, other):
  394.         self.option_set.update(other.option_set)
  395.  
  396.     
  397.     def option_parser(self, usage = '', gui_mode = False):
  398.         return self.option_set.option_parser(user_defaults = self.parse(), usage = usage, gui_mode = gui_mode)
  399.  
  400.     
  401.     def smart_update(self, opts1, opts2):
  402.         self.option_set.smart_update(opts1, opts2)
  403.  
  404.  
  405.  
  406. class Config(ConfigInterface):
  407.     
  408.     def __init__(self, basename, description = ''):
  409.         ConfigInterface.__init__(self, description)
  410.         self.config_file_path = os.path.join(config_dir, basename + '.py')
  411.  
  412.     
  413.     def parse(self):
  414.         src = ''
  415.         if os.path.exists(self.config_file_path):
  416.             
  417.             try:
  418.                 
  419.                 try:
  420.                     f = _[1]
  421.                     
  422.                     try:
  423.                         src = f.read().decode('utf-8')
  424.                     except ValueError:
  425.                         ExclusiveFile(self.config_file_path).__exit__
  426.                         ExclusiveFile(self.config_file_path).__exit__
  427.                         ExclusiveFile(self.config_file_path)
  428.                         print 'Failed to parse', self.config_file_path
  429.                         traceback.print_exc()
  430.                     except:
  431.                         ExclusiveFile(self.config_file_path).__exit__
  432.  
  433.                 finally:
  434.                     pass
  435.  
  436.             except LockError:
  437.                 raise IOError('Could not lock config file: %s' % self.config_file_path)
  438.             except:
  439.                 None<EXCEPTION MATCH>LockError
  440.             
  441.  
  442.         None<EXCEPTION MATCH>LockError
  443.         return self.option_set.parse_string(src)
  444.  
  445.     
  446.     def as_string(self):
  447.         if not os.path.exists(self.config_file_path):
  448.             return ''
  449.         
  450.         try:
  451.             
  452.             try:
  453.                 f = _[1]
  454.                 return f.read().decode('utf-8')
  455.             finally:
  456.                 pass
  457.  
  458.         except LockError:
  459.             os.path.exists(self.config_file_path)
  460.             os.path.exists(self.config_file_path)
  461.             raise IOError('Could not lock config file: %s' % self.config_file_path)
  462.         except:
  463.             os.path.exists(self.config_file_path)
  464.  
  465.  
  466.     
  467.     def set(self, name, val):
  468.         if not self.option_set.has_option(name):
  469.             raise ValueError('The option %s is not defined.' % name)
  470.         self.option_set.has_option(name)
  471.         
  472.         try:
  473.             if not os.path.exists(config_dir):
  474.                 make_config_dir()
  475.             
  476.             
  477.             try:
  478.                 f = _[1]
  479.                 src = f.read()
  480.                 opts = self.option_set.parse_string(src)
  481.                 setattr(opts, name, val)
  482.                 footer = self.option_set.get_override_section(src)
  483.                 src = self.option_set.serialize(opts) + '\n\n' + footer + '\n'
  484.                 f.seek(0)
  485.                 f.truncate()
  486.                 f.write(src)
  487.             finally:
  488.                 pass
  489.  
  490.         except LockError:
  491.             raise IOError('Could not lock config file: %s' % self.config_file_path)
  492.  
  493.  
  494.  
  495.  
  496. class StringConfig(ConfigInterface):
  497.     
  498.     def __init__(self, src, description = ''):
  499.         ConfigInterface.__init__(self, description)
  500.         self.src = src
  501.  
  502.     
  503.     def parse(self):
  504.         return self.option_set.parse_string(self.src)
  505.  
  506.     
  507.     def set(self, name, val):
  508.         if not self.option_set.has_option(name):
  509.             raise ValueError('The option %s is not defined.' % name)
  510.         self.option_set.has_option(name)
  511.         opts = self.option_set.parse_string(self.src)
  512.         setattr(opts, name, val)
  513.         footer = self.option_set.get_override_section(self.src)
  514.         self.src = self.option_set.serialize(opts) + '\n\n' + footer + '\n'
  515.  
  516.  
  517.  
  518. class ConfigProxy(object):
  519.     
  520.     def __init__(self, config):
  521.         self._ConfigProxy__config = config
  522.         self._ConfigProxy__opts = None
  523.  
  524.     
  525.     def refresh(self):
  526.         self._ConfigProxy__opts = self._ConfigProxy__config.parse()
  527.  
  528.     
  529.     def __getitem__(self, key):
  530.         return self.get(key)
  531.  
  532.     
  533.     def __setitem__(self, key, val):
  534.         return self.set(key, val)
  535.  
  536.     
  537.     def get(self, key):
  538.         if self._ConfigProxy__opts is None:
  539.             self.refresh()
  540.         
  541.         return getattr(self._ConfigProxy__opts, key)
  542.  
  543.     
  544.     def set(self, key, val):
  545.         if self._ConfigProxy__opts is None:
  546.             self.refresh()
  547.         
  548.         setattr(self._ConfigProxy__opts, key, val)
  549.         return self._ConfigProxy__config.set(key, val)
  550.  
  551.  
  552.  
  553. class DynamicConfig(dict):
  554.     
  555.     def __init__(self, name = 'dynamic'):
  556.         dict.__init__(self, { })
  557.         self.name = name
  558.         self.file_path = os.path.join(config_dir, name + '.pickle')
  559.         self.refresh()
  560.  
  561.     
  562.     def refresh(self):
  563.         d = { }
  564.         self.clear()
  565.         self.update(d)
  566.  
  567.     
  568.     def __getitem__(self, key):
  569.         
  570.         try:
  571.             return dict.__getitem__(self, key)
  572.         except KeyError:
  573.             return None
  574.  
  575.  
  576.     
  577.     def __setitem__(self, key, val):
  578.         dict.__setitem__(self, key, val)
  579.         self.commit()
  580.  
  581.     
  582.     def set(self, key, val):
  583.         self.__setitem__(key, val)
  584.  
  585.     
  586.     def commit(self):
  587.         pass
  588.  
  589.  
  590. dynamic = DynamicConfig()
  591.  
  592. class XMLConfig(dict):
  593.     EXTENSION = '.plist'
  594.     
  595.     def __init__(self, rel_path_to_cf_file):
  596.         dict.__init__(self)
  597.         self.file_path = os.path.join(config_dir, *rel_path_to_cf_file.split('/'))
  598.         self.file_path = os.path.abspath(self.file_path)
  599.         if not self.file_path.endswith(self.EXTENSION):
  600.             self.file_path += self.EXTENSION
  601.         
  602.         self.refresh()
  603.  
  604.     
  605.     def raw_to_object(self, raw):
  606.         return plistlib.readPlistFromString(raw)
  607.  
  608.     
  609.     def to_raw(self):
  610.         return plistlib.writePlistToString(self)
  611.  
  612.     
  613.     def refresh(self):
  614.         d = { }
  615.         self.clear()
  616.         self.update(d)
  617.  
  618.     
  619.     def __getitem__(self, key):
  620.         
  621.         try:
  622.             ans = dict.__getitem__(self, key)
  623.             if isinstance(ans, plistlib.Data):
  624.                 ans = ans.data
  625.             
  626.             return ans
  627.         except KeyError:
  628.             return None
  629.  
  630.  
  631.     
  632.     def __setitem__(self, key, val):
  633.         if isinstance(val, (bytes, str)):
  634.             val = plistlib.Data(val)
  635.         
  636.         dict.__setitem__(self, key, val)
  637.         self.commit()
  638.  
  639.     
  640.     def set(self, key, val):
  641.         self.__setitem__(key, val)
  642.  
  643.     
  644.     def __delitem__(self, key):
  645.         dict.__delitem__(self, key)
  646.         self.commit()
  647.  
  648.     
  649.     def commit(self):
  650.         pass
  651.  
  652.  
  653.  
  654. def to_json(obj):
  655.     if isinstance(obj, bytearray):
  656.         return {
  657.             '__class__': 'bytearray',
  658.             '__value__': base64.standard_b64encode(bytes(obj)) }
  659.     if isinstance(obj, datetime.datetime):
  660.         isoformat = isoformat
  661.         import calibre.utils.date
  662.         return {
  663.             '__class__': 'datetime.datetime',
  664.             '__value__': isoformat(obj, as_utc = True) }
  665.     raise TypeError(repr(obj) + ' is not JSON serializable')
  666.  
  667.  
  668. def from_json(obj):
  669.     return obj
  670.  
  671.  
  672. class JSONConfig(XMLConfig):
  673.     EXTENSION = '.json'
  674.     
  675.     def raw_to_object(self, raw):
  676.         return json.loads(raw.decode('utf-8'), object_hook = from_json)
  677.  
  678.     
  679.     def to_raw(self):
  680.         return json.dumps(self, indent = 2, default = to_json)
  681.  
  682.     
  683.     def __getitem__(self, key):
  684.         return dict.__getitem__(self, key)
  685.  
  686.     
  687.     def __setitem__(self, key, val):
  688.         dict.__setitem__(self, key, val)
  689.         self.commit()
  690.  
  691.  
  692.  
  693. def _prefs():
  694.     c = Config('global', 'calibre wide preferences')
  695.     c.add_opt('database_path', default = os.path.expanduser('~/library1.db'), help = _('Path to the database in which books are stored'))
  696.     c.add_opt('filename_pattern', default = u'(?P<title>.+) - (?P<author>[^_]+)', help = _('Pattern to guess metadata from filenames'))
  697.     c.add_opt('isbndb_com_key', default = '', help = _('Access key for isbndb.com'))
  698.     c.add_opt('network_timeout', default = 5, help = _('Default timeout for network operations (seconds)'))
  699.     c.add_opt('library_path', default = None, help = _('Path to directory in which your library of books is stored'))
  700.     c.add_opt('language', default = None, help = _('The language in which to display the user interface'))
  701.     c.add_opt('output_format', default = 'EPUB', help = _('The default output format for ebook conversions.'))
  702.     c.add_opt('input_format_order', default = [
  703.         'EPUB',
  704.         'MOBI',
  705.         'LIT',
  706.         'PRC',
  707.         'FB2',
  708.         'HTML',
  709.         'HTM',
  710.         'XHTM',
  711.         'SHTML',
  712.         'XHTML',
  713.         'ODT',
  714.         'RTF',
  715.         'PDF',
  716.         'TXT'], help = _('Ordered list of formats to prefer for input.'))
  717.     c.add_opt('read_file_metadata', default = True, help = _('Read metadata from files'))
  718.     c.add_opt('worker_process_priority', default = 'normal', help = _('The priority of worker processes'))
  719.     c.add_opt('swap_author_names', default = False, help = _('Swap author first and last names when reading metadata'))
  720.     c.add_opt('add_formats_to_existing', default = False, help = _('Add new formats to existing book records'))
  721.     c.add_opt('installation_uuid', default = None, help = 'Installation UUID')
  722.     c.add_opt('saved_searches', default = { }, help = _('List of named saved searches'))
  723.     c.add_opt('user_categories', default = { }, help = _('User-created tag browser categories'))
  724.     c.add_opt('manage_device_metadata', default = 'manual', help = _('How and when calibre updates metadata on the device.'))
  725.     c.add_opt('migrated', default = False, help = "For Internal use. Don't modify.")
  726.     return c
  727.  
  728. prefs = ConfigProxy(_prefs())
  729. if prefs['installation_uuid'] is None:
  730.     import uuid
  731.     prefs['installation_uuid'] = str(uuid.uuid4())
  732.  
  733.  
  734. def read_tweaks():
  735.     make_config_dir()
  736.     default_tweaks = P('default_tweaks.py', data = True)
  737.     tweaks_file = os.path.join(config_dir, 'tweaks.py')
  738.     l = { }
  739.     g = { }
  740.     
  741.     try:
  742.         exec open(tweaks_file, 'rb') in g, l
  743.     except:
  744.         None if not os.path.exists(tweaks_file) else open(tweaks_file, 'wb')
  745.         print 'Failed to load custom tweaks file'
  746.         traceback.print_exc()
  747.  
  748.     dl = { }
  749.     dg = { }
  750.     exec default_tweaks in dg, dl
  751.     dl.update(l)
  752.     return dl
  753.  
  754. tweaks = read_tweaks()
  755.  
  756. def migrate():
  757.     if hasattr(os, 'geteuid') and os.geteuid() == 0:
  758.         return None
  759.     p = prefs
  760.     if p.get('migrated'):
  761.         return None
  762.     QSettings = QSettings
  763.     QVariant = QVariant
  764.     import PyQt4.QtCore
  765.     
  766.     class Settings('Settings', (QSettings,)):
  767.         
  768.         def __init__(self, name = ('calibre2',)):
  769.             QSettings.__init__(self, QSettings.IniFormat, QSettings.UserScope, 'kovidgoyal.net', name)
  770.  
  771.         
  772.         def get(self, key, default = (None,)):
  773.             
  774.             try:
  775.                 key = str(key)
  776.                 if not self.contains(key):
  777.                     return default
  778.                 val = str(self.value(key, QVariant()).toByteArray())
  779.                 if not val:
  780.                     return None
  781.                 return cPickle.loads(val)
  782.             except:
  783.                 return default
  784.  
  785.  
  786.  
  787.     s = Settings()
  788.     migrated = set([])
  789.     all_keys = set(map(unicode, s.allKeys()))
  790.     config = config
  791.     dynamic = dynamic
  792.     import calibre.gui2
  793.     
  794.     def _migrate(key, safe = None, from_qvariant = os.geteuid() == 0, p = (None, None, config)):
  795.         
  796.         try:
  797.             if key not in all_keys:
  798.                 return None
  799.             if safe is None:
  800.                 safe = re.sub('[^0-9a-zA-Z]', '_', key)
  801.             
  802.             val = s.get(key)
  803.             if from_qvariant is not None:
  804.                 val = getattr(s.value(key), from_qvariant)()
  805.             
  806.             p.set(safe, val)
  807.         except:
  808.             pass
  809.         finally:
  810.             migrated.add(key)
  811.  
  812.  
  813.     _migrate('database path', p = prefs)
  814.     _migrate('filename pattern', p = prefs)
  815.     _migrate('network timeout', p = prefs)
  816.     _migrate('isbndb.com key', p = prefs)
  817.     _migrate('frequently used directories')
  818.     _migrate('send to device by default')
  819.     _migrate('save to disk single format')
  820.     _migrate('confirm delete')
  821.     _migrate('show text in toolbar')
  822.     _migrate('new version notification')
  823.     _migrate('use roman numerals for series number')
  824.     _migrate('cover flow queue length')
  825.     _migrate('LRF conversion defaults')
  826.     _migrate('LRF ebook viewer options')
  827.     for key in all_keys - migrated:
  828.         if key.endswith(': un') or key.endswith(': pw'):
  829.             _migrate(key, p = dynamic)
  830.             continue
  831.     
  832.     p.set('migrated', True)
  833.  
  834.