Get rid of @dynamic_property

This commit is contained in:
Kovid Goyal 2019-05-15 20:39:48 +05:30
parent 846a1a5e9f
commit f51e63718c
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
43 changed files with 1269 additions and 1487 deletions

View File

@ -1,6 +1,6 @@
[flake8] [flake8]
max-line-length = 160 max-line-length = 160
builtins = _,dynamic_property,__,P,I,lopen,icu_lower,icu_upper,icu_title,ngettext,connect_lambda builtins = _,__,P,I,lopen,icu_lower,icu_upper,icu_title,ngettext,connect_lambda
ignore = E12,E203,E22,E231,E241,E401,E402,E731,W391,E722,E741,W504 ignore = E12,E203,E22,E231,E241,E401,E402,E731,W391,E722,E741,W504
[yapf] [yapf]

View File

@ -4,9 +4,8 @@ __copyright__ = '2008, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import sys, os, re, time, random, warnings import sys, os, re, time, random, warnings
from polyglot.builtins import (builtins, codepoint_to_chr, iteritems, from polyglot.builtins import (codepoint_to_chr, iteritems,
itervalues, unicode_type, range, filter, hasenv) itervalues, unicode_type, range, filter, hasenv)
builtins.__dict__['dynamic_property'] = lambda func: func(None)
from math import floor from math import floor
from functools import partial from functools import partial

View File

@ -1145,18 +1145,15 @@ class DB(object):
def vacuum(self): def vacuum(self):
self.execute('VACUUM') self.execute('VACUUM')
@dynamic_property @property
def user_version(self): def user_version(self):
doc = 'The user version of this database' '''The user version of this database'''
def fget(self):
return self.conn.get('pragma user_version;', all=False) return self.conn.get('pragma user_version;', all=False)
def fset(self, val): @user_version.setter
def user_version(self, val):
self.execute('pragma user_version=%d'%int(val)) self.execute('pragma user_version=%d'%int(val))
return property(doc=doc, fget=fget, fset=fset)
def initialize_database(self): def initialize_database(self):
metadata_sqlite = P('metadata_sqlite.sql', data=True, metadata_sqlite = P('metadata_sqlite.sql', data=True,
allow_user_override=False).decode('utf-8') allow_user_override=False).decode('utf-8')
@ -1252,12 +1249,10 @@ class DB(object):
def exists_at(cls, path): def exists_at(cls, path):
return path and os.path.exists(os.path.join(path, 'metadata.db')) return path and os.path.exists(os.path.join(path, 'metadata.db'))
@dynamic_property @property
def library_id(self): def library_id(self):
doc = ('The UUID for this library. As long as the user only operates' '''The UUID for this library. As long as the user only operates on libraries with calibre, it will be unique'''
' on libraries with calibre, it will be unique')
def fget(self):
if getattr(self, '_library_id_', None) is None: if getattr(self, '_library_id_', None) is None:
ans = self.conn.get('SELECT uuid FROM library_id', all=False) ans = self.conn.get('SELECT uuid FROM library_id', all=False)
if ans is None: if ans is None:
@ -1267,15 +1262,14 @@ class DB(object):
self._library_id_ = ans self._library_id_ = ans
return self._library_id_ return self._library_id_
def fset(self, val): @library_id.setter
def library_id(self, val):
self._library_id_ = unicode_type(val) self._library_id_ = unicode_type(val)
self.execute(''' self.execute('''
DELETE FROM library_id; DELETE FROM library_id;
INSERT INTO library_id (uuid) VALUES (?); INSERT INTO library_id (uuid) VALUES (?);
''', (self._library_id_,)) ''', (self._library_id_,))
return property(doc=doc, fget=fget, fset=fset)
def last_modified(self): def last_modified(self):
''' Return last modified time as a UTC datetime object ''' ''' Return last modified time as a UTC datetime object '''
return utcfromtimestamp(os.stat(self.dbpath).st_mtime) return utcfromtimestamp(os.stat(self.dbpath).st_mtime)

View File

@ -31,11 +31,9 @@ class FileFormatter(object):
self.name = file.name self.name = file.name
self.path = file.path self.path = file.path
@dynamic_property @property
def mode_string(self): def mode_string(self):
doc=""" The mode string for this file. There are only two modes read-only and read-write """ """ The mode string for this file. There are only two modes read-only and read-write """
def fget(self):
mode, x = "-", "-" mode, x = "-", "-"
if self.is_dir: if self.is_dir:
mode, x = "d", "x" mode, x = "d", "x"
@ -44,24 +42,18 @@ class FileFormatter(object):
else: else:
mode += "rw"+x+"rw"+x+"rw"+x mode += "rw"+x+"rw"+x+"rw"+x
return mode return mode
return property(doc=doc, fget=fget)
@dynamic_property @property
def isdir_name(self): def isdir_name(self):
doc='''Return self.name + '/' if self is a directory''' '''Return self.name + '/' if self is a directory'''
def fget(self):
name = self.name name = self.name
if self.is_dir: if self.is_dir:
name += '/' name += '/'
return name return name
return property(doc=doc, fget=fget)
@dynamic_property @property
def name_in_color(self): def name_in_color(self):
doc=""" The name in ANSI text. Directories are blue, ebooks are green """ """ The name in ANSI text. Directories are blue, ebooks are green """
def fget(self):
cname = self.name cname = self.name
blue, green, normal = "", "", "" blue, green, normal = "", "", ""
if self.term: if self.term:
@ -73,31 +65,21 @@ class FileFormatter(object):
if ext in (".pdf", ".rtf", ".lrf", ".lrx", ".txt"): if ext in (".pdf", ".rtf", ".lrf", ".lrx", ".txt"):
cname = green + self.name + normal cname = green + self.name + normal
return cname return cname
return property(doc=doc, fget=fget)
@dynamic_property @property
def human_readable_size(self): def human_readable_size(self):
doc=""" File size in human readable form """ """ File size in human readable form """
def fget(self):
return human_readable(self.size) return human_readable(self.size)
return property(doc=doc, fget=fget)
@dynamic_property @property
def modification_time(self): def modification_time(self):
doc=""" Last modified time in the Linux ls -l format """ """ Last modified time in the Linux ls -l format """
def fget(self):
return time.strftime("%Y-%m-%d %H:%M", time.localtime(self.wtime)) return time.strftime("%Y-%m-%d %H:%M", time.localtime(self.wtime))
return property(doc=doc, fget=fget)
@dynamic_property @property
def creation_time(self): def creation_time(self):
doc=""" Last modified time in the Linux ls -l format """ """ Last modified time in the Linux ls -l format """
def fget(self):
return time.strftime("%Y-%m-%d %H:%M", time.localtime(self.ctime)) return time.strftime("%Y-%m-%d %H:%M", time.localtime(self.ctime))
return property(doc=doc, fget=fget)
def info(dev): def info(dev):

View File

@ -46,26 +46,21 @@ class Book(Metadata):
# use lpath because the prefix can change, changing path # use lpath because the prefix can change, changing path
return self.lpath == getattr(other, 'lpath', None) return self.lpath == getattr(other, 'lpath', None)
@dynamic_property @property
def db_id(self): def db_id(self):
doc = '''The database id in the application database that this file corresponds to''' '''The database id in the application database that this file corresponds to'''
def fget(self):
match = re.search(r'_(\d+)$', self.lpath.rpartition('.')[0]) match = re.search(r'_(\d+)$', self.lpath.rpartition('.')[0])
if match: if match:
return int(match.group(1)) return int(match.group(1))
return None return None
return property(fget=fget, doc=doc)
@dynamic_property @property
def title_sorter(self): def title_sorter(self):
doc = '''String to sort the title. If absent, title is returned''' '''String to sort the title. If absent, title is returned'''
def fget(self):
return title_sort(self.title) return title_sort(self.title)
return property(doc=doc, fget=fget)
@dynamic_property @property
def thumbnail(self): def thumbnail(self):
return None return None

View File

@ -169,12 +169,12 @@ class Block(object):
def height(self): def height(self):
return int(ceil(sum(l if isinstance(l, numbers.Number) else l.boundingRect().height() for l in self.layouts))) return int(ceil(sum(l if isinstance(l, numbers.Number) else l.boundingRect().height() for l in self.layouts)))
@dynamic_property @property
def position(self): def position(self):
def fget(self):
return self._position return self._position
def fset(self, new_pos): @position.setter
def position(self, new_pos):
(x, y) = new_pos (x, y) = new_pos
self._position = Point(x, y) self._position = Point(x, y)
if self.layouts: if self.layouts:
@ -186,7 +186,6 @@ class Block(object):
else: else:
l.setPosition(QPointF(x, y)) l.setPosition(QPointF(x, y))
y += l.boundingRect().height() y += l.boundingRect().height()
return property(fget=fget, fset=fset)
def draw(self, painter): def draw(self, painter):
for l in self.layouts: for l in self.layouts:

View File

@ -209,37 +209,29 @@ class Tag(object):
s += " at %08X, contents: %s" % (self.offset, repr(self.contents)) s += " at %08X, contents: %s" % (self.offset, repr(self.contents))
return s return s
@dynamic_property @property
def byte(self): def byte(self):
def fget(self):
if len(self.contents) != 1: if len(self.contents) != 1:
raise LRFParseError("Bad parameter for tag ID: %04X" % self.id) raise LRFParseError("Bad parameter for tag ID: %04X" % self.id)
return struct.unpack("<B", self.contents)[0] return struct.unpack("<B", self.contents)[0]
return property(fget=fget)
@dynamic_property @property
def word(self): def word(self):
def fget(self):
if len(self.contents) != 2: if len(self.contents) != 2:
raise LRFParseError("Bad parameter for tag ID: %04X" % self.id) raise LRFParseError("Bad parameter for tag ID: %04X" % self.id)
return struct.unpack("<H", self.contents)[0] return struct.unpack("<H", self.contents)[0]
return property(fget=fget)
@dynamic_property @property
def sword(self): def sword(self):
def fget(self):
if len(self.contents) != 2: if len(self.contents) != 2:
raise LRFParseError("Bad parameter for tag ID: %04X" % self.id) raise LRFParseError("Bad parameter for tag ID: %04X" % self.id)
return struct.unpack("<h", self.contents)[0] return struct.unpack("<h", self.contents)[0]
return property(fget=fget)
@dynamic_property @property
def dword(self): def dword(self):
def fget(self):
if len(self.contents) != 4: if len(self.contents) != 4:
raise LRFParseError("Bad parameter for tag ID: %04X" % self.id) raise LRFParseError("Bad parameter for tag ID: %04X" % self.id)
return struct.unpack("<I", self.contents)[0] return struct.unpack("<I", self.contents)[0]
return property(fget=fget)
def dummy_parser(self, stream): def dummy_parser(self, stream):
raise LRFParseError("Unknown tag at %08X" % stream.tell()) raise LRFParseError("Unknown tag at %08X" % stream.tell())

View File

