Remove single format save option

This commit is contained in:
Kovid Goyal 2009-05-08 22:37:16 -07:00
parent 5f0c27e6d6
commit 486e1fd375
6 changed files with 126 additions and 150 deletions

View File

@ -27,8 +27,6 @@ def _config():
help=_('Frequently used directories')) help=_('Frequently used directories'))
c.add_opt('send_to_storage_card_by_default', default=False, c.add_opt('send_to_storage_card_by_default', default=False,
help=_('Send file to storage card instead of main memory by default')) help=_('Send file to storage card instead of main memory by default'))
c.add_opt('save_to_disk_single_format', default='lrf',
help=_('The format to use when saving single files to disk'))
c.add_opt('confirm_delete', default=False, c.add_opt('confirm_delete', default=False,
help=_('Confirm before deleting')) help=_('Confirm before deleting'))
c.add_opt('toolbar_icon_size', default=QSize(48, 48), c.add_opt('toolbar_icon_size', default=QSize(48, 48),

View File

@ -391,20 +391,16 @@ class ConfigDialog(QDialog, Ui_Dialog):
icons = config['toolbar_icon_size'] icons = config['toolbar_icon_size']
self.toolbar_button_size.setCurrentIndex(0 if icons == self.ICON_SIZES[0] else 1 if icons == self.ICON_SIZES[1] else 2) self.toolbar_button_size.setCurrentIndex(0 if icons == self.ICON_SIZES[0] else 1 if icons == self.ICON_SIZES[1] else 2)
self.show_toolbar_text.setChecked(config['show_text_in_toolbar']) self.show_toolbar_text.setChecked(config['show_text_in_toolbar'])
output_formats = sorted(available_output_formats()) output_formats = sorted(available_output_formats())
output_formats.remove('oeb') output_formats.remove('oeb')
for f in output_formats: for f in output_formats:
self.output_format.addItem(f) self.output_format.addItem(f.upper())
default_index = self.output_format.findText(prefs['output_format']) default_index = \
self.output_format.findText(prefs['output_format'].upper())
self.output_format.setCurrentIndex(default_index if default_index != -1 else 0) self.output_format.setCurrentIndex(default_index if default_index != -1 else 0)
self.book_exts = sorted(BOOK_EXTENSIONS)
for ext in self.book_exts:
self.single_format.addItem(ext.upper(), QVariant(ext))
single_format = config['save_to_disk_single_format']
self.single_format.setCurrentIndex(self.book_exts.index(single_format))
self.cover_browse.setValue(config['cover_flow_queue_length']) self.cover_browse.setValue(config['cover_flow_queue_length'])
self.systray_notifications.setChecked(not config['disable_tray_notification']) self.systray_notifications.setChecked(not config['disable_tray_notification'])
from calibre.translations.compiled import translations from calibre.translations.compiled import translations
@ -426,17 +422,17 @@ class ConfigDialog(QDialog, Ui_Dialog):
self.pdf_metadata.setChecked(prefs['read_file_metadata']) self.pdf_metadata.setChecked(prefs['read_file_metadata'])
added_html = False exts = set([])
for ext in self.book_exts: for ext in BOOK_EXTENSIONS:
ext = ext.lower() ext = ext.lower()
ext = re.sub(r'(x{0,1})htm(l{0,1})', 'html', ext) ext = re.sub(r'(x{0,1})htm(l{0,1})', 'html', ext)
if ext == 'lrf' or is_supported('book.'+ext): if ext == 'lrf' or is_supported('book.'+ext):
if ext == 'html' and added_html: exts.add(ext)
continue
self.viewer.addItem(ext.upper()) for ext in sorted(exts):
self.viewer.item(self.viewer.count()-1).setFlags(Qt.ItemIsEnabled|Qt.ItemIsUserCheckable) self.viewer.addItem(ext.upper())
self.viewer.item(self.viewer.count()-1).setCheckState(Qt.Checked if ext.upper() in config['internally_viewed_formats'] else Qt.Unchecked) self.viewer.item(self.viewer.count()-1).setFlags(Qt.ItemIsEnabled|Qt.ItemIsUserCheckable)
added_html = ext == 'html' self.viewer.item(self.viewer.count()-1).setCheckState(Qt.Checked if ext.upper() in config['internally_viewed_formats'] else Qt.Unchecked)
self.viewer.sortItems() self.viewer.sortItems()
self.start.setEnabled(not getattr(self.server, 'is_running', False)) self.start.setEnabled(not getattr(self.server, 'is_running', False))
self.test.setEnabled(not self.start.isEnabled()) self.test.setEnabled(not self.start.isEnabled())
@ -767,8 +763,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
p = {0:'normal', 1:'high', 2:'low'}[self.priority.currentIndex()] p = {0:'normal', 1:'high', 2:'low'}[self.priority.currentIndex()]
prefs['worker_process_priority'] = p prefs['worker_process_priority'] = p
prefs['read_file_metadata'] = bool(self.pdf_metadata.isChecked()) prefs['read_file_metadata'] = bool(self.pdf_metadata.isChecked())
prefs['output_format'] = self.output_format.currentText() prefs['output_format'] = unicode(self.output_format.currentText()).upper()
config['save_to_disk_single_format'] = self.book_exts[self.single_format.currentIndex()]
config['cover_flow_queue_length'] = self.cover_browse.value() config['cover_flow_queue_length'] = self.cover_browse.value()
prefs['language'] = str(self.language.itemData(self.language.currentIndex()).toString()) prefs['language'] = str(self.language.itemData(self.language.currentIndex()).toString())
config['systray_icon'] = self.systray_icon.checkState() == Qt.Checked config['systray_icon'] = self.systray_icon.checkState() == Qt.Checked

View File

@ -147,19 +147,6 @@
<item> <item>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Format for &amp;single file save:</string>
</property>
<property name="buddy">
<cstring>single_format</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="single_format"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>Default network &amp;timeout:</string> <string>Default network &amp;timeout:</string>
@ -169,7 +156,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="1" column="1">
<widget class="QSpinBox" name="timeout"> <widget class="QSpinBox" name="timeout">
<property name="toolTip"> <property name="toolTip">
<string>Set the default timeout for network fetches (i.e. anytime we go out to the internet to get information)</string> <string>Set the default timeout for network fetches (i.e. anytime we go out to the internet to get information)</string>
@ -188,10 +175,10 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="2" column="1">
<widget class="QComboBox" name="language"/> <widget class="QComboBox" name="language"/>
</item> </item>
<item row="3" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_7"> <widget class="QLabel" name="label_7">
<property name="text"> <property name="text">
<string>Choose &amp;language (requires restart):</string> <string>Choose &amp;language (requires restart):</string>
@ -201,7 +188,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="3" column="1">
<widget class="QComboBox" name="priority"> <widget class="QComboBox" name="priority">
<item> <item>
<property name="text"> <property name="text">
@ -220,7 +207,7 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="3" column="0">
<widget class="QLabel" name="priority_label"> <widget class="QLabel" name="priority_label">
<property name="text"> <property name="text">
<string>Job &amp;priority:</string> <string>Job &amp;priority:</string>

View File

@ -201,8 +201,6 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
self.save_menu = QMenu() self.save_menu = QMenu()
self.save_menu.addAction(_('Save to disk')) self.save_menu.addAction(_('Save to disk'))
self.save_menu.addAction(_('Save to disk in a single directory')) self.save_menu.addAction(_('Save to disk in a single directory'))
self.save_menu.addAction(_('Save only %s format to disk')%\
config.get('save_to_disk_single_format').upper())
self.view_menu = QMenu() self.view_menu = QMenu()
self.view_menu.addAction(_('View')) self.view_menu.addAction(_('View'))
@ -214,8 +212,6 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
self.save_to_disk) self.save_to_disk)
QObject.connect(self.save_menu.actions()[1], SIGNAL("triggered(bool)"), QObject.connect(self.save_menu.actions()[1], SIGNAL("triggered(bool)"),
self.save_to_single_dir) self.save_to_single_dir)
QObject.connect(self.save_menu.actions()[2], SIGNAL("triggered(bool)"),
self.save_single_format_to_disk)
QObject.connect(self.action_view, SIGNAL("triggered(bool)"), QObject.connect(self.action_view, SIGNAL("triggered(bool)"),
self.view_book) self.view_book)
QObject.connect(self.view_menu.actions()[0], QObject.connect(self.view_menu.actions()[0],

View File

@ -42,7 +42,7 @@
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>16777215</width> <width>16777215</width>
<height>100</height> <height>75</height>
</size> </size>
</property> </property>
<property name="verticalScrollBarPolicy"> <property name="verticalScrollBarPolicy">

View File

@ -14,7 +14,7 @@ from optparse import IndentedHelpFormatter
from PyQt4.QtCore import QString from PyQt4.QtCore import QString
from calibre.constants import terminal_controller, iswindows, isosx, \ from calibre.constants import terminal_controller, iswindows, isosx, \
__appname__, __version__, __author__, plugins __appname__, __version__, __author__, plugins
from calibre.utils.lock import LockError, ExclusiveFile from calibre.utils.lock import LockError, ExclusiveFile
from collections import defaultdict from collections import defaultdict
if os.environ.has_key('CALIBRE_CONFIG_DIRECTORY'): if os.environ.has_key('CALIBRE_CONFIG_DIRECTORY'):
@ -38,14 +38,14 @@ def make_config_dir():
class CustomHelpFormatter(IndentedHelpFormatter): class CustomHelpFormatter(IndentedHelpFormatter):
def format_usage(self, usage): def format_usage(self, usage):
return _("%sUsage%s: %s\n") % (terminal_controller.BLUE, terminal_controller.NORMAL, usage) return _("%sUsage%s: %s\n") % (terminal_controller.BLUE, terminal_controller.NORMAL, usage)
def format_heading(self, heading): def format_heading(self, heading):
return "%*s%s%s%s:\n" % (self.current_indent, terminal_controller.BLUE, return "%*s%s%s%s:\n" % (self.current_indent, terminal_controller.BLUE,
"", heading, terminal_controller.NORMAL) "", heading, terminal_controller.NORMAL)
def format_option(self, option): def format_option(self, option):
result = [] result = []
opts = self.option_strings[option] opts = self.option_strings[option]
@ -55,14 +55,14 @@ class CustomHelpFormatter(IndentedHelpFormatter):
terminal_controller.GREEN+opts+terminal_controller.NORMAL) terminal_controller.GREEN+opts+terminal_controller.NORMAL)
indent_first = self.help_position indent_first = self.help_position
else: # start help on same line as opts else: # start help on same line as opts
opts = "%*s%-*s " % (self.current_indent, "", opt_width + len(terminal_controller.GREEN + terminal_controller.NORMAL), opts = "%*s%-*s " % (self.current_indent, "", opt_width + len(terminal_controller.GREEN + terminal_controller.NORMAL),
terminal_controller.GREEN + opts + terminal_controller.NORMAL) terminal_controller.GREEN + opts + terminal_controller.NORMAL)
indent_first = 0 indent_first = 0
result.append(opts) result.append(opts)
if option.help: if option.help:
help_text = self.expand_default(option).split('\n') help_text = self.expand_default(option).split('\n')
help_lines = [] help_lines = []
for line in help_text: for line in help_text:
help_lines.extend(textwrap.wrap(line, self.help_width)) help_lines.extend(textwrap.wrap(line, self.help_width))
result.append("%*s%s\n" % (indent_first, "", help_lines[0])) result.append("%*s%s\n" % (indent_first, "", help_lines[0]))
@ -74,7 +74,7 @@ class CustomHelpFormatter(IndentedHelpFormatter):
class OptionParser(_OptionParser): class OptionParser(_OptionParser):
def __init__(self, def __init__(self,
usage='%prog [options] filename', usage='%prog [options] filename',
version='%%prog (%s %s)'%(__appname__, __version__), version='%%prog (%s %s)'%(__appname__, __version__),
@ -85,16 +85,16 @@ class OptionParser(_OptionParser):
usage = textwrap.dedent(usage) usage = textwrap.dedent(usage)
usage += '''\n\nWhenever you pass arguments to %prog that have spaces in them, '''\ usage += '''\n\nWhenever you pass arguments to %prog that have spaces in them, '''\
'''enclose the arguments in quotation marks.''' '''enclose the arguments in quotation marks.'''
_OptionParser.__init__(self, usage=usage, version=version, epilog=epilog, _OptionParser.__init__(self, usage=usage, version=version, epilog=epilog,
formatter=CustomHelpFormatter(), formatter=CustomHelpFormatter(),
conflict_handler=conflict_handler, **kwds) conflict_handler=conflict_handler, **kwds)
self.gui_mode = gui_mode self.gui_mode = gui_mode
def error(self, msg): def error(self, msg):
if self.gui_mode: if self.gui_mode:
raise Exception(msg) raise Exception(msg)
_OptionParser.error(self, msg) _OptionParser.error(self, msg)
def merge(self, parser): def merge(self, parser):
''' '''
Add options from parser to self. In case of conflicts, conflicting options from Add options from parser to self. In case of conflicts, conflicting options from
@ -102,18 +102,18 @@ class OptionParser(_OptionParser):
''' '''
opts = list(parser.option_list) opts = list(parser.option_list)
groups = list(parser.option_groups) groups = list(parser.option_groups)
def merge_options(options, container): def merge_options(options, container):
for opt in deepcopy(options): for opt in deepcopy(options):
if not self.has_option(opt.get_opt_string()): if not self.has_option(opt.get_opt_string()):
container.add_option(opt) container.add_option(opt)
merge_options(opts, self) merge_options(opts, self)
for group in groups: for group in groups:
g = self.add_option_group(group.title) g = self.add_option_group(group.title)
merge_options(group.option_list, g) merge_options(group.option_list, g)
def subsume(self, group_name, msg=''): def subsume(self, group_name, msg=''):
''' '''
Move all existing options into a subgroup named Move all existing options into a subgroup named
@ -125,7 +125,7 @@ class OptionParser(_OptionParser):
for opt in opts: for opt in opts:
self.remove_option(opt.get_opt_string()) self.remove_option(opt.get_opt_string())
subgroup.add_option(opt) subgroup.add_option(opt)
def options_iter(self): def options_iter(self):
for opt in self.option_list: for opt in self.option_list:
if str(opt).strip(): if str(opt).strip():
@ -134,12 +134,12 @@ class OptionParser(_OptionParser):
for opt in gr.option_list: for opt in gr.option_list:
if str(opt).strip(): if str(opt).strip():
yield opt yield opt
def option_by_dest(self, dest): def option_by_dest(self, dest):
for opt in self.options_iter(): for opt in self.options_iter():
if opt.dest == dest: if opt.dest == dest:
return opt return opt
def merge_options(self, lower, upper): def merge_options(self, lower, upper):
''' '''
Merge options in lower and upper option lists into upper. Merge options in lower and upper option lists into upper.
@ -153,16 +153,16 @@ class OptionParser(_OptionParser):
if lower.__dict__[dest] != opt.default and \ if lower.__dict__[dest] != opt.default and \
upper.__dict__[dest] == opt.default: upper.__dict__[dest] == opt.default:
upper.__dict__[dest] = lower.__dict__[dest] upper.__dict__[dest] = lower.__dict__[dest]
class Option(object): class Option(object):
def __init__(self, name, switches=[], help='', type=None, choices=None, def __init__(self, name, switches=[], help='', type=None, choices=None,
check=None, group=None, default=None, action=None, metavar=None): check=None, group=None, default=None, action=None, metavar=None):
if choices: if choices:
type = 'choice' type = 'choice'
self.name = name self.name = name
self.switches = switches self.switches = switches
self.help = help.replace('%default', repr(default)) if help else None self.help = help.replace('%default', repr(default)) if help else None
@ -172,40 +172,40 @@ class Option(object):
self.type = 'float' self.type = 'float'
elif isinstance(default, int) and not isinstance(default, bool): elif isinstance(default, int) and not isinstance(default, bool):
self.type = 'int' self.type = 'int'
self.choices = choices self.choices = choices
self.check = check self.check = check
self.group = group self.group = group
self.default = default self.default = default
self.action = action self.action = action
self.metavar = metavar self.metavar = metavar
def __eq__(self, other): def __eq__(self, other):
return self.name == getattr(other, 'name', other) return self.name == getattr(other, 'name', other)
def __repr__(self): def __repr__(self):
return 'Option: '+self.name return 'Option: '+self.name
def __str__(self): def __str__(self):
return repr(self) return repr(self)
class OptionValues(object): class OptionValues(object):
def copy(self): def copy(self):
return deepcopy(self) return deepcopy(self)
class OptionSet(object): class OptionSet(object):
OVERRIDE_PAT = re.compile(r'#{3,100} Override Options #{15}(.*?)#{3,100} End Override #{3,100}', OVERRIDE_PAT = re.compile(r'#{3,100} Override Options #{15}(.*?)#{3,100} End Override #{3,100}',
re.DOTALL|re.IGNORECASE) re.DOTALL|re.IGNORECASE)
def __init__(self, description=''): def __init__(self, description=''):
self.description = description self.description = description
self.preferences = [] self.preferences = []
self.group_list = [] self.group_list = []
self.groups = {} self.groups = {}
self.set_buffer = {} self.set_buffer = {}
def has_option(self, name_or_option_object): def has_option(self, name_or_option_object):
if name_or_option_object in self.preferences: if name_or_option_object in self.preferences:
return True return True
@ -213,14 +213,14 @@ class OptionSet(object):
if p.name == name_or_option_object: if p.name == name_or_option_object:
return True return True
return False return False
def add_group(self, name, description=''): def add_group(self, name, description=''):
if name in self.group_list: if name in self.group_list:
raise ValueError('A group by the name %s already exists in this set'%name) raise ValueError('A group by the name %s already exists in this set'%name)
self.groups[name] = description self.groups[name] = description
self.group_list.append(name) self.group_list.append(name)
return partial(self.add_opt, group=name) return partial(self.add_opt, group=name)
def update(self, other): def update(self, other):
for name in other.groups.keys(): for name in other.groups.keys():
self.groups[name] = other.groups[name] self.groups[name] = other.groups[name]
@ -230,7 +230,7 @@ class OptionSet(object):
if pref in self.preferences: if pref in self.preferences:
self.preferences.remove(pref) self.preferences.remove(pref)
self.preferences.append(pref) self.preferences.append(pref)
def smart_update(self, opts1, opts2): def smart_update(self, opts1, opts2):
''' '''
Updates the preference values in opts1 using only the non-default preference values in opts2. Updates the preference values in opts1 using only the non-default preference values in opts2.
@ -239,47 +239,47 @@ class OptionSet(object):
new = getattr(opts2, pref.name, pref.default) new = getattr(opts2, pref.name, pref.default)
if new != pref.default: if new != pref.default:
setattr(opts1, pref.name, new) setattr(opts1, pref.name, new)
def remove_opt(self, name): def remove_opt(self, name):
if name in self.preferences: if name in self.preferences:
self.preferences.remove(name) self.preferences.remove(name)
def add_opt(self, name, switches=[], help=None, type=None, choices=None, def add_opt(self, name, switches=[], help=None, type=None, choices=None,
group=None, default=None, action=None, metavar=None): group=None, default=None, action=None, metavar=None):
''' '''
Add an option to this section. Add an option to this section.
:param name: The name of this option. Must be a valid Python identifier. :param name: The name of this option. Must be a valid Python identifier.
Must also be unique in this OptionSet and all its subsets. Must also be unique in this OptionSet and all its subsets.
:param switches: List of command line switches for this option :param switches: List of command line switches for this option
(as supplied to :module:`optparse`). If empty, this (as supplied to :module:`optparse`). If empty, this
option will not be added to the command line parser. option will not be added to the command line parser.
:param help: Help text. :param help: Help text.
:param type: Type checking of option values. Supported types are: :param type: Type checking of option values. Supported types are:
`None, 'choice', 'complex', 'float', 'int', 'string'`. `None, 'choice', 'complex', 'float', 'int', 'string'`.
:param choices: List of strings or `None`. :param choices: List of strings or `None`.
:param group: Group this option belongs to. You must previously :param group: Group this option belongs to. You must previously
have created this group with a call to :method:`add_group`. have created this group with a call to :method:`add_group`.
:param default: The default value for this option. :param default: The default value for this option.
:param action: The action to pass to optparse. Supported values are: :param action: The action to pass to optparse. Supported values are:
`None, 'count'`. For choices and boolean options, `None, 'count'`. For choices and boolean options,
action is automatically set correctly. action is automatically set correctly.
''' '''
pref = Option(name, switches=switches, help=help, type=type, choices=choices, pref = Option(name, switches=switches, help=help, type=type, choices=choices,
group=group, default=default, action=action, metavar=None) group=group, default=default, action=action, metavar=None)
if group is not None and group not in self.groups.keys(): if group is not None and group not in self.groups.keys():
raise ValueError('Group %s has not been added to this section'%group) raise ValueError('Group %s has not been added to this section'%group)
if pref in self.preferences: if pref in self.preferences:
raise ValueError('An option with the name %s already exists in this set.'%name) raise ValueError('An option with the name %s already exists in this set.'%name)
self.preferences.append(pref) self.preferences.append(pref)
def option_parser(self, user_defaults=None, usage='', gui_mode=False): def option_parser(self, user_defaults=None, usage='', gui_mode=False):
parser = OptionParser(usage, gui_mode=gui_mode) parser = OptionParser(usage, gui_mode=gui_mode)
groups = defaultdict(lambda : parser) groups = defaultdict(lambda : parser)
for group, desc in self.groups.items(): for group, desc in self.groups.items():
groups[group] = parser.add_option_group(group.upper(), desc) groups[group] = parser.add_option_group(group.upper(), desc)
for pref in self.preferences: for pref in self.preferences:
if not pref.switches: if not pref.switches:
continue continue
@ -299,16 +299,16 @@ class OptionSet(object):
action=action, action=action,
) )
g.add_option(*pref.switches, **args) g.add_option(*pref.switches, **args)
return parser return parser
def get_override_section(self, src): def get_override_section(self, src):
match = self.OVERRIDE_PAT.search(src) match = self.OVERRIDE_PAT.search(src)
if match: if match:
return match.group() return match.group()
return '' return ''
def parse_string(self, src): def parse_string(self, src):
options = {'cPickle':cPickle} options = {'cPickle':cPickle}
if not isinstance(src, unicode): if not isinstance(src, unicode):
@ -327,9 +327,9 @@ class OptionSet(object):
if callable(formatter): if callable(formatter):
val = formatter(val) val = formatter(val)
setattr(opts, pref.name, val) setattr(opts, pref.name, val)
return opts return opts
def render_group(self, name, desc, opts): def render_group(self, name, desc, opts):
prefs = [pref for pref in self.preferences if pref.group == name] prefs = [pref for pref in self.preferences if pref.group == name]
lines = ['### Begin group: %s'%(name if name else 'DEFAULT')] lines = ['### Begin group: %s'%(name if name else 'DEFAULT')]
@ -340,11 +340,11 @@ class OptionSet(object):
lines.append('# '+pref.name.replace('_', ' ')) lines.append('# '+pref.name.replace('_', ' '))
if pref.help: if pref.help:
lines += map(lambda x: '# ' + x, pref.help.split('\n')) lines += map(lambda x: '# ' + x, pref.help.split('\n'))
lines.append('%s = %s'%(pref.name, lines.append('%s = %s'%(pref.name,
self.serialize_opt(getattr(opts, pref.name, pref.default)))) self.serialize_opt(getattr(opts, pref.name, pref.default))))
lines.append(' ') lines.append(' ')
return '\n'.join(lines) return '\n'.join(lines)
def serialize_opt(self, val): def serialize_opt(self, val):
if val is val is True or val is False or val is None or \ if val is val is True or val is False or val is None or \
isinstance(val, (int, float, long, basestring)): isinstance(val, (int, float, long, basestring)):
@ -353,7 +353,7 @@ class OptionSet(object):
return repr(unicode(val)) return repr(unicode(val))
pickle = cPickle.dumps(val, -1) pickle = cPickle.dumps(val, -1)
return 'cPickle.loads(%s)'%repr(pickle) return 'cPickle.loads(%s)'%repr(pickle)
def serialize(self, opts): def serialize(self, opts):
src = '# %s\n\n'%(self.description.replace('\n', '\n# ')) src = '# %s\n\n'%(self.description.replace('\n', '\n# '))
groups = [self.render_group(name, self.groups.get(name, ''), opts) \ groups = [self.render_group(name, self.groups.get(name, ''), opts) \
@ -361,34 +361,34 @@ class OptionSet(object):
return src + '\n\n'.join(groups) return src + '\n\n'.join(groups)
class ConfigInterface(object): class ConfigInterface(object):
def __init__(self, description): def __init__(self, description):
self.option_set = OptionSet(description=description) self.option_set = OptionSet(description=description)
self.add_opt = self.option_set.add_opt self.add_opt = self.option_set.add_opt
self.add_group = self.option_set.add_group self.add_group = self.option_set.add_group
self.remove_opt = self.remove = self.option_set.remove_opt self.remove_opt = self.remove = self.option_set.remove_opt
self.parse_string = self.option_set.parse_string self.parse_string = self.option_set.parse_string
def update(self, other): def update(self, other):
self.option_set.update(other.option_set) self.option_set.update(other.option_set)
def option_parser(self, usage='', gui_mode=False): def option_parser(self, usage='', gui_mode=False):
return self.option_set.option_parser(user_defaults=self.parse(), return self.option_set.option_parser(user_defaults=self.parse(),
usage=usage, gui_mode=gui_mode) usage=usage, gui_mode=gui_mode)
def smart_update(self, opts1, opts2): def smart_update(self, opts1, opts2):
self.option_set.smart_update(opts1, opts2) self.option_set.smart_update(opts1, opts2)
class Config(ConfigInterface): class Config(ConfigInterface):
''' '''
A file based configuration. A file based configuration.
''' '''
def __init__(self, basename, description=''): def __init__(self, basename, description=''):
ConfigInterface.__init__(self, description) ConfigInterface.__init__(self, description)
self.config_file_path = os.path.join(config_dir, basename+'.py') self.config_file_path = os.path.join(config_dir, basename+'.py')
def parse(self): def parse(self):
src = '' src = ''
if os.path.exists(self.config_file_path): if os.path.exists(self.config_file_path):
@ -398,7 +398,7 @@ class Config(ConfigInterface):
except LockError: except LockError:
raise IOError('Could not lock config file: %s'%self.config_file_path) raise IOError('Could not lock config file: %s'%self.config_file_path)
return self.option_set.parse_string(src) return self.option_set.parse_string(src)
def as_string(self): def as_string(self):
if not os.path.exists(self.config_file_path): if not os.path.exists(self.config_file_path):
return '' return ''
@ -407,7 +407,7 @@ class Config(ConfigInterface):
return f.read().decode('utf-8') return f.read().decode('utf-8')
except LockError: except LockError:
raise IOError('Could not lock config file: %s'%self.config_file_path) raise IOError('Could not lock config file: %s'%self.config_file_path)
def set(self, name, val): def set(self, name, val):
if not self.option_set.has_option(name): if not self.option_set.has_option(name):
raise ValueError('The option %s is not defined.'%name) raise ValueError('The option %s is not defined.'%name)
@ -427,19 +427,19 @@ class Config(ConfigInterface):
f.write(src) f.write(src)
except LockError: except LockError:
raise IOError('Could not lock config file: %s'%self.config_file_path) raise IOError('Could not lock config file: %s'%self.config_file_path)
class StringConfig(ConfigInterface): class StringConfig(ConfigInterface):
''' '''
A string based configuration A string based configuration
''' '''
def __init__(self, src, description=''): def __init__(self, src, description=''):
ConfigInterface.__init__(self, description) ConfigInterface.__init__(self, description)
self.src = src self.src = src
def parse(self): def parse(self):
return self.option_set.parse_string(self.src) return self.option_set.parse_string(self.src)
def set(self, name, val): def set(self, name, val):
if not self.option_set.has_option(name): if not self.option_set.has_option(name):
raise ValueError('The option %s is not defined.'%name) raise ValueError('The option %s is not defined.'%name)
@ -452,30 +452,30 @@ class ConfigProxy(object):
''' '''
A Proxy to minimize file reads for widely used config settings A Proxy to minimize file reads for widely used config settings
''' '''
def __init__(self, config): def __init__(self, config):
self.__config = config self.__config = config
self.__opts = None self.__opts = None
def refresh(self): def refresh(self):
self.__opts = self.__config.parse() self.__opts = self.__config.parse()
def __getitem__(self, key): def __getitem__(self, key):
return self.get(key) return self.get(key)
def __setitem__(self, key, val): def __setitem__(self, key, val):
return self.set(key, val) return self.set(key, val)
def get(self, key): def get(self, key):
if self.__opts is None: if self.__opts is None:
self.refresh() self.refresh()
return getattr(self.__opts, key) return getattr(self.__opts, key)
def set(self, key, val): def set(self, key, val):
if self.__opts is None: if self.__opts is None:
self.refresh() self.refresh()
setattr(self.__opts, key, val) setattr(self.__opts, key, val)
return self.__config.set(key, val) return self.__config.set(key, val)
class DynamicConfig(dict): class DynamicConfig(dict):
''' '''
@ -489,7 +489,7 @@ class DynamicConfig(dict):
self.name = name self.name = name
self.file_path = os.path.join(config_dir, name+'.pickle') self.file_path = os.path.join(config_dir, name+'.pickle')
self.refresh() self.refresh()
def refresh(self): def refresh(self):
d = {} d = {}
if os.path.exists(self.file_path): if os.path.exists(self.file_path):
@ -503,20 +503,20 @@ class DynamicConfig(dict):
d = {} d = {}
self.clear() self.clear()
self.update(d) self.update(d)
def __getitem__(self, key): def __getitem__(self, key):
try: try:
return dict.__getitem__(self, key) return dict.__getitem__(self, key)
except KeyError: except KeyError:
return None return None
def __setitem__(self, key, val): def __setitem__(self, key, val):
dict.__setitem__(self, key, val) dict.__setitem__(self, key, val)
self.commit() self.commit()
def set(self, key, val): def set(self, key, val):
self.__setitem__(key, val) self.__setitem__(key, val)
def commit(self): def commit(self):
if hasattr(self, 'file_path') and self.file_path: if hasattr(self, 'file_path') and self.file_path:
if not os.path.exists(self.file_path): if not os.path.exists(self.file_path):
@ -526,17 +526,17 @@ class DynamicConfig(dict):
f.seek(0) f.seek(0)
f.truncate() f.truncate()
f.write(raw) f.write(raw)
dynamic = DynamicConfig() dynamic = DynamicConfig()
def _prefs(): def _prefs():
c = Config('global', 'calibre wide preferences') c = Config('global', 'calibre wide preferences')
c.add_opt('database_path', c.add_opt('database_path',
default=os.path.expanduser('~/library1.db'), default=os.path.expanduser('~/library1.db'),
help=_('Path to the database in which books are stored')) help=_('Path to the database in which books are stored'))
c.add_opt('filename_pattern', default=ur'(?P<title>.+) - (?P<author>[^_]+)', c.add_opt('filename_pattern', default=ur'(?P<title>.+) - (?P<author>[^_]+)',
help=_('Pattern to guess metadata from filenames')) help=_('Pattern to guess metadata from filenames'))
c.add_opt('isbndb_com_key', default='', c.add_opt('isbndb_com_key', default='',
help=_('Access key for isbndb.com')) help=_('Access key for isbndb.com'))
c.add_opt('network_timeout', default=5, c.add_opt('network_timeout', default=5,
help=_('Default timeout for network operations (seconds)')) help=_('Default timeout for network operations (seconds)'))
@ -544,13 +544,13 @@ def _prefs():
help=_('Path to directory in which your library of books is stored')) help=_('Path to directory in which your library of books is stored'))
c.add_opt('language', default=None, c.add_opt('language', default=None,
help=_('The language in which to display the user interface')) help=_('The language in which to display the user interface'))
c.add_opt('output_format', default='EPUB', c.add_opt('output_format', default='EPUB',
help=_('The default output format for ebook conversions.')) help=_('The default output format for ebook conversions.'))
c.add_opt('read_file_metadata', default=True, c.add_opt('read_file_metadata', default=True,
help=_('Read metadata from files')) help=_('Read metadata from files'))
c.add_opt('worker_process_priority', default='normal', c.add_opt('worker_process_priority', default='normal',
help=_('The priority of worker processes')) help=_('The priority of worker processes'))
c.add_opt('migrated', default=False, help='For Internal use. Don\'t modify.') c.add_opt('migrated', default=False, help='For Internal use. Don\'t modify.')
return c return c
@ -565,11 +565,11 @@ def migrate():
from PyQt4.QtCore import QSettings, QVariant from PyQt4.QtCore import QSettings, QVariant
class Settings(QSettings): class Settings(QSettings):
def __init__(self, name='calibre2'): def __init__(self, name='calibre2'):
QSettings.__init__(self, QSettings.IniFormat, QSettings.UserScope, QSettings.__init__(self, QSettings.IniFormat, QSettings.UserScope,
'kovidgoyal.net', name) 'kovidgoyal.net', name)
def get(self, key, default=None): def get(self, key, default=None):
try: try:
key = str(key) key = str(key)
@ -581,7 +581,7 @@ def migrate():
return cPickle.loads(val) return cPickle.loads(val)
except: except:
return default return default
s, migrated = Settings(), set([]) s, migrated = Settings(), set([])
all_keys = set(map(unicode, s.allKeys())) all_keys = set(map(unicode, s.allKeys()))
from calibre.gui2 import config, dynamic from calibre.gui2 import config, dynamic
@ -599,13 +599,13 @@ def migrate():
pass pass
finally: finally:
migrated.add(key) migrated.add(key)
_migrate('database path', p=prefs) _migrate('database path', p=prefs)
_migrate('filename pattern', p=prefs) _migrate('filename pattern', p=prefs)
_migrate('network timeout', p=prefs) _migrate('network timeout', p=prefs)
_migrate('isbndb.com key', p=prefs) _migrate('isbndb.com key', p=prefs)
_migrate('frequently used directories') _migrate('frequently used directories')
_migrate('send to device by default') _migrate('send to device by default')
_migrate('save to disk single format') _migrate('save to disk single format')
@ -616,33 +616,33 @@ def migrate():
_migrate('cover flow queue length') _migrate('cover flow queue length')
_migrate('LRF conversion defaults') _migrate('LRF conversion defaults')
_migrate('LRF ebook viewer options') _migrate('LRF ebook viewer options')
for key in all_keys - migrated: for key in all_keys - migrated:
if key.endswith(': un') or key.endswith(': pw'): if key.endswith(': un') or key.endswith(': pw'):
_migrate(key, p=dynamic) _migrate(key, p=dynamic)
p.set('migrated', True) p.set('migrated', True)
if __name__ == '__main__': if __name__ == '__main__':
import subprocess import subprocess
from PyQt4.Qt import QByteArray from PyQt4.Qt import QByteArray
c = Config('test', 'test config') c = Config('test', 'test config')
c.add_opt('one', ['-1', '--one'], help="This is option #1") c.add_opt('one', ['-1', '--one'], help="This is option #1")
c.set('one', u'345') c.set('one', u'345')
c.add_opt('two', help="This is option #2") c.add_opt('two', help="This is option #2")
c.set('two', 345) c.set('two', 345)
c.add_opt('three', help="This is option #3") c.add_opt('three', help="This is option #3")
c.set('three', QString(u'aflatoon')) c.set('three', QString(u'aflatoon'))
c.add_opt('four', help="This is option #4") c.add_opt('four', help="This is option #4")
c.set('four', QByteArray('binary aflatoon')) c.set('four', QByteArray('binary aflatoon'))
subprocess.call(['pygmentize', os.path.expanduser('~/.config/calibre/test.py')]) subprocess.call(['pygmentize', os.path.expanduser('~/.config/calibre/test.py')])
opts = c.parse() opts = c.parse()
for i in ('one', 'two', 'three', 'four'): for i in ('one', 'two', 'three', 'four'):
print i, repr(getattr(opts, i)) print i, repr(getattr(opts, i))