From 1cd78a56f29c110fb8601ab9ba63f3283f6828e7 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sun, 26 Sep 2010 17:31:39 +0100
Subject: [PATCH 1/4] Fix problem where :0>3s produced a string of all zeros
for null fields. Add a confirmation dialog to the backup pushbutton
---
src/calibre/gui2/preferences/misc.py | 3 +++
src/calibre/gui2/preferences/misc.ui | 2 +-
src/calibre/library/caches.py | 1 +
src/calibre/utils/formatter.py | 2 +-
4 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/calibre/gui2/preferences/misc.py b/src/calibre/gui2/preferences/misc.py
index e749a6fb98..e72a1921ef 100644
--- a/src/calibre/gui2/preferences/misc.py
+++ b/src/calibre/gui2/preferences/misc.py
@@ -97,6 +97,9 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
db = self.gui.library_view.model().db
ids = [id for id in db.data.iterallids()]
db.dirtied(ids)
+ info_dialog(self, _('Backup metadata'),
+ _('Metadata will be backed up while calibre is running, at the '
+ 'rate of 30 books per minute.'), show=True)
def debug_device_detection(self, *args):
from calibre.gui2.preferences.device_debug import DebugDevice
diff --git a/src/calibre/gui2/preferences/misc.ui b/src/calibre/gui2/preferences/misc.ui
index 492540901d..adf2a15c16 100644
--- a/src/calibre/gui2/preferences/misc.ui
+++ b/src/calibre/gui2/preferences/misc.ui
@@ -127,7 +127,7 @@
-
- Back up metadata of all books (while you are working)
+ Back up metadata of all books
diff --git a/src/calibre/library/caches.py b/src/calibre/library/caches.py
index 9d6f87324f..3e7f4d85ee 100644
--- a/src/calibre/library/caches.py
+++ b/src/calibre/library/caches.py
@@ -75,6 +75,7 @@ class MetadataBackup(Thread): # {{{
# Give the GUI thread a chance to do something. Python threads don't
# have priorities, so this thread would naturally keep the processor
# until some scheduling event happens. The sleep makes such an event
+ print 'do one'
time.sleep(0.1)
try:
raw = metadata_to_opf(mi)
diff --git a/src/calibre/utils/formatter.py b/src/calibre/utils/formatter.py
index 6fed4e157a..f95a6deee5 100644
--- a/src/calibre/utils/formatter.py
+++ b/src/calibre/utils/formatter.py
@@ -100,7 +100,7 @@ class TemplateFormatter(string.Formatter):
val = func[1](self, val)
else:
val = func[1](self, val, *args)
- else:
+ elif val:
val = string.Formatter.format_field(self, val, fmt)
if not val:
return ''
From a05448f7844d9f6f0730a4354b6c6e70dc8020ed Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sun, 26 Sep 2010 17:49:52 +0100
Subject: [PATCH 2/4] Fix stupid mistake in method naming in base.py
---
src/calibre/ebooks/metadata/book/base.py | 21 +++++++--------------
src/calibre/gui2/library/models.py | 2 +-
2 files changed, 8 insertions(+), 15 deletions(-)
diff --git a/src/calibre/ebooks/metadata/book/base.py b/src/calibre/ebooks/metadata/book/base.py
index 0526de96a0..bdf11ad4ba 100644
--- a/src/calibre/ebooks/metadata/book/base.py
+++ b/src/calibre/ebooks/metadata/book/base.py
@@ -181,17 +181,10 @@ class Metadata(object):
'''
return metadata describing a standard or custom field.
'''
- if key in self.user_metadata_keys():
+ if key not in self.custom_field_keys():
return self.get_standard_metadata(self, key, make_copy=False)
return self.get_user_metadata(key, make_copy=False)
- def user_metadata_keys(self):
- '''
- Return the standard keys actually in this book.
- '''
- _data = object.__getattribute__(self, '_data')
- return frozenset(_data['user_metadata'].iterkeys())
-
def all_non_none_fields(self):
'''
Return a dictionary containing all non-None metadata fields, including
@@ -305,7 +298,7 @@ class Metadata(object):
def print_all_attributes(self):
for x in STANDARD_METADATA_FIELDS:
prints('%s:'%x, getattr(self, x, 'None'))
- for x in self.user_metadata_keys():
+ for x in self.custom_field_keys():
meta = self.get_user_metadata(x, make_copy=False)
if meta is not None:
prints(x, meta)
@@ -370,8 +363,8 @@ class Metadata(object):
if len(other_cover) > len(self_cover):
self.cover_data = other.cover_data
- if getattr(other, 'user_metadata_keys', None):
- for x in other.user_metadata_keys():
+ if getattr(other, 'custom_field_keys', None):
+ for x in other.custom_field_keys():
meta = other.get_user_metadata(x, make_copy=True)
if meta is not None:
self_tags = self.get(x, [])
@@ -434,7 +427,7 @@ class Metadata(object):
'''
returns the tuple (field_name, formatted_value)
'''
- if key in self.user_metadata_keys():
+ if key in self.custom_field_keys():
res = self.get(key, None)
cmeta = self.get_user_metadata(key, make_copy=False)
name = unicode(cmeta['name'])
@@ -516,7 +509,7 @@ class Metadata(object):
fmt('Published', isoformat(self.pubdate))
if self.rights is not None:
fmt('Rights', unicode(self.rights))
- for key in self.user_metadata_keys():
+ for key in self.custom_field_keys():
val = self.get(key, None)
if val:
(name, val) = self.format_field(key)
@@ -541,7 +534,7 @@ class Metadata(object):
ans += [(_('Published'), unicode(self.pubdate.isoformat(' ')))]
if self.rights is not None:
ans += [(_('Rights'), unicode(self.rights))]
- for key in self.user_metadata_keys():
+ for key in self.custom_field_keys():
val = self.get(key, None)
if val:
(name, val) = self.format_field(key)
diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py
index ff6d8b70f0..6725989ee5 100644
--- a/src/calibre/gui2/library/models.py
+++ b/src/calibre/gui2/library/models.py
@@ -331,7 +331,7 @@ class BooksModel(QAbstractTableModel): # {{{
_('Book %s of %s.')%\
(sidx, prepare_string_for_xml(series))
mi = self.db.get_metadata(idx)
- for key in mi.user_metadata_keys():
+ for key in mi.custom_field_keys():
name, val = mi.format_field(key)
if val:
data[name] = val
From 10f9af93a9e2ec28938a2d855fc01247ab129960 Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sun, 26 Sep 2010 18:18:45 +0100
Subject: [PATCH 3/4] Fix restoring custom column definitions
---
src/calibre/library/caches.py | 1 -
src/calibre/library/restore.py | 38 ++++++++++++++++++++--------------
2 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/src/calibre/library/caches.py b/src/calibre/library/caches.py
index 3e7f4d85ee..9d6f87324f 100644
--- a/src/calibre/library/caches.py
+++ b/src/calibre/library/caches.py
@@ -75,7 +75,6 @@ class MetadataBackup(Thread): # {{{
# Give the GUI thread a chance to do something. Python threads don't
# have priorities, so this thread would naturally keep the processor
# until some scheduling event happens. The sleep makes such an event
- print 'do one'
time.sleep(0.1)
try:
raw = metadata_to_opf(mi)
diff --git a/src/calibre/library/restore.py b/src/calibre/library/restore.py
index 89c7fe8395..d34e831fc7 100644
--- a/src/calibre/library/restore.py
+++ b/src/calibre/library/restore.py
@@ -145,25 +145,33 @@ class Restore(Thread):
def create_cc_metadata(self):
self.books.sort(key=itemgetter('timestamp'))
m = {}
- fields = ('label', 'name', 'datatype', 'is_multiple', 'editable',
+ fields = ('label', 'name', 'datatype', 'is_multiple', 'is_editable',
'display')
for b in self.books:
- args = []
- for x in fields:
- if x in b:
- args.append(b[x])
- if len(args) == len(fields):
- # TODO: Do series type columns need special handling?
- label = b['label']
- if label in m and args != m[label]:
- if label not in self.conflicting_custom_cols:
- self.conflicting_custom_cols[label] = set([m[label]])
- self.conflicting_custom_cols[label].add(args)
- m[b['label']] = args
+ for key in b['mi'].custom_field_keys():
+ cfm = b['mi'].metadata_for_field(key)
+ args = []
+ for x in fields:
+ if x in cfm:
+ if x == 'is_multiple':
+ args.append(cfm[x] is not None)
+ else:
+ args.append(cfm[x])
+ if len(args) == len(fields):
+ # TODO: Do series type columns need special handling?
+ label = cfm['label']
+ if label in m and args != m[label]:
+ if label not in self.conflicting_custom_cols:
+ self.conflicting_custom_cols[label] = set([m[label]])
+ self.conflicting_custom_cols[label].add(args)
+ m[cfm['label']] = args
db = RestoreDatabase(self.library_path)
- for args in m.values():
- db.create_custom_column(*args)
+ self.progress_callback(None, len(m))
+ if len(m):
+ for i,args in enumerate(m.values()):
+ db.create_custom_column(*args)
+ self.progress_callback(_('creating custom column ')+args[0], i+1)
db.conn.close()
def restore_books(self):
From 4f522bde37cffedc184f4ff1f70b8b56aed1962d Mon Sep 17 00:00:00 2001
From: Charles Haley <>
Date: Sun, 26 Sep 2010 18:25:45 +0100
Subject: [PATCH 4/4] Add dialog box back to the backup button
---
src/calibre/gui2/preferences/misc.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/calibre/gui2/preferences/misc.py b/src/calibre/gui2/preferences/misc.py
index 37887d56dc..99080c63bc 100644
--- a/src/calibre/gui2/preferences/misc.py
+++ b/src/calibre/gui2/preferences/misc.py
@@ -96,6 +96,9 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
def mark_dirty(self):
db = self.gui.library_view.model().db
db.dirtied(list(db.data.iterallids()))
+ info_dialog(self, _('Backup metadata'),
+ _('Metadata will be backed up while calibre is running, at the '
+ 'rate of 30 books per minute.'), show=True)
def debug_device_detection(self, *args):
from calibre.gui2.preferences.device_debug import DebugDevice