@ -193,14 +193,13 @@ class ManifestItem(Resource): # {{{
res.mime_type = mt res.mime_type = mt
return res return res
@dynamic_property @property
def media_type(self): def media_type(self):
def fget(self):
return self.mime_type return self.mime_type
def fset(self, val): @media_type.setter
def media_type(self, val):
self.mime_type = val self.mime_type = val
return property(fget=fget, fset=fset)
def __unicode__representation__(self): def __unicode__representation__(self):
return u'<item id="%s" href="%s" media-type="%s" />'%(self.id, self.href(), self.media_type) return u'<item id="%s" href="%s" media-type="%s" />'%(self.id, self.href(), self.media_type)
@ -804,17 +803,17 @@ class OPF(object): # {{{
for item in self.iterguide(): for item in self.iterguide():
item.set('href', get_href(item)) item.set('href', get_href(item))
@dynamic_property @property
def title(self): def title(self):
# TODO: Add support for EPUB 3 refinements # TODO: Add support for EPUB 3 refinements
def fget(self):
for elem in self.title_path(self.metadata): for elem in self.title_path(self.metadata):
title = self.get_text(elem) title = self.get_text(elem)
if title and title.strip(): if title and title.strip():
return re.sub(r'\s+', ' ', title.strip()) return re.sub(r'\s+', ' ', title.strip())
def fset(self, val): @title.setter
def title(self, val):
val = (val or '').strip() val = (val or '').strip()
titles = self.title_path(self.metadata) titles = self.title_path(self.metadata)
if self.package_version < 3: if self.package_version < 3:
@ -827,18 +826,15 @@ class OPF(object): # {{{
title = titles[0] if titles else self.create_metadata_element('title') title = titles[0] if titles else self.create_metadata_element('title')
title.text = re.sub(r'\s+', ' ', unicode_type(val)) title.text = re.sub(r'\s+', ' ', unicode_type(val))
return property(fget=fget, fset=fset) @property
@dynamic_property
def authors(self): def authors(self):
def fget(self):
ans = [] ans = []
for elem in self.authors_path(self.metadata): for elem in self.authors_path(self.metadata):
ans.extend(string_to_authors(self.get_text(elem))) ans.extend(string_to_authors(self.get_text(elem)))
return ans return ans
def fset(self, val): @authors.setter
def authors(self, val):
remove = list(self.authors_path(self.metadata)) remove = list(self.authors_path(self.metadata))
for elem in remove: for elem in remove:
elem.getparent().remove(elem) elem.getparent().remove(elem)
@ -853,12 +849,8 @@ class OPF(object): # {{{
elem.set('{%s}role'%self.NAMESPACES['opf'], 'aut') elem.set('{%s}role'%self.NAMESPACES['opf'], 'aut')
self.set_text(elem, author.strip()) self.set_text(elem, author.strip())
return property(fget=fget, fset=fset) @property
@dynamic_property
def author_sort(self): def author_sort(self):
def fget(self):
matches = self.authors_path(self.metadata) matches = self.authors_path(self.metadata)
if matches: if matches:
for match in matches: for match in matches:
@ -868,7 +860,8 @@ class OPF(object): # {{{
if ans: if ans:
return ans return ans
def fset(self, val): @author_sort.setter
def author_sort(self, val):
matches = self.authors_path(self.metadata) matches = self.authors_path(self.metadata)
if matches: if matches:
for key in matches[0].attrib: for key in matches[0].attrib:
@ -876,12 +869,8 @@ class OPF(object): # {{{
matches[0].attrib.pop(key) matches[0].attrib.pop(key)
matches[0].set('{%s}file-as'%self.NAMESPACES['opf'], unicode_type(val)) matches[0].set('{%s}file-as'%self.NAMESPACES['opf'], unicode_type(val))
return property(fget=fget, fset=fset) @property
@dynamic_property
def tags(self): def tags(self):
def fget(self):
ans = [] ans = []
for tag in self.tags_path(self.metadata): for tag in self.tags_path(self.metadata):
text = self.get_text(tag) text = self.get_text(tag)
@ -889,19 +878,16 @@ class OPF(object): # {{{
ans.extend([x.strip() for x in text.split(',')]) ans.extend([x.strip() for x in text.split(',')])
return ans return ans
def fset(self, val): @tags.setter
def tags(self, val):
for tag in list(self.tags_path(self.metadata)): for tag in list(self.tags_path(self.metadata)):
tag.getparent().remove(tag) tag.getparent().remove(tag)
for tag in val: for tag in val:
elem = self.create_metadata_element('subject') elem = self.create_metadata_element('subject')
self.set_text(elem, unicode_type(tag)) self.set_text(elem, unicode_type(tag))
return property(fget=fget, fset=fset) @property
@dynamic_property
def pubdate(self): def pubdate(self):
def fget(self):
ans = None ans = None
for match in self.pubdate_path(self.metadata): for match in self.pubdate_path(self.metadata):
try: try:
@ -913,7 +899,8 @@ class OPF(object): # {{{
ans = val ans = val
return ans return ans
def fset(self, val): @pubdate.setter
def pubdate(self, val):
least_val = least_elem = None least_val = least_elem = None
for match in self.pubdate_path(self.metadata): for match in self.pubdate_path(self.metadata):
try: try:
@ -934,16 +921,13 @@ class OPF(object): # {{{
least_elem.attrib.clear() least_elem.attrib.clear()
least_elem.text = isoformat(val) least_elem.text = isoformat(val)
return property(fget=fget, fset=fset) @property
@dynamic_property
def isbn(self): def isbn(self):
def fget(self):
for match in self.isbn_path(self.metadata): for match in self.isbn_path(self.metadata):
return self.get_text(match) or None return self.get_text(match) or None
def fset(self, val): @isbn.setter
def isbn(self, val):
uuid_id = None uuid_id = None
for attr in self.root.attrib: for attr in self.root.attrib:
if attr.endswith('unique-identifier'): if attr.endswith('unique-identifier'):
@ -969,8 +953,6 @@ class OPF(object): # {{{
attrib=attrib)] attrib=attrib)]
self.set_text(matches[0], unicode_type(val)) self.set_text(matches[0], unicode_type(val))
return property(fget=fget, fset=fset)
def get_identifiers(self): def get_identifiers(self):
identifiers = {} identifiers = {}
for x in self.XPath( for x in self.XPath(
@ -1024,14 +1006,13 @@ class OPF(object): # {{{
self.set_text(self.create_metadata_element( self.set_text(self.create_metadata_element(
'identifier', attrib=attrib), unicode_type(val)) 'identifier', attrib=attrib), unicode_type(val))
@dynamic_property @property
def application_id(self): def application_id(self):
def fget(self):
for match in self.application_id_path(self.metadata): for match in self.application_id_path(self.metadata):
return self.get_text(match) or None return self.get_text(match) or None
def fset(self, val): @application_id.setter
def application_id(self, val):
removed_ids = set() removed_ids = set()
for x in tuple(self.application_id_path(self.metadata)): for x in tuple(self.application_id_path(self.metadata)):
removed_ids.add(x.get('id', None)) removed_ids.add(x.get('id', None))
@ -1048,16 +1029,13 @@ class OPF(object): # {{{
self.set_text(self.create_metadata_element( self.set_text(self.create_metadata_element(
'identifier', attrib=attrib), unicode_type(val)) 'identifier', attrib=attrib), unicode_type(val))
return property(fget=fget, fset=fset) @property
@dynamic_property
def uuid(self): def uuid(self):
def fget(self):
for match in self.uuid_id_path(self.metadata): for match in self.uuid_id_path(self.metadata):
return self.get_text(match) or None return self.get_text(match) or None
def fset(self, val): @uuid.setter
def uuid(self, val):
matches = self.uuid_id_path(self.metadata) matches = self.uuid_id_path(self.metadata)
if not matches: if not matches:
attrib = {'{%s}scheme'%self.NAMESPACES['opf']: 'uuid'} attrib = {'{%s}scheme'%self.NAMESPACES['opf']: 'uuid'}
@ -1065,25 +1043,18 @@ class OPF(object): # {{{
attrib=attrib)] attrib=attrib)]
self.set_text(matches[0], unicode_type(val)) self.set_text(matches[0], unicode_type(val))
return property(fget=fget, fset=fset) @property
@dynamic_property
def language(self): def language(self):
def fget(self):
ans = self.languages ans = self.languages
if ans: if ans:
return ans[0] return ans[0]
def fset(self, val): @language.setter
def language(self, val):
self.languages = [val] self.languages = [val]
return property(fget=fget, fset=fset) @property
@dynamic_property
def languages(self): def languages(self):
def fget(self):
ans = [] ans = []
for match in self.languages_path(self.metadata): for match in self.languages_path(self.metadata):
t = self.get_text(match) t = self.get_text(match)
@ -1093,7 +1064,8 @@ class OPF(object): # {{{
ans.append(l) ans.append(l)
return ans return ans
def fset(self, val): @languages.setter
def languages(self, val):
matches = self.languages_path(self.metadata) matches = self.languages_path(self.metadata)
for x in matches: for x in matches:
x.getparent().remove(x) x.getparent().remove(x)
@ -1102,8 +1074,6 @@ class OPF(object): # {{{
l = self.create_metadata_element('language') l = self.create_metadata_element('language')
self.set_text(l, unicode_type(lang)) self.set_text(l, unicode_type(lang))
return property(fget=fget, fset=fset)
@property @property
def raw_languages(self): def raw_languages(self):
for match in self.languages_path(self.metadata): for match in self.languages_path(self.metadata):
@ -1111,20 +1081,18 @@ class OPF(object): # {{{
if t and t.strip(): if t and t.strip():
yield t.strip() yield t.strip()
@dynamic_property @property
def book_producer(self): def book_producer(self):
def fget(self):
for match in self.bkp_path(self.metadata): for match in self.bkp_path(self.metadata):
return self.get_text(match) or None return self.get_text(match) or None
def fset(self, val): @book_producer.setter
def book_producer(self, val):
matches = self.bkp_path(self.metadata) matches = self.bkp_path(self.metadata)
if not matches: if not matches:
matches = [self.create_metadata_element('contributor')] matches = [self.create_metadata_element('contributor')]
matches[0].set('{%s}role'%self.NAMESPACES['opf'], 'bkp') matches[0].set('{%s}role'%self.NAMESPACES['opf'], 'bkp')
self.set_text(matches[0], unicode_type(val)) self.set_text(matches[0], unicode_type(val))
return property(fget=fget, fset=fset)
def identifier_iter(self): def identifier_iter(self):
for item in self.identifier_path(self.metadata): for item in self.identifier_path(self.metadata):
@ -1238,10 +1206,8 @@ class OPF(object): # {{{
if path and os.path.exists(path): if path and os.path.exists(path):
return path return path
@dynamic_property @property
def cover(self): def cover(self):
def fget(self):
if self.guide is not None: if self.guide is not None:
for t in ('cover', 'other.ms-coverimage-standard', 'other.ms-coverimage'): for t in ('cover', 'other.ms-coverimage-standard', 'other.ms-coverimage'):
for item in self.guide: for item in self.guide:
@ -1253,7 +1219,8 @@ class OPF(object): # {{{
except: except:
pass pass
def fset(self, path): @cover.setter
def cover(self, path):
if self.guide is not None: if self.guide is not None:
self.guide.set_cover(path) self.guide.set_cover(path)
for item in list(self.iterguide()): for item in list(self.iterguide()):
@ -1273,8 +1240,6 @@ class OPF(object): # {{{
if item.type.lower() == t: if item.type.lower() == t:
self.create_manifest_item(item.href(), guess_type(path)[0]) self.create_manifest_item(item.href(), guess_type(path)[0])
return property(fget=fget, fset=fset)
def get_metadata_element(self, name): def get_metadata_element(self, name):
matches = self.metadata_elem_path(self.metadata, name=name) matches = self.metadata_elem_path(self.metadata, name=name)
if matches: if matches:

View File

@ -122,11 +122,10 @@ class TOC(list):
for i in obj.flat(): for i in obj.flat():
yield i yield i
@dynamic_property @property
def abspath(self): def abspath(self):
doc='Return the file this toc entry points to as a absolute path to a file on the system.' 'Return the file this toc entry points to as a absolute path to a file on the system.'
def fget(self):
if self.href is None: if self.href is None:
return None return None
path = self.href.replace('/', os.sep) path = self.href.replace('/', os.sep)
@ -134,8 +133,6 @@ class TOC(list):
path = os.path.join(self.base_path, path) path = os.path.join(self.base_path, path)
return path return path
return property(fget=fget, doc=doc)
def read_from_opf(self, opfreader): def read_from_opf(self, opfreader):
toc = opfreader.soup.find('spine', toc=True) toc = opfreader.soup.find('spine', toc=True)
if toc is not None: if toc is not None:

View File

@ -131,14 +131,13 @@ class IndexEntry(object):
' parent_index=%r)')%(self.offset, self.depth, self.length, ' parent_index=%r)')%(self.offset, self.depth, self.length,
self.index, self.parent_index) self.index, self.parent_index)
@dynamic_property @property
def size(self): def size(self):
def fget(self):
return self.length return self.length
def fset(self, val): @size.setter
def size(self, val):
self.length = val self.length = val
return property(fget=fget, fset=fset, doc='Alias for length')
@property @property
def next_offset(self): def next_offset(self):

View File

