Fix #2204 ("Delete news when sent" does not work)

This commit is contained in:
Kovid Goyal 2009-04-07 11:57:47 -07:00
parent 5254aec93e
commit c4f554dc0e
3 changed files with 53 additions and 51 deletions

View File

@ -4,14 +4,13 @@ __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
""" """
Provides abstraction for metadata reading.writing from a variety of ebook formats. Provides abstraction for metadata reading.writing from a variety of ebook formats.
""" """
import os, mimetypes, sys import os, mimetypes, sys
from urllib import unquote, quote from urllib import unquote, quote
from urlparse import urlparse from urlparse import urlparse
from calibre.constants import __version__ as VERSION
from calibre import relpath from calibre import relpath
from calibre.utils.config import OptionParser from calibre.utils.config import OptionParser
@ -51,17 +50,17 @@ def get_parser(extension):
class Resource(object): class Resource(object):
''' '''
Represents a resource (usually a file on the filesystem or a URL pointing Represents a resource (usually a file on the filesystem or a URL pointing
to the web. Such resources are commonly referred to in OPF files. to the web. Such resources are commonly referred to in OPF files.
They have the interface: They have the interface:
:member:`path` :member:`path`
:member:`mime_type` :member:`mime_type`
:method:`href` :method:`href`
''' '''
def __init__(self, href_or_path, basedir=os.getcwd(), is_path=True): def __init__(self, href_or_path, basedir=os.getcwd(), is_path=True):
self._href = None self._href = None
self._basedir = basedir self._basedir = basedir
@ -91,13 +90,13 @@ class Resource(object):
pc = unquote(pc).decode('utf-8') pc = unquote(pc).decode('utf-8')
self.path = os.path.abspath(os.path.join(basedir, pc.replace('/', os.sep))) self.path = os.path.abspath(os.path.join(basedir, pc.replace('/', os.sep)))
self.fragment = unquote(url[-1]) self.fragment = unquote(url[-1])
def href(self, basedir=None): def href(self, basedir=None):
''' '''
Return a URL pointing to this resource. If it is a file on the filesystem Return a URL pointing to this resource. If it is a file on the filesystem
the URL is relative to `basedir`. the URL is relative to `basedir`.
`basedir`: If None, the basedir of this resource is used (see :method:`set_basedir`). `basedir`: If None, the basedir of this resource is used (see :method:`set_basedir`).
If this resource has no basedir, then the current working directory is used as the basedir. If this resource has no basedir, then the current working directory is used as the basedir.
''' '''
@ -119,54 +118,54 @@ class Resource(object):
if isinstance(rpath, unicode): if isinstance(rpath, unicode):
rpath = rpath.encode('utf-8') rpath = rpath.encode('utf-8')
return quote(rpath.replace(os.sep, '/'))+frag return quote(rpath.replace(os.sep, '/'))+frag
def set_basedir(self, path): def set_basedir(self, path):
self._basedir = path self._basedir = path
def basedir(self): def basedir(self):
return self._basedir return self._basedir
def __repr__(self): def __repr__(self):
return 'Resource(%s, %s)'%(repr(self.path), repr(self.href())) return 'Resource(%s, %s)'%(repr(self.path), repr(self.href()))
class ResourceCollection(object): class ResourceCollection(object):
def __init__(self): def __init__(self):
self._resources = [] self._resources = []
def __iter__(self): def __iter__(self):
for r in self._resources: for r in self._resources:
yield r yield r
def __len__(self): def __len__(self):
return len(self._resources) return len(self._resources)
def __getitem__(self, index): def __getitem__(self, index):
return self._resources[index] return self._resources[index]
def __bool__(self): def __bool__(self):
return len(self._resources) > 0 return len(self._resources) > 0
def __str__(self): def __str__(self):
resources = map(repr, self) resources = map(repr, self)
return '[%s]'%', '.join(resources) return '[%s]'%', '.join(resources)
def __repr__(self): def __repr__(self):
return str(self) return str(self)
def append(self, resource): def append(self, resource):
if not isinstance(resource, Resource): if not isinstance(resource, Resource):
raise ValueError('Can only append objects of type Resource') raise ValueError('Can only append objects of type Resource')
self._resources.append(resource) self._resources.append(resource)
def remove(self, resource): def remove(self, resource):
self._resources.remove(resource) self._resources.remove(resource)
def replace(self, start, end, items): def replace(self, start, end, items):
'Same as list[start:end] = items' 'Same as list[start:end] = items'
self._resources[start:end] = items self._resources[start:end] = items
@staticmethod @staticmethod
def from_directory_contents(top, topdown=True): def from_directory_contents(top, topdown=True):
collection = ResourceCollection() collection = ResourceCollection()
@ -176,28 +175,28 @@ class ResourceCollection(object):
res.set_basedir(top) res.set_basedir(top)
collection.append(res) collection.append(res)
return collection return collection
def set_basedir(self, path): def set_basedir(self, path):
for res in self: for res in self:
res.set_basedir(path) res.set_basedir(path)
class MetaInformation(object): class MetaInformation(object):
'''Convenient encapsulation of book metadata''' '''Convenient encapsulation of book metadata'''
@staticmethod @staticmethod
def copy(mi): def copy(mi):
ans = MetaInformation(mi.title, mi.authors) ans = MetaInformation(mi.title, mi.authors)
for attr in ('author_sort', 'title_sort', 'comments', 'category', for attr in ('author_sort', 'title_sort', 'comments', 'category',
'publisher', 'series', 'series_index', 'rating', 'publisher', 'series', 'series_index', 'rating',
'isbn', 'tags', 'cover_data', 'application_id', 'guide', 'isbn', 'tags', 'cover_data', 'application_id', 'guide',
'manifest', 'spine', 'toc', 'cover', 'language', 'manifest', 'spine', 'toc', 'cover', 'language',
'book_producer', 'timestamp'): 'book_producer', 'timestamp'):
if hasattr(mi, attr): if hasattr(mi, attr):
setattr(ans, attr, getattr(mi, attr)) setattr(ans, attr, getattr(mi, attr))
def __init__(self, title, authors=[_('Unknown')]): def __init__(self, title, authors=(_('Unknown'),)):
''' '''
@param title: title or "Unknown" or a MetaInformation object @param title: title or "Unknown" or a MetaInformation object
@param authors: List of strings or [] @param authors: List of strings or []
@ -208,20 +207,20 @@ class MetaInformation(object):
title = mi.title title = mi.title
authors = mi.authors authors = mi.authors
self.title = title self.title = title
self.author = authors # Needed for backward compatibility self.author = list(authors) # Needed for backward compatibility
#: List of strings or [] #: List of strings or []
self.authors = authors self.authors = list(authors)
self.tags = getattr(mi, 'tags', []) self.tags = getattr(mi, 'tags', [])
#: mi.cover_data = (ext, data) #: mi.cover_data = (ext, data)
self.cover_data = getattr(mi, 'cover_data', (None, None)) self.cover_data = getattr(mi, 'cover_data', (None, None))
for x in ('author_sort', 'title_sort', 'comments', 'category', 'publisher', for x in ('author_sort', 'title_sort', 'comments', 'category', 'publisher',
'series', 'series_index', 'rating', 'isbn', 'language', 'series', 'series_index', 'rating', 'isbn', 'language',
'application_id', 'manifest', 'toc', 'spine', 'guide', 'cover', 'application_id', 'manifest', 'toc', 'spine', 'guide', 'cover',
'book_producer', 'timestamp' 'book_producer', 'timestamp'
): ):
setattr(self, x, getattr(mi, x, None)) setattr(self, x, getattr(mi, x, None))
def smart_update(self, mi): def smart_update(self, mi):
''' '''
Merge the information in C{mi} into self. In case of conflicts, the information Merge the information in C{mi} into self. In case of conflicts, the information
@ -229,26 +228,26 @@ class MetaInformation(object):
''' '''
if mi.title and mi.title != _('Unknown'): if mi.title and mi.title != _('Unknown'):
self.title = mi.title self.title = mi.title
if mi.authors and mi.authors[0] != _('Unknown'): if mi.authors and mi.authors[0] != _('Unknown'):
self.authors = mi.authors self.authors = mi.authors
for attr in ('author_sort', 'title_sort', 'category', for attr in ('author_sort', 'title_sort', 'category',
'publisher', 'series', 'series_index', 'rating', 'publisher', 'series', 'series_index', 'rating',
'isbn', 'application_id', 'manifest', 'spine', 'toc', 'isbn', 'application_id', 'manifest', 'spine', 'toc',
'cover', 'language', 'guide', 'book_producer', 'cover', 'language', 'guide', 'book_producer',
'timestamp'): 'timestamp'):
if hasattr(mi, attr): if hasattr(mi, attr):
val = getattr(mi, attr) val = getattr(mi, attr)
if val is not None: if val is not None:
setattr(self, attr, val) setattr(self, attr, val)
self.tags += mi.tags self.tags += mi.tags
self.tags = list(set(self.tags)) self.tags = list(set(self.tags))
if getattr(mi, 'cover_data', None) and mi.cover_data[0] is not None: if getattr(mi, 'cover_data', None) and mi.cover_data[0] is not None:
self.cover_data = mi.cover_data self.cover_data = mi.cover_data
my_comments = getattr(self, 'comments', '') my_comments = getattr(self, 'comments', '')
other_comments = getattr(mi, 'comments', '') other_comments = getattr(mi, 'comments', '')
if not my_comments: if not my_comments:
@ -257,14 +256,14 @@ class MetaInformation(object):
other_comments = '' other_comments = ''
if len(other_comments.strip()) > len(my_comments.strip()): if len(other_comments.strip()) > len(my_comments.strip()):
self.comments = other_comments self.comments = other_comments
def format_series_index(self): def format_series_index(self):
try: try:
x = float(self.series_index) x = float(self.series_index)
except ValueError: except ValueError:
x = 1.0 x = 1.0
return '%d'%x if int(x) == x else '%.2f'%x return '%d'%x if int(x) == x else '%.2f'%x
def __unicode__(self): def __unicode__(self):
ans = u'' ans = u''
ans += u'Title : ' + unicode(self.title) + u'\n' ans += u'Title : ' + unicode(self.title) + u'\n'
@ -275,7 +274,7 @@ class MetaInformation(object):
ans += u'Publisher: '+ unicode(self.publisher) + u'\n' ans += u'Publisher: '+ unicode(self.publisher) + u'\n'
if getattr(self, 'book_producer', False): if getattr(self, 'book_producer', False):
ans += u'Producer : '+ unicode(self.book_producer) + u'\n' ans += u'Producer : '+ unicode(self.book_producer) + u'\n'
if self.category: if self.category:
ans += u'Category : ' + unicode(self.category) + u'\n' ans += u'Category : ' + unicode(self.category) + u'\n'
if self.comments: if self.comments:
ans += u'Comments : ' + unicode(self.comments) + u'\n' ans += u'Comments : ' + unicode(self.comments) + u'\n'
@ -284,13 +283,13 @@ class MetaInformation(object):
if self.tags: if self.tags:
ans += u'Tags : ' + u', '.join([unicode(t) for t in self.tags]) + '\n' ans += u'Tags : ' + u', '.join([unicode(t) for t in self.tags]) + '\n'
if self.series: if self.series:
ans += u'Series : '+unicode(self.series) + ' #%s\n'%self.format_series_index() ans += u'Series : '+unicode(self.series) + ' #%s\n'%self.format_series_index()
if self.language: if self.language:
ans += u'Language : ' + unicode(self.language) + u'\n' ans += u'Language : ' + unicode(self.language) + u'\n'
if self.timestamp is not None: if self.timestamp is not None:
ans += u'Timestamp : ' + self.timestamp.isoformat(' ') ans += u'Timestamp : ' + self.timestamp.isoformat(' ')
return ans.strip() return ans.strip()
def to_html(self): def to_html(self):
ans = [(_('Title'), unicode(self.title))] ans = [(_('Title'), unicode(self.title))]
ans += [(_('Author(s)'), (authors_to_string(self.authors) if self.authors else _('Unknown')))] ans += [(_('Author(s)'), (authors_to_string(self.authors) if self.authors else _('Unknown')))]
@ -307,9 +306,9 @@ class MetaInformation(object):
for i, x in enumerate(ans): for i, x in enumerate(ans):
ans[i] = u'<tr><td><b>%s</b></td><td>%s</td></tr>'%x ans[i] = u'<tr><td><b>%s</b></td><td>%s</td></tr>'%x
return u'<table>%s</table>'%u'\n'.join(ans) return u'<table>%s</table>'%u'\n'.join(ans)
def __str__(self): def __str__(self):
return self.__unicode__().encode('utf-8') return self.__unicode__().encode('utf-8')
def __nonzero__(self): def __nonzero__(self):
return bool(self.title or self.author or self.comments or self.category) return bool(self.title or self.author or self.comments or self.category)

View File

@ -397,6 +397,9 @@ class ConfigDialog(QDialog, Ui_Dialog):
self.separate_cover_flow.setChecked(config['separate_cover_flow']) self.separate_cover_flow.setChecked(config['separate_cover_flow'])
self.setup_email_page() self.setup_email_page()
self.category_view.setCurrentIndex(self.category_view.model().index(0)) self.category_view.setCurrentIndex(self.category_view.model().index(0))
self.delete_news.setEnabled(bool(self.sync_news.isChecked()))
self.connect(self.sync_news, SIGNAL('toggled(bool)'),
self.delete_news.setEnabled)
def setup_email_page(self): def setup_email_page(self):
opts = smtp_prefs().parse() opts = smtp_prefs().parse()

View File

@ -371,7 +371,7 @@
<item> <item>
<widget class="QCheckBox" name="delete_news"> <widget class="QCheckBox" name="delete_news">
<property name="text"> <property name="text">
<string>&amp;Delete news from library when it is sent to reader</string> <string>&amp;Delete news from library when it is automatically sent to reader</string>
</property> </property>
</widget> </widget>
</item> </item>