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