@ -704,20 +704,17 @@ class Metadata(object):
if attr != nsattr: if attr != nsattr:
attrib[nsattr] = attrib.pop(attr) attrib[nsattr] = attrib.pop(attr)
@dynamic_property @property
def name(self): def name(self):
def fget(self):
return self.term return self.term
return property(fget=fget)
@dynamic_property @property
def content(self): def content(self):
def fget(self):
return self.value return self.value
def fset(self, value): @content.setter
def content(self, value):
self.value = value self.value = value
return property(fget=fget, fset=fset)
scheme = Attribute(lambda term: 'scheme' if scheme = Attribute(lambda term: 'scheme' if
term == OPF('meta') else OPF('scheme'), term == OPF('meta') else OPF('scheme'),
@ -830,33 +827,27 @@ class Metadata(object):
def __getattr__(self, term): def __getattr__(self, term):
return self.items[term] return self.items[term]
@dynamic_property @property
def _nsmap(self): def _nsmap(self):
def fget(self):
nsmap = {} nsmap = {}
for term in self.items: for term in self.items:
for item in self.items[term]: for item in self.items[term]:
nsmap.update(item.nsmap) nsmap.update(item.nsmap)
return nsmap return nsmap
return property(fget=fget)
@dynamic_property @property
def _opf1_nsmap(self): def _opf1_nsmap(self):
def fget(self):
nsmap = self._nsmap nsmap = self._nsmap
for key, value in nsmap.items(): for key, value in nsmap.items():
if value in OPF_NSES or value in DC_NSES: if value in OPF_NSES or value in DC_NSES:
del nsmap[key] del nsmap[key]
return nsmap return nsmap
return property(fget=fget)
@dynamic_property @property
def _opf2_nsmap(self): def _opf2_nsmap(self):
def fget(self):
nsmap = self._nsmap nsmap = self._nsmap
nsmap.update(OPF2_NSMAP) nsmap.update(OPF2_NSMAP)
return nsmap return nsmap
return property(fget=fget)
def to_opf1(self, parent=None): def to_opf1(self, parent=None):
nsmap = self._opf1_nsmap nsmap = self._opf1_nsmap
@ -1011,9 +1002,9 @@ class Manifest(object):
# }}} # }}}
@dynamic_property @property
def data(self): def data(self):
doc = """Provides MIME type sensitive access to the manifest """Provides MIME type sensitive access to the manifest
entry's associated content. entry's associated content.
- XHTML, HTML, and variant content is parsed as necessary to - XHTML, HTML, and variant content is parsed as necessary to
@ -1025,8 +1016,6 @@ class Manifest(object):
- All other content is returned as a :class:`str` object with no - All other content is returned as a :class:`str` object with no
special parsing. special parsing.
""" """
def fget(self):
data = self._data data = self._data
if data is None: if data is None:
if self._loader is None: if self._loader is None:
@ -1053,12 +1042,13 @@ class Manifest(object):
self._data = data self._data = data
return data return data
def fset(self, value): @data.setter
def data(self, value):
self._data = value self._data = value
def fdel(self): @data.deleter
def data(self):
self._data = None self._data = None
return property(fget, fset, fdel, doc=doc)
def unload_data_from_memory(self, memory=None): def unload_data_from_memory(self, memory=None):
if isinstance(self._data, bytes): if isinstance(self._data, bytes):
@ -1266,9 +1256,8 @@ class Manifest(object):
element(elem, OPF('item'), attrib=attrib) element(elem, OPF('item'), attrib=attrib)
return elem return elem
@dynamic_property @property
def main_stylesheet(self): def main_stylesheet(self):
def fget(self):
ans = getattr(self, '_main_stylesheet', None) ans = getattr(self, '_main_stylesheet', None)
if ans is None: if ans is None:
for item in self: for item in self:
@ -1277,9 +1266,9 @@ class Manifest(object):
break break
return ans return ans
def fset(self, item): @main_stylesheet.setter
def main_stylesheet(self, item):
self._main_stylesheet = item self._main_stylesheet = item
return property(fget=fget, fset=fset)
class Spine(object): class Spine(object):
@ -1422,15 +1411,12 @@ class Guide(object):
return 'Reference(type=%r, title=%r, href=%r)' \ return 'Reference(type=%r, title=%r, href=%r)' \
% (self.type, self.title, self.href) % (self.type, self.title, self.href)
@dynamic_property @property
def item(self): def item(self):
doc = """The manifest item associated with this reference.""" """The manifest item associated with this reference."""
def fget(self):
path = urldefrag(self.href)[0] path = urldefrag(self.href)[0]
hrefs = self.oeb.manifest.hrefs hrefs = self.oeb.manifest.hrefs
return hrefs.get(path, None) return hrefs.get(path, None)
return property(fget=fget, doc=doc)
def __init__(self, oeb): def __init__(self, oeb):
self.oeb = oeb self.oeb = oeb

View File

@ -1369,14 +1369,13 @@ class EpubContainer(Container):
with self.open(name, 'wb') as f: with self.open(name, 'wb') as f:
f.write(data) f.write(data)
@dynamic_property @property
def path_to_ebook(self): def path_to_ebook(self):
def fget(self):
return self.pathtoepub return self.pathtoepub
def fset(self, val): @path_to_ebook.setter
def path_to_ebook(self, val):
self.pathtoepub = val self.pathtoepub = val
return property(fget=fget, fset=fset)
# }}} # }}}
@ -1496,14 +1495,13 @@ class AZW3Container(Container):
outpath = self.pathtoazw3 outpath = self.pathtoazw3
opf_to_azw3(self.name_path_map[self.opf_name], outpath, self) opf_to_azw3(self.name_path_map[self.opf_name], outpath, self)
@dynamic_property @property
def path_to_ebook(self): def path_to_ebook(self):
def fget(self):
return self.pathtoazw3 return self.pathtoazw3
def fset(self, val): @path_to_ebook.setter
def path_to_ebook(self, val):
self.pathtoazw3 = val self.pathtoazw3 = val
return property(fget=fget, fset=fset)
@property @property
def names_that_must_not_be_changed(self): def names_that_must_not_be_changed(self):

View File

@ -1022,19 +1022,19 @@ class Application(QApplication):
else: else:
return QApplication.event(self, e) return QApplication.event(self, e)
@dynamic_property @property
def current_custom_colors(self): def current_custom_colors(self):
from PyQt5.Qt import QColorDialog, QColor from PyQt5.Qt import QColorDialog
def fget(self):
return [col.getRgb() for col in return [col.getRgb() for col in
(QColorDialog.customColor(i) for i in range(QColorDialog.customCount()))] (QColorDialog.customColor(i) for i in range(QColorDialog.customCount()))]
def fset(self, colors): @current_custom_colors.setter
def current_custom_colors(self, colors):
from PyQt5.Qt import QColorDialog, QColor
num = min(len(colors), QColorDialog.customCount()) num = min(len(colors), QColorDialog.customCount())
for i in range(num): for i in range(num):
QColorDialog.setCustomColor(i, QColor(*colors[i])) QColorDialog.setCustomColor(i, QColor(*colors[i]))
return property(fget=fget, fset=fset)
def read_custom_colors(self): def read_custom_colors(self):
colors = self.color_prefs.get('custom_colors_for_color_dialog', None) colors = self.color_prefs.get('custom_colors_for_color_dialog', None)

View File

@ -51,18 +51,17 @@ class ChooseFormat(QDialog): # {{{
b.setChecked(True) b.setChecked(True)
self.accept() self.accept()
@dynamic_property @property
def formats(self): def formats(self):
def fget(self):
for b in self.buttons: for b in self.buttons:
if b.isChecked(): if b.isChecked():
yield unicode_type(b.text())[1:] yield unicode_type(b.text())[1:]
def fset(self, formats): @formats.setter
def formats(self, formats):
formats = {x.upper() for x in formats} formats = {x.upper() for x in formats}
for b in self.buttons: for b in self.buttons:
b.setChecked(b.text()[1:] in formats) b.setChecked(b.text()[1:] in formats)
return property(fget=fget, fset=fset)
# }}} # }}}

View File

@ -336,10 +336,8 @@ class EditorWidget(QWebView, LineEditECM): # {{{
def remove_format_cleanup(self): def remove_format_cleanup(self):
self.html = self.html self.html = self.html
@dynamic_property @property
def html(self): def html(self):
def fget(self):
ans = u'' ans = u''
try: try:
if not self.page().mainFrame().documentElement().findFirst('meta[name="calibre-dont-sanitize"]').isNull(): if not self.page().mainFrame().documentElement().findFirst('meta[name="calibre-dont-sanitize"]').isNull():
@ -378,13 +376,13 @@ class EditorWidget(QWebView, LineEditECM): # {{{
return ans return ans
def fset(self, val): @html.setter
def html(self, val):
if self.base_url is None: if self.base_url is None:
self.setHtml(val) self.setHtml(val)
else: else:
self.setHtml(val, self.base_url) self.setHtml(val, self.base_url)
self.set_font_style() self.set_font_style()
return property(fget=fget, fset=fset)
def set_base_url(self, qurl): def set_base_url(self, qurl):
self.base_url = qurl self.base_url = qurl
@ -763,15 +761,14 @@ class Editor(QWidget): # {{{
def set_minimum_height_for_editor(self, val): def set_minimum_height_for_editor(self, val):
self.editor.setMinimumHeight(val) self.editor.setMinimumHeight(val)
@dynamic_property @property
def html(self): def html(self):
def fset(self, v):
self.editor.html = v
def fget(self):
self.tabs.setCurrentIndex(0) self.tabs.setCurrentIndex(0)
return self.editor.html return self.editor.html
return property(fget=fget, fset=fset)
@html.setter
def html(self, v):
self.editor.html = v
def change_tab(self, index): def change_tab(self, index):
# print 'reloading:', (index and self.wyswyg_dirty) or (not index and # print 'reloading:', (index and self.wyswyg_dirty) or (not index and
@ -785,14 +782,13 @@ class Editor(QWidget): # {{{
self.editor.html = unicode_type(self.code_edit.toPlainText()) self.editor.html = unicode_type(self.code_edit.toPlainText())
self.source_dirty = False self.source_dirty = False
@dynamic_property @property
def tab(self): def tab(self):
def fget(self):
return 'code' if self.tabs.currentWidget() is self.code_edit else 'wyswyg' return 'code' if self.tabs.currentWidget() is self.code_edit else 'wyswyg'
def fset(self, val): @tab.setter
def tab(self, val):
self.tabs.setCurrentWidget(self.code_edit if val == 'code' else self.wyswyg) self.tabs.setCurrentWidget(self.code_edit if val == 'code' else self.wyswyg)
return property(fget=fget, fset=fset)
def wyswyg_dirtied(self, *args): def wyswyg_dirtied(self, *args):
self.wyswyg_dirty = True self.wyswyg_dirty = True
@ -816,14 +812,13 @@ class Editor(QWidget): # {{{
if self.toolbar_prefs_name is not None: if self.toolbar_prefs_name is not None:
gprefs.set(self.toolbar_prefs_name, visible) gprefs.set(self.toolbar_prefs_name, visible)
@dynamic_property @property
def toolbars_visible(self): def toolbars_visible(self):
def fget(self):
return self.toolbar1.isVisible() or self.toolbar2.isVisible() or self.toolbar3.isVisible() return self.toolbar1.isVisible() or self.toolbar2.isVisible() or self.toolbar3.isVisible()
def fset(self, val): @toolbars_visible.setter
def toolbars_visible(self, val):
getattr(self, ('show' if val else 'hide') + '_toolbars')() getattr(self, ('show' if val else 'hide') + '_toolbars')()
return property(fget=fget, fset=fset)
def set_readonly(self, what): def set_readonly(self, what):
self.editor.set_readonly(what) self.editor.set_readonly(what)

View File

@ -333,23 +333,21 @@ class LineEdit(QLineEdit, LineEditECM):
def set_add_separator(self, what): def set_add_separator(self, what):
self.add_separator = bool(what) self.add_separator = bool(what)
@dynamic_property @property
def all_items(self): def all_items(self):
def fget(self):
return self.mcompleter.model().all_items return self.mcompleter.model().all_items
def fset(self, items): @all_items.setter
def all_items(self, items):
self.mcompleter.model().set_items(items) self.mcompleter.model().set_items(items)
return property(fget=fget, fset=fset)
@dynamic_property @property
def disable_popup(self): def disable_popup(self):
def fget(self):
return self.mcompleter.disable_popup return self.mcompleter.disable_popup
def fset(self, val): @disable_popup.setter
def disable_popup(self, val):
self.mcompleter.disable_popup = bool(val) self.mcompleter.disable_popup = bool(val)
return property(fget=fget, fset=fset)
# }}} # }}}
def event(self, ev): def event(self, ev):
@ -471,23 +469,21 @@ class EditWithComplete(EnComboBox):
self.setText(what) self.setText(what)
self.lineEdit().selectAll() self.lineEdit().selectAll()
@dynamic_property @property
def all_items(self): def all_items(self):
def fget(self):
return self.lineEdit().all_items return self.lineEdit().all_items
def fset(self, val): @all_items.setter
def all_items(self, val):
self.lineEdit().all_items = val self.lineEdit().all_items = val
return property(fget=fget, fset=fset)
@dynamic_property @property
def disable_popup(self): def disable_popup(self):
def fget(self):
return self.lineEdit().disable_popup return self.lineEdit().disable_popup
def fset(self, val): @disable_popup.setter
def disable_popup(self, val):
self.lineEdit().disable_popup = bool(val) self.lineEdit().disable_popup = bool(val)
return property(fget=fget, fset=fset)
# }}} # }}}
def text(self): def text(self):

View File

@ -43,14 +43,13 @@ class ColorButton(QToolButton):
self.setIcon(QIcon(self.pix)) self.setIcon(QIcon(self.pix))
self.clicked.connect(self.choose_color) self.clicked.connect(self.choose_color)
@dynamic_property @property
def color(self): def color(self):
def fget(self):
return self._color.name(QColor.HexRgb)[1:] return self._color.name(QColor.HexRgb)[1:]
def fset(self, val): @color.setter
def color(self, val):
self._color = QColor('#' + val) self._color = QColor('#' + val)
return property(fget=fget, fset=fset)
def update_display(self): def update_display(self):
self.pix.fill(self._color) self.pix.fill(self._color)

View File

@ -377,14 +377,13 @@ class Comments(Base):
val = None val = None
return val return val
@dynamic_property @property
def tab(self): def tab(self):
def fget(self):
return self._tb.tab return self._tb.tab
def fset(self, val): @tab.setter
def tab(self, val):
self._tb.tab = val self._tb.tab = val
return property(fget=fget, fset=fset)
def connect_data_changed(self, slot): def connect_data_changed(self, slot):
self._tb.data_changed.connect(slot) self._tb.data_changed.connect(slot)

View File

@ -1367,11 +1367,9 @@ class DeviceMixin(object): # {{{
memory=[files, remove]) memory=[files, remove])
self.status_bar.show_message(_('Sending catalogs to device.'), 5000) self.status_bar.show_message(_('Sending catalogs to device.'), 5000)
@dynamic_property @property
def news_to_be_synced(self): def news_to_be_synced(self):
doc = 'Set of ids to be sent to device' 'Set of ids to be sent to device'
def fget(self):
ans = [] ans = []
try: try:
ans = self.library_view.model().db.prefs.get('news_to_be_synced', ans = self.library_view.model().db.prefs.get('news_to_be_synced',
@ -1381,7 +1379,8 @@ class DeviceMixin(object): # {{{
traceback.print_exc() traceback.print_exc()
return set(ans) return set(ans)
def fset(self, ids): @news_to_be_synced.setter
def news_to_be_synced(self, ids):
try: try:
self.library_view.model().db.new_api.set_pref('news_to_be_synced', self.library_view.model().db.new_api.set_pref('news_to_be_synced',
list(ids)) list(ids))
@ -1389,8 +1388,6 @@ class DeviceMixin(object): # {{{
import traceback import traceback
traceback.print_exc() traceback.print_exc()
return property(fget=fget, fset=fset, doc=doc)
def sync_news(self, send_ids=None, do_auto_convert=True): def sync_news(self, send_ids=None, do_auto_convert=True):
if self.device_connected: if self.device_connected:
del_on_upload = config['delete_news_from_library_on_upload'] del_on_upload = config['delete_news_from_library_on_upload']

View File

@ -378,15 +378,15 @@ class BasicRecipe(QWidget): # {{{
return False return False
return True return True
@dynamic_property @property
def recipe_source(self): def recipe_source(self):
def fget(self):
title = self.title.text().strip() title = self.title.text().strip()
feeds = [self.feeds.item(i).data(Qt.UserRole) for i in range(self.feeds.count())] feeds = [self.feeds.item(i).data(Qt.UserRole) for i in range(self.feeds.count())]
return options_to_recipe_source(title, self.oldest_article.value(), self.max_articles.value(), feeds) return options_to_recipe_source(title, self.oldest_article.value(), self.max_articles.value(), feeds)
def fset(self, src): @recipe_source.setter
def recipe_source(self, src):
self.feeds.clear() self.feeds.clear()
self.feed_title.clear() self.feed_title.clear()
self.feed_url.clear() self.feed_url.clear()
@ -403,7 +403,6 @@ class BasicRecipe(QWidget): # {{{
title, url = ('', x) if len(x) == 1 else x title, url = ('', x) if len(x) == 1 else x
QListWidgetItem('%s - %s' % (title, url), self.feeds).setData(Qt.UserRole, (title, url)) QListWidgetItem('%s - %s' % (title, url), self.feeds).setData(Qt.UserRole, (title, url))
return property(fget=fget, fset=fset)
# }}} # }}}
@ -431,17 +430,14 @@ class AdvancedRecipe(QWidget): # {{{
return False return False
return True return True
@dynamic_property @property
def recipe_source(self): def recipe_source(self):
def fget(self):
return self.editor.toPlainText() return self.editor.toPlainText()
def fset(self, src): @recipe_source.setter
def recipe_source(self, src):
self.editor.load_text(src, syntax='python', doc_name='<recipe>') self.editor.load_text(src, syntax='python', doc_name='<recipe>')
return property(fget=fget, fset=fset)
def sizeHint(self): def sizeHint(self):
return QSize(800, 500) return QSize(800, 500)
# }}} # }}}

View File

@ -64,14 +64,13 @@ class ProgressDialog(QDialog):
def set_value(self, val): def set_value(self, val):
self.value = val self.value = val
@dynamic_property @property
def value(self): def value(self):
def fset(self, val):
return self.bar.setValue(val)
def fget(self):
return self.bar.value() return self.bar.value()
return property(fget=fget, fset=fset)
@value.setter
def value(self, val):
self.bar.setValue(val)
def set_min(self, min): def set_min(self, min):
self.min = min self.min = min
@ -79,42 +78,38 @@ class ProgressDialog(QDialog):
def set_max(self, max): def set_max(self, max):
self.max = max self.max = max
@dynamic_property @property
def max(self): def max(self):
def fget(self):
return self.bar.maximum() return self.bar.maximum()
def fset(self, val): @max.setter
def max(self, val):
self.bar.setMaximum(val) self.bar.setMaximum(val)
return property(fget=fget, fset=fset)
@dynamic_property @property
def min(self): def min(self):
def fget(self):
return self.bar.minimum() return self.bar.minimum()
def fset(self, val): @min.setter
def min(self, val):
self.bar.setMinimum(val) self.bar.setMinimum(val)
return property(fget=fget, fset=fset)
@dynamic_property @property
def title(self): def title(self):
def fget(self):
return self.title_label.text() return self.title_label.text()
def fset(self, val): @title.setter
def title(self, val):
self.title_label.setText(unicode_type(val or '')) self.title_label.setText(unicode_type(val or ''))
return property(fget=fget, fset=fset)
@dynamic_property @property
def msg(self): def msg(self):
def fget(self):
return self.message.text() return self.message.text()
def fset(self, val): @msg.setter
def msg(self, val):
val = unicode_type(val or '') val = unicode_type(val or '')
self.message.setText(elided_text(val, self.font(), self.message.minimumWidth()-10)) self.message.setText(elided_text(val, self.font(), self.message.minimumWidth()-10))
return property(fget=fget, fset=fset)
def _canceled(self, *args): def _canceled(self, *args):
self.canceled = True self.canceled = True

View File

@ -353,18 +353,17 @@ class FontFamilyChooser(QWidget):
def clear_family(self): def clear_family(self):
self.font_family = None self.font_family = None
@dynamic_property @property
def font_family(self): def font_family(self):
def fget(self):
return self._current_family return self._current_family
def fset(self, val): @font_family.setter
def font_family(self, val):
if not val: if not val:
val = None val = None
self._current_family = val self._current_family = val
self.button.setText(val or self.default_text) self.button.setText(val or self.default_text)
self.family_changed.emit(val) self.family_changed.emit(val)
return property(fget=fget, fset=fset)
def show_chooser(self): def show_chooser(self):
d = FontFamilyDialog(self.font_family, self) d = FontFamilyDialog(self.font_family, self)

View File

@ -60,10 +60,8 @@ class LanguagesEdit(EditWithComplete):
parts = [x.strip() for x in raw.split(',')] parts = [x.strip() for x in raw.split(',')]
return [self.comma_rmap.get(x, x) for x in parts] return [self.comma_rmap.get(x, x) for x in parts]
@dynamic_property @property
def lang_codes(self): def lang_codes(self):
def fget(self):
vals = self.vals vals = self.vals
ans = [] ans = []
for name in vals: for name in vals:
@ -73,11 +71,10 @@ class LanguagesEdit(EditWithComplete):
ans.append(code) ans.append(code)
return ans return ans
def fset(self, lang_codes): @lang_codes.setter
def lang_codes(self, lang_codes):
self.set_lang_codes(lang_codes, allow_undo=False) self.set_lang_codes(lang_codes, allow_undo=False)
return property(fget=fget, fset=fset)
def set_lang_codes(self, lang_codes, allow_undo=True): def set_lang_codes(self, lang_codes, allow_undo=True):
ans = [] ans = []
for lc in lang_codes: for lc in lang_codes:

View File

@ -186,18 +186,17 @@ class PreserveViewState(object): # {{{
view.horizontalScrollBar().setValue(self.hscroll) view.horizontalScrollBar().setValue(self.hscroll)
self.init_vals() self.init_vals()
@dynamic_property @property
def state(self): def state(self):
def fget(self):
self.__enter__() self.__enter__()
return {x:getattr(self, x) for x in ('selected_ids', 'current_id', return {x:getattr(self, x) for x in ('selected_ids', 'current_id',
'vscroll', 'hscroll')} 'vscroll', 'hscroll')}
def fset(self, state): @state.setter
def state(self, state):
for k, v in iteritems(state): for k, v in iteritems(state):
setattr(self, k, v) setattr(self, k, v)
self.__exit__() self.__exit__()
return property(fget=fget, fset=fset)
# }}} # }}}
@ -1161,16 +1160,16 @@ class BooksView(QTableView): # {{{
ans.append(i) ans.append(i)
return ans return ans
@dynamic_property @property
def current_id(self): def current_id(self):
def fget(self):
try: try:
return self.model().id(self.currentIndex()) return self.model().id(self.currentIndex())
except: except:
pass pass
return None return None
def fset(self, val): @current_id.setter
def current_id(self, val):
if val is None: if val is None:
return return
m = self.model() m = self.model()
@ -1178,7 +1177,6 @@ class BooksView(QTableView): # {{{
if m.id(row) == val: if m.id(row) == val:
self.set_current_row(row, select=False) self.set_current_row(row, select=False)
break break
return property(fget=fget, fset=fset)
@property @property
def next_id(self): def next_id(self):

View File

@ -72,14 +72,13 @@ class BasicMetadataWidget(object):
def commit(self, db, id_): def commit(self, db, id_):
return True return True
@dynamic_property @property
def current_val(self): def current_val(self):
# Present in most but not all basic metadata widgets
def fget(self):
return None return None
def fset(self, val):
@current_val.setter
def current_val(self, val):
pass pass
return property(fget=fget, fset=fset)
''' '''
@ -225,16 +224,16 @@ class TitleEdit(EnLineEdit, ToMetadataMixin):
# to work even if some of the book files are opened in windows. # to work even if some of the book files are opened in windows.
getattr(db, 'set_'+ self.TITLE_ATTR)(id_, title, notify=False) getattr(db, 'set_'+ self.TITLE_ATTR)(id_, title, notify=False)
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
title = clean_text(unicode_type(self.text())) title = clean_text(unicode_type(self.text()))
if not title: if not title:
title = self.get_default() title = self.get_default()
return title.strip() return title.strip()
def fset(self, val): @current_val.setter
def current_val(self, val):
if hasattr(val, 'strip'): if hasattr(val, 'strip'):
val = val.strip() val = val.strip()
if not val: if not val:
@ -242,8 +241,6 @@ class TitleEdit(EnLineEdit, ToMetadataMixin):
self.set_text(val) self.set_text(val)
self.setCursorPosition(0) self.setCursorPosition(0)
return property(fget=fget, fset=fset)
def break_cycles(self): def break_cycles(self):
self.dialog = None self.dialog = None
@ -416,23 +413,21 @@ class AuthorsEdit(EditWithComplete, ToMetadataMixin):
self.books_to_refresh |= db.set_authors(id_, authors, notify=False, self.books_to_refresh |= db.set_authors(id_, authors, notify=False,
allow_case_change=True) allow_case_change=True)
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
au = clean_text(unicode_type(self.text())) au = clean_text(unicode_type(self.text()))
if not au: if not au:
au = self.get_default() au = self.get_default()
return string_to_authors(au) return string_to_authors(au)
def fset(self, val): @current_val.setter
def current_val(self, val):
if not val: if not val:
val = [self.get_default()] val = [self.get_default()]
self.set_edit_text(' & '.join([x.strip() for x in val])) self.set_edit_text(' & '.join([x.strip() for x in val]))
self.lineEdit().setCursorPosition(0) self.lineEdit().setCursorPosition(0)
return property(fget=fget, fset=fset)
def break_cycles(self): def break_cycles(self):
self.db = self.dialog = None self.db = self.dialog = None
try: try:
@ -485,20 +480,18 @@ class AuthorSortEdit(EnLineEdit, ToMetadataMixin):
self.first_time = True self.first_time = True
self.update_state() self.update_state()
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return clean_text(unicode_type(self.text())) return clean_text(unicode_type(self.text()))
def fset(self, val): @current_val.setter
def current_val(self, val):
if not val: if not val:
val = '' val = ''
self.set_text(val.strip()) self.set_text(val.strip())
self.setCursorPosition(0) self.setCursorPosition(0)
return property(fget=fget, fset=fset)
def update_state_and_val(self): def update_state_and_val(self):
# Handle case change if the authors box changed # Handle case change if the authors box changed
aus = authors_to_sort_string(self.authors_edit.current_val) aus = authors_to_sort_string(self.authors_edit.current_val)
@ -613,20 +606,18 @@ class SeriesEdit(EditWithComplete, ToMetadataMixin):
self.books_to_refresh = set([]) self.books_to_refresh = set([])
self.lineEdit().textChanged.connect(self.data_changed) self.lineEdit().textChanged.connect(self.data_changed)
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return clean_text(unicode_type(self.currentText())) return clean_text(unicode_type(self.currentText()))
def fset(self, val): @current_val.setter
def current_val(self, val):
if not val: if not val:
val = '' val = ''
self.set_edit_text(val.strip()) self.set_edit_text(val.strip())
self.lineEdit().setCursorPosition(0) self.lineEdit().setCursorPosition(0)
return property(fget=fget, fset=fset)
def initialize(self, db, id_): def initialize(self, db, id_):
self.books_to_refresh = set([]) self.books_to_refresh = set([])
all_series = db.all_series() all_series = db.all_series()
@ -672,20 +663,18 @@ class SeriesIndexEdit(make_undoable(QDoubleSpinBox), ToMetadataMixin):
def enable(self, *args): def enable(self, *args):
self.setEnabled(bool(self.series_edit.current_val)) self.setEnabled(bool(self.series_edit.current_val))
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return self.value() return self.value()
def fset(self, val): @current_val.setter
def current_val(self, val):
if val is None: if val is None:
val = 1.0 val = 1.0
val = float(val) val = float(val)
self.set_spinbox_value(val) self.set_spinbox_value(val)
return property(fget=fget, fset=fset)
def initialize(self, db, id_): def initialize(self, db, id_):
self.db = db self.db = db
if self.series_edit.current_val: if self.series_edit.current_val:
@ -1255,12 +1244,12 @@ class Cover(ImageView): # {{{
def changed(self): def changed(self):
return self.current_val != self.original_val return self.current_val != self.original_val
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return self._cdata return self._cdata
def fset(self, cdata): @current_val.setter
def current_val(self, cdata):
self._cdata = None self._cdata = None
self.cdata_before_trim = None self.cdata_before_trim = None
pm = QPixmap() pm = QPixmap()
@ -1279,8 +1268,6 @@ class Cover(ImageView): # {{{
self.setToolTip(tt) self.setToolTip(tt)
self.data_changed.emit() self.data_changed.emit()
return property(fget=fget, fset=fset)
def commit(self, db, id_): def commit(self, db, id_):
if self.changed: if self.changed:
if self.current_val: if self.current_val:
@ -1309,12 +1296,12 @@ class CommentsEdit(Editor, ToMetadataMixin): # {{{
FIELD_NAME = 'comments' FIELD_NAME = 'comments'
toolbar_prefs_name = 'metadata-comments-editor-widget-hidden-toolbars' toolbar_prefs_name = 'metadata-comments-editor-widget-hidden-toolbars'
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return self.html return self.html
def fset(self, val): @current_val.setter
def current_val(self, val):
if not val or not val.strip(): if not val or not val.strip():
val = '' val = ''
else: else:
@ -1322,7 +1309,6 @@ class CommentsEdit(Editor, ToMetadataMixin): # {{{
self.set_html(val, self.allow_undo) self.set_html(val, self.allow_undo)
self.wyswyg_dirtied() self.wyswyg_dirtied()
self.data_changed.emit() self.data_changed.emit()
return property(fget=fget, fset=fset)
def initialize(self, db, id_): def initialize(self, db, id_):
path = db.abspath(id_, index_is_id=True) path = db.abspath(id_, index_is_id=True)
@ -1350,14 +1336,13 @@ class RatingEdit(RatingEditor, ToMetadataMixin): # {{{
self.setWhatsThis(self.TOOLTIP) self.setWhatsThis(self.TOOLTIP)
self.currentTextChanged.connect(self.data_changed) self.currentTextChanged.connect(self.data_changed)
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return self.rating_value return self.rating_value
def fset(self, val): @current_val.setter
def current_val(self, val):
self.rating_value = val self.rating_value = val
return property(fget=fget, fset=fset)
def initialize(self, db, id_): def initialize(self, db, id_):
val = db.rating(id_, index_is_id=True) val = db.rating(id_, index_is_id=True)
@ -1390,17 +1375,16 @@ class TagsEdit(EditWithComplete, ToMetadataMixin): # {{{
self.setToolTip(self.TOOLTIP) self.setToolTip(self.TOOLTIP)
self.setWhatsThis(self.TOOLTIP) self.setWhatsThis(self.TOOLTIP)
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return [clean_text(x) for x in unicode_type(self.text()).split(',')] return [clean_text(x) for x in unicode_type(self.text()).split(',')]
def fset(self, val): @current_val.setter
def current_val(self, val):
if not val: if not val:
val = [] val = []
self.set_edit_text(', '.join([x.strip() for x in val])) self.set_edit_text(', '.join([x.strip() for x in val]))
self.setCursorPosition(0) self.setCursorPosition(0)
return property(fget=fget, fset=fset)
def initialize(self, db, id_): def initialize(self, db, id_):
self.books_to_refresh = set([]) self.books_to_refresh = set([])
@ -1454,14 +1438,13 @@ class LanguagesEdit(LE, ToMetadataMixin): # {{{
self.textChanged.connect(self.data_changed) self.textChanged.connect(self.data_changed)
self.setToolTip(self.TOOLTIP) self.setToolTip(self.TOOLTIP)
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return self.lang_codes return self.lang_codes
def fset(self, val): @current_val.setter
def current_val(self, val):
self.set_lang_codes(val, self.allow_undo) self.set_lang_codes(val, self.allow_undo)
return property(fget=fget, fset=fset)
def initialize(self, db, id_): def initialize(self, db, id_):
self.init_langs(db) self.init_langs(db)
@ -1562,9 +1545,8 @@ class IdentifiersEdit(QLineEdit, ToMetadataMixin):
if d.exec_() == d.Accepted: if d.exec_() == d.Accepted:
self.current_val = d.get_identifiers() self.current_val = d.get_identifiers()
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
raw = unicode_type(self.text()).strip() raw = unicode_type(self.text()).strip()
parts = [clean_text(x) for x in raw.split(',')] parts = [clean_text(x) for x in raw.split(',')]
ans = {} ans = {}
@ -1580,7 +1562,8 @@ class IdentifiersEdit(QLineEdit, ToMetadataMixin):
ans[itype] = c ans[itype] = c
return ans return ans
def fset(self, val): @current_val.setter
def current_val(self, val):
if not val: if not val:
val = {} val = {}
@ -1599,7 +1582,6 @@ class IdentifiersEdit(QLineEdit, ToMetadataMixin):
# Use selectAll + insert instead of setText so that undo works # Use selectAll + insert instead of setText so that undo works
self.selectAll(), self.insert(txt.strip()) self.selectAll(), self.insert(txt.strip())
self.setCursorPosition(0) self.setCursorPosition(0)
return property(fget=fget, fset=fset)
def initialize(self, db, id_): def initialize(self, db, id_):
self.original_val = db.get_identifiers(id_, index_is_id=True) self.original_val = db.get_identifiers(id_, index_is_id=True)
@ -1778,20 +1760,18 @@ class PublisherEdit(EditWithComplete, ToMetadataMixin): # {{{
self.clear_button.setToolTip(_('Clear publisher')) self.clear_button.setToolTip(_('Clear publisher'))
self.clear_button.clicked.connect(self.clearEditText) self.clear_button.clicked.connect(self.clearEditText)
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return clean_text(unicode_type(self.currentText())) return clean_text(unicode_type(self.currentText()))
def fset(self, val): @current_val.setter
def current_val(self, val):
if not val: if not val:
val = '' val = ''
self.set_edit_text(val.strip()) self.set_edit_text(val.strip())
self.lineEdit().setCursorPosition(0) self.lineEdit().setCursorPosition(0)
return property(fget=fget, fset=fset)
def initialize(self, db, id_): def initialize(self, db, id_):
self.books_to_refresh = set([]) self.books_to_refresh = set([])
all_publishers = db.all_publishers() all_publishers = db.all_publishers()
@ -1857,18 +1837,17 @@ class DateEdit(make_undoable(QDateTimeEdit), ToMetadataMixin):
def reset_date(self, *args): def reset_date(self, *args):
self.current_val = None self.current_val = None
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return qt_to_dt(self.dateTime(), as_utc=False) return qt_to_dt(self.dateTime(), as_utc=False)
def fset(self, val): @current_val.setter
def current_val(self, val):
if val is None or is_date_undefined(val): if val is None or is_date_undefined(val):
val = UNDEFINED_DATE val = UNDEFINED_DATE
else: else:
val = as_local_time(val) val = as_local_time(val)
self.set_spinbox_value(val) self.set_spinbox_value(val)
return property(fget=fget, fset=fset)
def initialize(self, db, id_): def initialize(self, db, id_):
self.current_val = getattr(db, self.ATTR)(id_, index_is_id=True) self.current_val = getattr(db, self.ATTR)(id_, index_is_id=True)

View File

@ -49,9 +49,8 @@ class LineEdit(EditWithComplete):
self.set_separator(sep) self.set_separator(sep)
self.textChanged.connect(self.changed) self.textChanged.connect(self.changed)
@dynamic_property @property
def value(self): def value(self):
def fget(self):
val = unicode_type(self.text()).strip() val = unicode_type(self.text()).strip()
ism = self.metadata['is_multiple'] ism = self.metadata['is_multiple']
if ism: if ism:
@ -62,7 +61,8 @@ class LineEdit(EditWithComplete):
val = [x.strip() for x in val.split(ism['list_to_ui']) if x.strip()] val = [x.strip() for x in val.split(ism['list_to_ui']) if x.strip()]
return val return val
def fset(self, val): @value.setter
def value(self, val):
ism = self.metadata['is_multiple'] ism = self.metadata['is_multiple']
if ism: if ism:
if not val: if not val:
@ -71,7 +71,6 @@ class LineEdit(EditWithComplete):
val = ism['list_to_ui'].join(val) val = ism['list_to_ui'].join(val)
self.setText(val) self.setText(val)
self.setCursorPosition(0) self.setCursorPosition(0)
return property(fget=fget, fset=fset)
def from_mi(self, mi): def from_mi(self, mi):
val = mi.get(self.field, default='') or '' val = mi.get(self.field, default='') or ''
@ -85,15 +84,14 @@ class LineEdit(EditWithComplete):
elif self.field == 'authors': elif self.field == 'authors':
mi.set('author_sort', authors_to_sort_string(val)) mi.set('author_sort', authors_to_sort_string(val))
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return unicode_type(self.text()) return unicode_type(self.text())
def fset(self, val): @current_val.setter
def current_val(self, val):
self.setText(val) self.setText(val)
self.setCursorPosition(0) self.setCursorPosition(0)
return property(fget=fget, fset=fset)
@property @property
def is_blank(self): def is_blank(self):
@ -119,14 +117,13 @@ class LanguagesEdit(LE):
if not is_new: if not is_new:
self.lineEdit().setReadOnly(True) self.lineEdit().setReadOnly(True)
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return self.lang_codes return self.lang_codes
def fset(self, val): @current_val.setter
def current_val(self, val):
self.lang_codes = val self.lang_codes = val
return property(fget=fget, fset=fset)
def from_mi(self, mi): def from_mi(self, mi):
self.lang_codes = mi.languages self.lang_codes = mi.languages
@ -241,17 +238,16 @@ class IdentifiersEdit(LineEdit):
def to_mi(self, mi): def to_mi(self, mi):
mi.set_identifiers(self.as_dict) mi.set_identifiers(self.as_dict)
@dynamic_property @property
def as_dict(self): def as_dict(self):
def fget(self):
parts = (x.strip() for x in self.current_val.split(',') if x.strip()) parts = (x.strip() for x in self.current_val.split(',') if x.strip())
return {k:v for k, v in iteritems({x.partition(':')[0].strip():x.partition(':')[-1].strip() for x in parts}) if k and v} return {k:v for k, v in iteritems({x.partition(':')[0].strip():x.partition(':')[-1].strip() for x in parts}) if k and v}
def fset(self, val): @as_dict.setter
def as_dict(self, val):
val = ('%s:%s' % (k, v) for k, v in iteritems(val)) val = ('%s:%s' % (k, v) for k, v in iteritems(val))
self.setText(', '.join(val)) self.setText(', '.join(val))
self.setCursorPosition(0) self.setCursorPosition(0)
return property(fget=fget, fset=fset)
class CommentsEdit(Editor): class CommentsEdit(Editor):
@ -269,15 +265,14 @@ class CommentsEdit(Editor):
self.hide_toolbars() self.hide_toolbars()
self.set_readonly(True) self.set_readonly(True)
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return self.html return self.html
def fset(self, val): @current_val.setter
def current_val(self, val):
self.html = val or '' self.html = val or ''
self.changed.emit() self.changed.emit()
return property(fget=fget, fset=fset)
def from_mi(self, mi): def from_mi(self, mi):
val = mi.get(self.field, default='') val = mi.get(self.field, default='')
@ -315,16 +310,15 @@ class CoverView(QWidget):
def is_blank(self): def is_blank(self):
return self.pixmap is None return self.pixmap is None
@dynamic_property @property
def current_val(self): def current_val(self):
def fget(self):
return self.pixmap return self.pixmap
def fset(self, val): @current_val.setter
def current_val(self, val):
self.pixmap = val self.pixmap = val
self.changed.emit() self.changed.emit()
self.update() self.update()
return property(fget=fget, fset=fset)
def from_mi(self, mi): def from_mi(self, mi):
p = getattr(mi, 'cover', None) p = getattr(mi, 'cover', None)

View File

@ -138,35 +138,33 @@ class ConditionEditor(QWidget): # {{{
b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon) b.setSizeAdjustPolicy(b.AdjustToMinimumContentsLengthWithIcon)
b.setMinimumContentsLength(20) b.setMinimumContentsLength(20)
@dynamic_property @property
def current_col(self): def current_col(self):
def fget(self):
idx = self.column_box.currentIndex() idx = self.column_box.currentIndex()
return unicode_type(self.column_box.itemData(idx) or '') return unicode_type(self.column_box.itemData(idx) or '')
def fset(self, val): @current_col.setter
def current_col(self, val):
for idx in range(self.column_box.count()): for idx in range(self.column_box.count()):
c = unicode_type(self.column_box.itemData(idx) or '') c = unicode_type(self.column_box.itemData(idx) or '')
if c == val: if c == val:
self.column_box.setCurrentIndex(idx) self.column_box.setCurrentIndex(idx)
return return
raise ValueError('Column %r not found'%val) raise ValueError('Column %r not found'%val)
return property(fget=fget, fset=fset)
@dynamic_property @property
def current_action(self): def current_action(self):
def fget(self):
idx = self.action_box.currentIndex() idx = self.action_box.currentIndex()
return unicode_type(self.action_box.itemData(idx) or '') return unicode_type(self.action_box.itemData(idx) or '')
def fset(self, val): @current_action.setter
def current_action(self, val):
for idx in range(self.action_box.count()): for idx in range(self.action_box.count()):
c = unicode_type(self.action_box.itemData(idx) or '') c = unicode_type(self.action_box.itemData(idx) or '')
if c == val: if c == val:
self.action_box.setCurrentIndex(idx) self.action_box.setCurrentIndex(idx)
return return
raise ValueError('Action %r not valid for current column'%val) raise ValueError('Action %r not valid for current column'%val)
return property(fget=fget, fset=fset)
@property @property
def current_val(self): def current_val(self):
@ -176,17 +174,17 @@ class ConditionEditor(QWidget): # {{{
ans = rmap.get(lower(ans), ans) ans = rmap.get(lower(ans), ans)
return ans return ans
@dynamic_property @property
def condition(self): def condition(self):
def fget(self):
c, a, v = (self.current_col, self.current_action, c, a, v = (self.current_col, self.current_action,
self.current_val) self.current_val)
if not c or not a: if not c or not a:
return None return None
return (c, a, v) return (c, a, v)
def fset(self, condition): @condition.setter
def condition(self, condition):
c, a, v = condition c, a, v = condition
if not v: if not v:
v = '' v = ''
@ -195,8 +193,6 @@ class ConditionEditor(QWidget): # {{{
self.current_action = a self.current_action = a
self.value_box.setText(v) self.value_box.setText(v)
return property(fget=fget, fset=fset)
def init_action_box(self): def init_action_box(self):
self.action_box.blockSignals(True) self.action_box.blockSignals(True)
self.action_box.clear() self.action_box.clear()

View File

@ -62,23 +62,21 @@ class ResizeDialog(QDialog): # {{{
other.setValue(oval) other.setValue(oval)
other.blockSignals(False) other.blockSignals(False)
@dynamic_property @property
def width(self): def width(self):
def fget(self):
return self._width.value() return self._width.value()
def fset(self, val): @width.setter
def width(self, val):
self._width.setValue(val) self._width.setValue(val)
return property(fget=fget, fset=fset)
@dynamic_property @property
def height(self): def height(self):
def fget(self):
return self._height.value() return self._height.value()
def fset(self, val): @height.setter
def height(self, val):
self._height.setValue(val) self._height.setValue(val)
return property(fget=fget, fset=fset)
# }}} # }}}
@ -111,24 +109,22 @@ class Editor(QMainWindow):
self.canvas.undo_redo_state_changed.connect(self.undo_redo_state_changed) self.canvas.undo_redo_state_changed.connect(self.undo_redo_state_changed)
self.canvas.selection_state_changed.connect(self.update_clipboard_actions) self.canvas.selection_state_changed.connect(self.update_clipboard_actions)
@dynamic_property @property
def is_modified(self): def is_modified(self):
def fget(self):
return self._is_modified return self._is_modified
def fset(self, val): @is_modified.setter
def is_modified(self, val):
self._is_modified = val self._is_modified = val
self.modification_state_changed.emit(val) self.modification_state_changed.emit(val)
return property(fget=fget, fset=fset)
@dynamic_property @property
def current_editing_state(self): def current_editing_state(self):
def fget(self):
return {} return {}
def fset(self, val): @current_editing_state.setter
def current_editing_state(self, val):
pass pass
return property(fget=fget, fset=fset)
@property @property
def undo_available(self): def undo_available(self):
@ -138,14 +134,13 @@ class Editor(QMainWindow):
def redo_available(self): def redo_available(self):
return self.canvas.redo_action.isEnabled() return self.canvas.redo_action.isEnabled()
@dynamic_property @property
def current_line(self): def current_line(self):
def fget(self):
return 0 return 0
def fset(self, val): @current_line.setter
def current_line(self, val):
pass pass
return property(fget=fget, fset=fset)
@property @property
def number_of_lines(self): def number_of_lines(self):
@ -160,15 +155,14 @@ class Editor(QMainWindow):
def get_raw_data(self): def get_raw_data(self):
return self.canvas.get_image_data(quality=self.quality) return self.canvas.get_image_data(quality=self.quality)
@dynamic_property @property
def data(self): def data(self):
def fget(self):
return self.get_raw_data() return self.get_raw_data()
def fset(self, val): @data.setter
def data(self, val):
self.canvas.load_image(val) self.canvas.load_image(val)
self._is_modified = False # The image_changed signal will have been triggered causing this editor to be incorrectly marked as modified self._is_modified = False # The image_changed signal will have been triggered causing this editor to be incorrectly marked as modified
return property(fget=fget, fset=fset)
def replace_data(self, raw, only_if_different=True): def replace_data(self, raw, only_if_different=True):
# We ignore only_if_different as it is useless in our case, and # We ignore only_if_different as it is useless in our case, and

View File

@ -221,9 +221,8 @@ class EditorTabStop(object):
with m: with m:
m.text = text m.text = text
@dynamic_property @property
def text(self): def text(self):
def fget(self):
editor = self.editor() editor = self.editor()
if editor is None or self.is_deleted: if editor is None or self.is_deleted:
return '' return ''
@ -231,7 +230,8 @@ class EditorTabStop(object):
c.setPosition(self.left), c.setPosition(self.right, c.KeepAnchor) c.setPosition(self.left), c.setPosition(self.right, c.KeepAnchor)
return editor.selected_text_from_cursor(c) return editor.selected_text_from_cursor(c)
def fset(self, text): @text.setter
def text(self, text):
editor = self.editor() editor = self.editor()
if editor is None or self.is_deleted: if editor is None or self.is_deleted:
return return
@ -240,7 +240,6 @@ class EditorTabStop(object):
c.setPosition(self.left), c.setPosition(self.right, c.KeepAnchor) c.setPosition(self.left), c.setPosition(self.right, c.KeepAnchor)
c.insertText(text) c.insertText(text)
c.endEditBlock() c.endEditBlock()
return property(fget=fget, fset=fset)
def set_editor_cursor(self, editor): def set_editor_cursor(self, editor):
if not self.is_deleted: if not self.is_deleted:
@ -537,12 +536,8 @@ class EditSnippet(QWidget):
self.types.item(0).setCheckState(Qt.Checked) self.types.item(0).setCheckState(Qt.Checked)
(self.name if self.creating_snippet else self.template).setFocus(Qt.OtherFocusReason) (self.name if self.creating_snippet else self.template).setFocus(Qt.OtherFocusReason)
@dynamic_property @property
def snip(self): def snip(self):
def fset(self, snip):
self.apply_snip(snip)
def fget(self):
ftypes = [] ftypes = []
for i in range(self.types.count()): for i in range(self.types.count()):
i = self.types.item(i) i = self.types.item(i)
@ -550,7 +545,9 @@ class EditSnippet(QWidget):
ftypes.append(i.data(Qt.UserRole)) ftypes.append(i.data(Qt.UserRole))
return {'description':self.name.text().strip(), 'trigger':self.trig.text(), 'template':self.template.toPlainText(), 'syntaxes':ftypes} return {'description':self.name.text().strip(), 'trigger':self.trig.text(), 'template':self.template.toPlainText(), 'syntaxes':ftypes}
return property(fget=fget, fset=fset) @snip.setter
def snip(self, snip):
self.apply_snip(snip)
def validate(self): def validate(self):
snip = self.snip snip = self.snip

View File

@ -206,17 +206,15 @@ class TextEdit(PlainTextEdit):
insert_text(md.html()) insert_text(md.html())
return return
@dynamic_property @property
def is_modified(self): def is_modified(self):
''' True if the document has been modified since it was loaded or since ''' True if the document has been modified since it was loaded or since
the last time is_modified was set to False. ''' the last time is_modified was set to False. '''
def fget(self):
return self.document().isModified() return self.document().isModified()
def fset(self, val): @is_modified.setter
def is_modified(self, val):
self.document().setModified(bool(val)) self.document().setModified(bool(val))
return property(fget=fget, fset=fset)
def sizeHint(self): def sizeHint(self):
return self.size_hint return self.size_hint

View File

@ -159,28 +159,26 @@ class Editor(QMainWindow):
self.editor.link_clicked.connect(self.link_clicked) self.editor.link_clicked.connect(self.link_clicked)
self.editor.smart_highlighting_updated.connect(self.smart_highlighting_updated) self.editor.smart_highlighting_updated.connect(self.smart_highlighting_updated)
@dynamic_property @property
def current_line(self): def current_line(self):
def fget(self):
return self.editor.textCursor().blockNumber() return self.editor.textCursor().blockNumber()
def fset(self, val): @current_line.setter
def current_line(self, val):
self.editor.go_to_line(val) self.editor.go_to_line(val)
return property(fget=fget, fset=fset)
@dynamic_property @property
def current_editing_state(self): def current_editing_state(self):
def fget(self):
c = self.editor.textCursor() c = self.editor.textCursor()
return {'cursor':(c.anchor(), c.position())} return {'cursor':(c.anchor(), c.position())}
def fset(self, val): @current_editing_state.setter
def current_editing_state(self, val):
anchor, position = val.get('cursor', (None, None)) anchor, position = val.get('cursor', (None, None))
if anchor is not None and position is not None: if anchor is not None and position is not None:
c = self.editor.textCursor() c = self.editor.textCursor()
c.setPosition(anchor), c.setPosition(position, c.KeepAnchor) c.setPosition(anchor), c.setPosition(position, c.KeepAnchor)
self.editor.setTextCursor(c) self.editor.setTextCursor(c)
return property(fget=fget, fset=fset)
def current_tag(self, for_position_sync=True): def current_tag(self, for_position_sync=True):
return self.editor.current_tag(for_position_sync=for_position_sync) return self.editor.current_tag(for_position_sync=for_position_sync)
@ -189,18 +187,17 @@ class Editor(QMainWindow):
def number_of_lines(self): def number_of_lines(self):
return self.editor.blockCount() return self.editor.blockCount()
@dynamic_property @property
def data(self): def data(self):
def fget(self):
ans = self.get_raw_data() ans = self.get_raw_data()
ans, changed = replace_encoding_declarations(ans, enc='utf-8', limit=4*1024) ans, changed = replace_encoding_declarations(ans, enc='utf-8', limit=4*1024)
if changed: if changed:
self.data = ans self.data = ans
return ans.encode('utf-8') return ans.encode('utf-8')
def fset(self, val): @data.setter
def data(self, val):
self.editor.load_text(val, syntax=self.syntax, doc_name=editor_name(self)) self.editor.load_text(val, syntax=self.syntax, doc_name=editor_name(self))
return property(fget=fget, fset=fset)
def init_from_template(self, template): def init_from_template(self, template):
self.editor.load_text(template, syntax=self.syntax, process_template=True, doc_name=editor_name(self)) self.editor.load_text(template, syntax=self.syntax, process_template=True, doc_name=editor_name(self))
@ -317,14 +314,13 @@ class Editor(QMainWindow):
def has_marked_text(self): def has_marked_text(self):
return self.editor.current_search_mark is not None return self.editor.current_search_mark is not None
@dynamic_property @property
def is_modified(self): def is_modified(self):
def fget(self):
return self.editor.is_modified return self.editor.is_modified
def fset(self, val): @is_modified.setter
def is_modified(self, val):
self.editor.is_modified = val self.editor.is_modified = val
return property(fget=fget, fset=fset)
def create_toolbars(self): def create_toolbars(self):
self.action_bar = b = self.addToolBar(_('Edit actions tool bar')) self.action_bar = b = self.addToolBar(_('Edit actions tool bar'))

View File

@ -370,17 +370,16 @@ class WebView(QWebView):
def refresh(self): def refresh(self):
self.pageAction(self.page().Reload).trigger() self.pageAction(self.page().Reload).trigger()
@dynamic_property @property
def scroll_pos(self): def scroll_pos(self):
def fget(self):
mf = self.page().mainFrame() mf = self.page().mainFrame()
return (mf.scrollBarValue(Qt.Horizontal), mf.scrollBarValue(Qt.Vertical)) return (mf.scrollBarValue(Qt.Horizontal), mf.scrollBarValue(Qt.Vertical))
def fset(self, val): @scroll_pos.setter
def scroll_pos(self, val):
mf = self.page().mainFrame() mf = self.page().mainFrame()
mf.setScrollBarValue(Qt.Horizontal, val[0]) mf.setScrollBarValue(Qt.Horizontal, val[0])
mf.setScrollBarValue(Qt.Vertical, val[1]) mf.setScrollBarValue(Qt.Vertical, val[1])
return property(fget=fget, fset=fset)
def clear(self): def clear(self):
self.setHtml(_( self.setHtml(_(

View File

@ -1061,14 +1061,13 @@ class CSSWidget(QWidget):
self.summary = la = QLabel('\xa0') self.summary = la = QLabel('\xa0')
h.addWidget(la) h.addWidget(la)
@dynamic_property @property
def sort_order(self): def sort_order(self):
def fget(self):
return [Qt.AscendingOrder, Qt.DescendingOrder][self._sort_order.currentIndex()] return [Qt.AscendingOrder, Qt.DescendingOrder][self._sort_order.currentIndex()]
def fset(self, val): @sort_order.setter
def sort_order(self, val):
self._sort_order.setCurrentIndex({Qt.AscendingOrder:0}.get(val, 1)) self._sort_order.setCurrentIndex({Qt.AscendingOrder:0}.get(val, 1))
return property(fget=fget, fset=fset)
def update_summary(self): def update_summary(self):
self.summary.setText(_('{0} rules, {1} unused').format(self.model.rowCount(), self.model.num_unused)) self.summary.setText(_('{0} rules, {1} unused').format(self.model.rowCount(), self.model.num_unused))

View File

@ -152,16 +152,15 @@ class WhereBox(QComboBox):
f.setBold(True), f.setItalic(True) f.setBold(True), f.setItalic(True)
self.setFont(f) self.setFont(f)
@dynamic_property @property
def where(self): def where(self):
wm = {0:'current', 1:'text', 2:'styles', 3:'selected', 4:'open', 5:'selected-text'} wm = {0:'current', 1:'text', 2:'styles', 3:'selected', 4:'open', 5:'selected-text'}
def fget(self):
return wm[self.currentIndex()] return wm[self.currentIndex()]
def fset(self, val): @where.setter
def where(self, val):
wm = {0:'current', 1:'text', 2:'styles', 3:'selected', 4:'open', 5:'selected-text'}
self.setCurrentIndex({v:k for k, v in iteritems(wm)}[val]) self.setCurrentIndex({v:k for k, v in iteritems(wm)}[val])
return property(fget=fget, fset=fset)
def showPopup(self): def showPopup(self):
# We do it like this so that the popup uses a normal font # We do it like this so that the popup uses a normal font
@ -190,14 +189,13 @@ class DirectionBox(QComboBox):
<dd>Search for the previous match from your current position</dd> <dd>Search for the previous match from your current position</dd>
</dl>''')) </dl>'''))
@dynamic_property @property
def direction(self): def direction(self):
def fget(self):
return 'down' if self.currentIndex() == 0 else 'up' return 'down' if self.currentIndex() == 0 else 'up'
def fset(self, val): @direction.setter
def direction(self, val):
self.setCurrentIndex(1 if val == 'up' else 0) self.setCurrentIndex(1 if val == 'up' else 0)
return property(fget=fget, fset=fset)
class ModeBox(QComboBox): class ModeBox(QComboBox):
@ -216,14 +214,13 @@ class ModeBox(QComboBox):
<dd>The search expression is interpreted as a regular expression. The replace expression is an arbitrarily powerful Python function.</dd> <dd>The search expression is interpreted as a regular expression. The replace expression is an arbitrarily powerful Python function.</dd>
</dl>''')) </dl>'''))
@dynamic_property @property
def mode(self): def mode(self):
def fget(self):
return ('normal', 'regex', 'function')[self.currentIndex()] return ('normal', 'regex', 'function')[self.currentIndex()]
def fset(self, val): @mode.setter
def mode(self, val):
self.setCurrentIndex({'regex':1, 'function':2}.get(val, 0)) self.setCurrentIndex({'regex':1, 'function':2}.get(val, 0))
return property(fget=fget, fset=fset)
class SearchWidget(QWidget): class SearchWidget(QWidget):
@ -353,91 +350,82 @@ class SearchWidget(QWidget):
self.replace_text.setVisible(not function_mode) self.replace_text.setVisible(not function_mode)
self.functions_container.setVisible(function_mode) self.functions_container.setVisible(function_mode)
@dynamic_property @property
def mode(self): def mode(self):
def fget(self):
return self.mode_box.mode return self.mode_box.mode
def fset(self, val): @mode.setter
def mode(self, val):
self.mode_box.mode = val self.mode_box.mode = val
self.da.setVisible(self.mode in ('regex', 'function')) self.da.setVisible(self.mode in ('regex', 'function'))
return property(fget=fget, fset=fset)
@dynamic_property @property
def find(self): def find(self):
def fget(self):
return unicode_type(self.find_text.text()) return unicode_type(self.find_text.text())
def fset(self, val): @find.setter
def find(self, val):
self.find_text.setText(val) self.find_text.setText(val)
return property(fget=fget, fset=fset)
@dynamic_property @property
def replace(self): def replace(self):
def fget(self):
if self.mode == 'function': if self.mode == 'function':
return self.functions.text() return self.functions.text()
return unicode_type(self.replace_text.text()) return unicode_type(self.replace_text.text())
def fset(self, val): @replace.setter
def replace(self, val):
self.replace_text.setText(val) self.replace_text.setText(val)
return property(fget=fget, fset=fset)
@dynamic_property @property
def where(self): def where(self):
def fget(self):
return self.where_box.where return self.where_box.where
def fset(self, val): @where.setter
def where(self, val):
self.where_box.where = val self.where_box.where = val
return property(fget=fget, fset=fset)
@dynamic_property @property
def case_sensitive(self): def case_sensitive(self):
def fget(self):
return self.cs.isChecked() return self.cs.isChecked()
def fset(self, val): @case_sensitive.setter
def case_sensitive(self, val):
self.cs.setChecked(bool(val)) self.cs.setChecked(bool(val))
return property(fget=fget, fset=fset)
@dynamic_property @property
def direction(self): def direction(self):
def fget(self):
return self.direction_box.direction return self.direction_box.direction
def fset(self, val): @direction.setter
def direction(self, val):
self.direction_box.direction = val self.direction_box.direction = val
return property(fget=fget, fset=fset)
@dynamic_property @property
def wrap(self): def wrap(self):
def fget(self):
return self.wr.isChecked() return self.wr.isChecked()
def fset(self, val): @wrap.setter
def wrap(self, val):
self.wr.setChecked(bool(val)) self.wr.setChecked(bool(val))
return property(fget=fget, fset=fset)
@dynamic_property @property
def dot_all(self): def dot_all(self):
def fget(self):
return self.da.isChecked() return self.da.isChecked()
def fset(self, val): @dot_all.setter
def dot_all(self, val):
self.da.setChecked(bool(val)) self.da.setChecked(bool(val))
return property(fget=fget, fset=fset)
@dynamic_property @property
def state(self): def state(self):
def fget(self):
return {x:getattr(self, x) for x in self.DEFAULT_STATE} return {x:getattr(self, x) for x in self.DEFAULT_STATE}
def fset(self, val): @state.setter
def state(self, val):
for x in self.DEFAULT_STATE: for x in self.DEFAULT_STATE:
if x in val: if x in val:
setattr(self, x, val[x]) setattr(self, x, val[x])
return property(fget=fget, fset=fset)
def restore_state(self): def restore_state(self):
self.state = tprefs.get('find-widget-state', self.DEFAULT_STATE) self.state = tprefs.get('find-widget-state', self.DEFAULT_STATE)
@ -1008,14 +996,13 @@ class SavedSearches(QWidget):
self.searches.setFocus(Qt.OtherFocusReason) self.searches.setFocus(Qt.OtherFocusReason)
@dynamic_property @property
def state(self): def state(self):
def fget(self):
return {'wrap':self.wrap, 'direction':self.direction, 'where':self.where} return {'wrap':self.wrap, 'direction':self.direction, 'where':self.where}
def fset(self, val): @state.setter
def state(self, val):
self.wrap, self.where, self.direction = val['wrap'], val['where'], val['direction'] self.wrap, self.where, self.direction = val['wrap'], val['where'], val['direction']
return property(fget=fget, fset=fset)
def save_state(self): def save_state(self):
tprefs['saved_seaches_state'] = self.state tprefs['saved_seaches_state'] = self.state
@ -1042,32 +1029,29 @@ class SavedSearches(QWidget):
for x in ('eb', 'ab', 'rb', 'upb', 'dnb', 'd2', 'filter_text', 'cft', 'd3', 'ib', 'eb2'): for x in ('eb', 'ab', 'rb', 'upb', 'dnb', 'd2', 'filter_text', 'cft', 'd3', 'ib', 'eb2'):
getattr(self, x).setVisible(visible) getattr(self, x).setVisible(visible)
@dynamic_property @property
def where(self): def where(self):
def fget(self):
return self.where_box.where return self.where_box.where
def fset(self, val): @where.setter
def where(self, val):
self.where_box.where = val self.where_box.where = val
return property(fget=fget, fset=fset)
@dynamic_property @property
def direction(self): def direction(self):
def fget(self):
return self.direction_box.direction return self.direction_box.direction
def fset(self, val): @direction.setter
def direction(self, val):
self.direction_box.direction = val self.direction_box.direction = val
return property(fget=fget, fset=fset)
@dynamic_property @property
def wrap(self): def wrap(self):
def fget(self):
return self.wr.isChecked() return self.wr.isChecked()
def fset(self, val): @wrap.setter
def wrap(self, val):
self.wr.setChecked(bool(val)) self.wr.setChecked(bool(val))
return property(fget=fget, fset=fset)
def do_filter(self, text): def do_filter(self, text):
self.model.do_filter(text) self.model.do_filter(text)

View File

@ -36,14 +36,13 @@ class ModeBox(QComboBox):
<dd>The search expression is interpreted as a regular expression. See the User Manual for more help on using regular expressions.</dd> <dd>The search expression is interpreted as a regular expression. See the User Manual for more help on using regular expressions.</dd>
</dl>''')) </dl>'''))
@dynamic_property @property
def mode(self): def mode(self):
def fget(self):
return ('normal', 'regex')[self.currentIndex()] return ('normal', 'regex')[self.currentIndex()]
def fset(self, val): @mode.setter
def mode(self, val):
self.setCurrentIndex({'regex':1}.get(val, 0)) self.setCurrentIndex({'regex':1}.get(val, 0))
return property(fget=fget, fset=fset)
class WhereBox(QComboBox): class WhereBox(QComboBox):
@ -71,16 +70,15 @@ class WhereBox(QComboBox):
f.setBold(True), f.setItalic(True) f.setBold(True), f.setItalic(True)
self.setFont(f) self.setFont(f)
@dynamic_property @property
def where(self): def where(self):
wm = {0:'current', 1:'text', 2:'selected', 3:'open'} wm = {0:'current', 1:'text', 2:'selected', 3:'open'}
def fget(self):
return wm[self.currentIndex()] return wm[self.currentIndex()]
def fset(self, val): @where.setter
def where(self, val):
wm = {0:'current', 1:'text', 2:'selected', 3:'open'}
self.setCurrentIndex({v:k for k, v in iteritems(wm)}[val]) self.setCurrentIndex({v:k for k, v in iteritems(wm)}[val])
return property(fget=fget, fset=fset)
def showPopup(self): def showPopup(self):
# We do it like this so that the popup uses a normal font # We do it like this so that the popup uses a normal font
@ -137,17 +135,16 @@ class TextSearch(QWidget):
state = tprefs.get('text_search_widget_state') state = tprefs.get('text_search_widget_state')
self.state = state or {} self.state = state or {}
@dynamic_property @property
def state(self): def state(self):
def fget(self):
return {'mode': self.mode.mode, 'where':self.where_box.where, 'case_sensitive':self.cs.isChecked(), 'dot_all':self.da.isChecked()} return {'mode': self.mode.mode, 'where':self.where_box.where, 'case_sensitive':self.cs.isChecked(), 'dot_all':self.da.isChecked()}
def fset(self, val): @state.setter
def state(self, val):
self.mode.mode = val.get('mode', 'normal') self.mode.mode = val.get('mode', 'normal')
self.where_box.where = val.get('where', 'current') self.where_box.where = val.get('where', 'current')
self.cs.setChecked(bool(val.get('case_sensitive'))) self.cs.setChecked(bool(val.get('case_sensitive')))
self.da.setChecked(bool(val.get('dot_all', True))) self.da.setChecked(bool(val.get('dot_all', True)))
return property(fget=fget, fset=fset)
def save_state(self): def save_state(self):
tprefs['text_search_widget_state'] = self.state tprefs['text_search_widget_state'] = self.state

View File

@ -236,17 +236,16 @@ class ConfigDialog(QDialog, Ui_Dialog):
from calibre.gui2.viewer.main import dprefs from calibre.gui2.viewer.main import dprefs
self.word_lookups = dprefs['word_lookups'] self.word_lookups = dprefs['word_lookups']
@dynamic_property @property
def word_lookups(self): def word_lookups(self):
def fget(self):
return dict(self.dictionary_list.item(i).data(Qt.UserRole) for i in range(self.dictionary_list.count())) return dict(self.dictionary_list.item(i).data(Qt.UserRole) for i in range(self.dictionary_list.count()))
def fset(self, wl): @word_lookups.setter
def word_lookups(self, wl):
self.dictionary_list.clear() self.dictionary_list.clear()
for langcode, url in sorted(iteritems(wl), key=lambda lc_url:sort_key(calibre_langcode_to_name(lc_url[0]))): for langcode, url in sorted(iteritems(wl), key=lambda lc_url:sort_key(calibre_langcode_to_name(lc_url[0]))):
i = QListWidgetItem('%s: %s' % (calibre_langcode_to_name(langcode), url), self.dictionary_list) i = QListWidgetItem('%s: %s' % (calibre_langcode_to_name(langcode), url), self.dictionary_list)
i.setData(Qt.UserRole, (langcode, url)) i.setData(Qt.UserRole, (langcode, url))
return property(fget=fget, fset=fset)
def add_dictionary_website(self): def add_dictionary_website(self):
class AD(QDialog): class AD(QDialog):

View File

@ -430,9 +430,8 @@ class Document(QWebPage): # {{{
def xpos(self): def xpos(self):
return self.mainFrame().scrollPosition().x() return self.mainFrame().scrollPosition().x()
@dynamic_property @property
def scroll_fraction(self): def scroll_fraction(self):
def fget(self):
if self.in_paged_mode: if self.in_paged_mode:
return self.javascript(''' return self.javascript('''
ans = 0.0; ans = 0.0;
@ -446,7 +445,8 @@ class Document(QWebPage): # {{{
except ZeroDivisionError: except ZeroDivisionError:
return 0. return 0.
def fset(self, val): @scroll_fraction.setter
def scroll_fraction(self, val):
if self.in_paged_mode and self.loaded_javascript: if self.in_paged_mode and self.loaded_javascript:
self.javascript('paged_display.scroll_to_pos(%f)'%val) self.javascript('paged_display.scroll_to_pos(%f)'%val)
else: else:
@ -454,22 +454,19 @@ class Document(QWebPage): # {{{
if npos < 0: if npos < 0:
npos = 0 npos = 0
self.scroll_to(x=self.xpos, y=npos) self.scroll_to(x=self.xpos, y=npos)
return property(fget=fget, fset=fset)
@dynamic_property @property
def page_number(self): def page_number(self):
' The page number is the number of the page at the left most edge of the screen (starting from 0) ' ' The page number is the number of the page at the left most edge of the screen (starting from 0) '
def fget(self):
if self.in_paged_mode: if self.in_paged_mode:
return self.javascript( return self.javascript(
'ans = 0; if (window.paged_display) ans = window.paged_display.column_boundaries()[0]; ans;', typ='int') 'ans = 0; if (window.paged_display) ans = window.paged_display.column_boundaries()[0]; ans;', typ='int')
def fset(self, val): @page_number.setter
def page_number(self, val):
if self.in_paged_mode and self.loaded_javascript: if self.in_paged_mode and self.loaded_javascript:
self.javascript('if (window.paged_display) window.paged_display.scroll_to_column(%d)' % int(val)) self.javascript('if (window.paged_display) window.paged_display.scroll_to_column(%d)' % int(val))
return True return True
return property(fget=fget, fset=fset)
@property @property
def page_dimensions(self): def page_dimensions(self):
@ -862,14 +859,13 @@ class DocumentView(QWebView): # {{{
def sizeHint(self): def sizeHint(self):
return self._size_hint return self._size_hint
@dynamic_property @property
def scroll_fraction(self): def scroll_fraction(self):
def fget(self):
return self.document.scroll_fraction return self.document.scroll_fraction
def fset(self, val): @scroll_fraction.setter
def scroll_fraction(self, val):
self.document.scroll_fraction = float(val) self.document.scroll_fraction = float(val)
return property(fget=fget, fset=fset)
@property @property
def hscroll_fraction(self): def hscroll_fraction(self):
@ -879,14 +875,13 @@ class DocumentView(QWebView): # {{{
def content_size(self): def content_size(self):
return self.document.width, self.document.height return self.document.width, self.document.height
@dynamic_property @property
def current_language(self): def current_language(self):
def fget(self):
return self.document.current_language return self.document.current_language
def fset(self, val): @current_language.setter
def current_language(self, val):
self.document.current_language = val self.document.current_language = val
return property(fget=fget, fset=fset)
def search(self, text, backwards=False): def search(self, text, backwards=False):
flags = self.document.FindBackward if backwards else self.document.FindFlags(0) flags = self.document.FindBackward if backwards else self.document.FindFlags(0)
@ -1189,19 +1184,18 @@ class DocumentView(QWebView): # {{{
if notify and self.manager is not None and new_pos != old_pos: if notify and self.manager is not None and new_pos != old_pos:
self.manager.scrolled(self.scroll_fraction) self.manager.scrolled(self.scroll_fraction)
@dynamic_property @property
def multiplier(self): def multiplier(self):
def fget(self):
return self.zoomFactor() return self.zoomFactor()
def fset(self, val): @multiplier.setter
def multiplier(self, val):
oval = self.zoomFactor() oval = self.zoomFactor()
self.setZoomFactor(val) self.setZoomFactor(val)
if val != oval: if val != oval:
if self.document.in_paged_mode: if self.document.in_paged_mode:
self.document.update_contents_size_for_paged_mode() self.document.update_contents_size_for_paged_mode()
self.magnification_changed.emit(val) self.magnification_changed.emit(val)
return property(fget=fget, fset=fset)
def magnify_fonts(self, amount=None): def magnify_fonts(self, amount=None):
if amount is None: if amount is None:

View File

@ -1131,14 +1131,14 @@ class Splitter(QSplitter):
print(self.save_name, 'side:', self.side_index_size, 'other:', end=' ') print(self.save_name, 'side:', self.side_index_size, 'other:', end=' ')
print(list(self.sizes())[self.other_index]) print(list(self.sizes())[self.other_index])
@dynamic_property @property
def side_index_size(self): def side_index_size(self):
def fget(self):
if self.count() < 2: if self.count() < 2:
return 0 return 0
return self.sizes()[self.side_index] return self.sizes()[self.side_index]
def fset(self, val): @side_index_size.setter
def side_index_size(self, val):
if self.count() < 2: if self.count() < 2:
return return
if val == 0 and not self.is_side_index_hidden: if val == 0 and not self.is_side_index_hidden:
@ -1154,8 +1154,6 @@ class Splitter(QSplitter):
self.setSizes(sizes) self.setSizes(sizes)
self.initialize() self.initialize()
return property(fget=fget, fset=fset)
def do_resize(self, *args): def do_resize(self, *args):
orig = self.desired_side_size orig = self.desired_side_size
QSplitter.resizeEvent(self, self._resize_ev) QSplitter.resizeEvent(self, self._resize_ev)

View File

@ -86,12 +86,12 @@ class ColorButton(QPushButton):
self.color = initial_color self.color = initial_color
self.clicked.connect(self.choose_color) self.clicked.connect(self.choose_color)
@dynamic_property @property
def color(self): def color(self):
def fget(self):
return self._color return self._color
def fset(self, val): @color.setter
def color(self, val):
val = unicode_type(val or '') val = unicode_type(val or '')
col = QColor(val) col = QColor(val)
orig = self._color orig = self._color
@ -107,7 +107,6 @@ class ColorButton(QPushButton):
self.setIcon(QIcon()) self.setIcon(QIcon())
if orig != col: if orig != col:
self.color_changed.emit(self._color) self.color_changed.emit(self._color)
return property(fget=fget, fset=fset)
def choose_color(self): def choose_color(self):
col = QColorDialog.getColor(QColor(self._color or Qt.white), self, _('Choose a color')) col = QColorDialog.getColor(QColor(self._color or Qt.white), self, _('Choose a color'))

View File

@ -827,13 +827,10 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
# _lock_file = None # _lock_file = None
self.conn.close() self.conn.close()
@dynamic_property @property
def user_version(self): def user_version(self):
doc = 'The user version of this database' 'The user version of this database'
def fget(self):
return self.conn.get('pragma user_version;', all=False) return self.conn.get('pragma user_version;', all=False)
return property(doc=doc, fget=fget)
def is_empty(self): def is_empty(self):
return not self.conn.get('SELECT id FROM books LIMIT 1', all=False) return not self.conn.get('SELECT id FROM books LIMIT 1', all=False)

View File

@ -75,25 +75,19 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
PATH_LIMIT = 40 if 'win32' in sys.platform else 100 PATH_LIMIT = 40 if 'win32' in sys.platform else 100
WINDOWS_LIBRARY_PATH_LIMIT = 75 WINDOWS_LIBRARY_PATH_LIMIT = 75
@dynamic_property @property
def user_version(self): def user_version(self):
doc = 'The user version of this database' 'The user version of this database'
def fget(self):
return self.conn.get('pragma user_version;', all=False) return self.conn.get('pragma user_version;', all=False)
def fset(self, val): @user_version.setter
def user_version(self, val):
self.conn.execute('pragma user_version=%d'%int(val)) self.conn.execute('pragma user_version=%d'%int(val))
self.conn.commit() self.conn.commit()
return property(doc=doc, fget=fget, fset=fset) @property
@dynamic_property
def library_id(self): def library_id(self):
doc = ('The UUID for this library. As long as the user only operates' '''The UUID for this library. As long as the user only operates on libraries with calibre, it will be unique'''
' on libraries with calibre, it will be unique')
def fget(self):
if self._library_id_ is None: if self._library_id_ is None:
ans = self.conn.get('SELECT uuid FROM library_id', all=False) ans = self.conn.get('SELECT uuid FROM library_id', all=False)
if ans is None: if ans is None:
@ -103,7 +97,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self._library_id_ = ans self._library_id_ = ans
return self._library_id_ return self._library_id_
def fset(self, val): @library_id.setter
def library_id(self, val):
self._library_id_ = unicode_type(val) self._library_id_ = unicode_type(val)
self.conn.executescript(''' self.conn.executescript('''
DELETE FROM library_id; DELETE FROM library_id;
@ -111,8 +106,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
'''%self._library_id_) '''%self._library_id_)
self.conn.commit() self.conn.commit()
return property(doc=doc, fget=fget, fset=fset)
def connect(self): def connect(self):
if iswindows and len(self.library_path) + 4*self.PATH_LIMIT + 10 > 259: if iswindows and len(self.library_path) + 4*self.PATH_LIMIT + 10 > 259:
raise ValueError(_( raise ValueError(_(

View File

@ -57,47 +57,43 @@ class Image(object):
def to_qimage(self): def to_qimage(self):
return clone_image(self.img) return clone_image(self.img)
@dynamic_property @property
def type(self): def type(self):
def fget(self):
if len(self.img.colorTable()) > 0: if len(self.img.colorTable()) > 0:
return 'PaletteType' return 'PaletteType'
return 'TrueColorType' return 'TrueColorType'
def fset(self, t): @type.setter
def type(self, t):
if t == 'GrayscaleType': if t == 'GrayscaleType':
self.img = grayscale_image(self.img) self.img = grayscale_image(self.img)
elif t == 'PaletteType': elif t == 'PaletteType':
self.img = quantize_image(self.img) self.img = quantize_image(self.img)
return property(fget=fget, fset=fset)
@dynamic_property @property
def format(self): def format(self):
def fget(self):
return self.write_format or self.read_format return self.write_format or self.read_format
def fset(self, val): @format.setter
def format(self, val):
self.write_format = val self.write_format = val
return property(fget=fget, fset=fset)
@dynamic_property @property
def colorspace(self): def colorspace(self):
def fget(self):
return 'RGBColorspace' return 'RGBColorspace'
def fset(self, val): @colorspace.setter
def colorspace(self, val):
raise NotImplementedError('Changing image colorspace is not supported') raise NotImplementedError('Changing image colorspace is not supported')
return property(fget=fget, fset=fset)
@dynamic_property @property
def size(self): def size(self):
def fget(self):
return self.img.width(), self.img.height() return self.img.width(), self.img.height()
def fset(self, val): @size.setter
def size(self, val):
w, h = val[:2] w, h = val[:2]
self.img = resize_image(self.img, w, h) self.img = resize_image(self.img, w, h)
return property(fget=fget, fset=fset)
def save(self, path, format=None): def save(self, path, format=None):
if format is None: if format is None:

View File

@ -57,32 +57,29 @@ class Article(object):
self.localtime = self.utctime.astimezone(local_tz) self.localtime = self.utctime.astimezone(local_tz)
self._formatted_date = None self._formatted_date = None
@dynamic_property @property
def formatted_date(self): def formatted_date(self):
def fget(self):
if self._formatted_date is None: if self._formatted_date is None:
self._formatted_date = strftime(" [%a, %d %b %H:%M]", self._formatted_date = strftime(" [%a, %d %b %H:%M]",
t=self.localtime.timetuple()) t=self.localtime.timetuple())
return self._formatted_date return self._formatted_date
def fset(self, val): @formatted_date.setter
def formatted_date(self, val):
if isinstance(val, unicode_type): if isinstance(val, unicode_type):
self._formatted_date = val self._formatted_date = val
return property(fget=fget, fset=fset) @property
@dynamic_property
def title(self): def title(self):
def fget(self):
t = self._title t = self._title
if not isinstance(t, unicode_type) and hasattr(t, 'decode'): if not isinstance(t, unicode_type) and hasattr(t, 'decode'):
t = t.decode('utf-8', 'replace') t = t.decode('utf-8', 'replace')
return t return t
def fset(self, val): @title.setter
def title(self, val):
self._title = clean_ascii_chars(val) self._title = clean_ascii_chars(val)
return property(fget=fget, fset=fset)
def __repr__(self): def __repr__(self):
return \ return \