Merge lp:~john-peterson/calibre/meta into lp:calibre

Proposed by John Peterson
Status: Needs review
Proposed branch: lp:~john-peterson/calibre/meta
Merge into: lp:calibre
Diff against target: 415 lines (+157/-40)
7 files modified
src/calibre/ebooks/metadata/sources/base.py (+4/-0)
src/calibre/gui2/actions/edit_metadata.py (+22/-13)
src/calibre/gui2/add.py (+37/-3)
src/calibre/gui2/metadata/bulk_download.py (+45/-15)
src/calibre/gui2/preferences/metadata_sources.py (+4/-0)
src/calibre/gui2/preferences/metadata_sources.ui (+37/-9)
src/calibre/library/database2.py (+8/-0)
To merge this branch: bzr merge lp:~john-peterson/calibre/meta
Reviewer Review Type Date Requested Status
Kovid Goyal Disapprove
Review via email: mp+146039@code.launchpad.net
To post a comment you must log in.
Revision history for this message
John Peterson (john-peterson) wrote :
Revision history for this message
Kovid Goyal (kovid) wrote :

Since you still insist on using github for comments and from your general tone, I conclude that dealing with you is more trouble than it is worth. I will not be accepting any patches from you in the future, so dont bother submitting any.

review: Disapprove
Revision history for this message
John Peterson (john-peterson) wrote :

Unmerged revisions

14248. By John Peterson

Adding option to auto add metadata on import

Coordinating add actions so that convert waits for metadata adding

Narrowing the metadata download modification check to avoid checking for changes in custom metadata (which is not downloaded or overwritten)

Adding option to clear IDs before metadata download (to obtain the default edition)

Adding option to not confirm before updating metadata in library

14247. By John Peterson

Adding postimport plugin call to manual add

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/calibre/ebooks/metadata/sources/base.py'
2--- src/calibre/ebooks/metadata/sources/base.py 2013-01-31 15:49:28 +0000
3+++ src/calibre/ebooks/metadata/sources/base.py 2013-02-01 04:56:24 +0000
4@@ -18,6 +18,10 @@
5 from calibre.ebooks.metadata import check_isbn
6
7 msprefs = JSONConfig('metadata_sources/global.json')
8+msprefs.defaults['confirm'] = True
9+msprefs.defaults['auto_add'] = False
10+msprefs.defaults['auto_overwrite'] = False
11+msprefs.defaults['auto_clear'] = False
12 msprefs.defaults['txt_comments'] = False
13 msprefs.defaults['ignore_fields'] = []
14 msprefs.defaults['user_default_ignore_fields'] = []
15
16=== modified file 'src/calibre/gui2/actions/edit_metadata.py'
17--- src/calibre/gui2/actions/edit_metadata.py 2012-10-05 06:00:02 +0000
18+++ src/calibre/gui2/actions/edit_metadata.py 2013-02-01 04:56:24 +0000
19@@ -67,18 +67,18 @@
20 self.action_merge.setEnabled(enabled)
21
22 # Download metadata {{{
23- def download_metadata(self, ids=None, ensure_fields=None):
24+ def download_metadata(self, ids=None, ensure_fields=None, confirm=True, clear=False, identify=True, covers=True, callback_done=None):
25+ db = self.gui.library_view.model().db
26 if ids is None:
27 rows = self.gui.library_view.selectionModel().selectedRows()
28 if not rows or len(rows) == 0:
29 return error_dialog(self.gui, _('Cannot download metadata'),
30 _('No books selected'), show=True)
31- db = self.gui.library_view.model().db
32 ids = [db.id(row.row()) for row in rows]
33 from calibre.gui2.metadata.bulk_download import start_download
34 start_download(self.gui, ids,
35 Dispatcher(self.metadata_downloaded),
36- ensure_fields=ensure_fields)
37+ ensure_fields=ensure_fields, confirm=confirm, clear=clear, identify=identify, covers=covers, callback_done=callback_done)
38
39 def cleanup_bulk_download(self, tdir, *args):
40 try:
41@@ -87,6 +87,11 @@
42 pass
43
44 def metadata_downloaded(self, job):
45+ self._metadata_downloaded(job)
46+ if job.callback_done:
47+ job.callback_done()
48+
49+ def _metadata_downloaded(self, job):
50 if job.failed:
51 self.gui.job_exception(job, dialog_title=_('Failed to download metadata'))
52 return
53@@ -118,16 +123,21 @@
54 'after updating metadata')
55
56 payload = (id_map, tdir, log_file, lm_map,
57- failed_ids.union(failed_covers))
58- self.gui.proceed_question(self.apply_downloaded_metadata, payload,
59- log_file, _('Download log'), _('Download complete'), msg,
60- det_msg=det_msg, show_copy_button=show_copy_button,
61- cancel_callback=partial(self.cleanup_bulk_download, tdir),
62- log_is_file=True, checkbox_msg=checkbox_msg,
63- checkbox_checked=False)
64+ failed_ids.union(failed_covers), job.old_metadata)
65+
66+ from calibre.ebooks.metadata.sources.base import msprefs
67+ if msprefs['confirm']:
68+ self.gui.proceed_question(self.apply_downloaded_metadata, payload,
69+ log_file, _('Download log'), _('Download complete'), msg,
70+ det_msg=det_msg, show_copy_button=show_copy_button,
71+ cancel_callback=partial(self.cleanup_bulk_download, tdir),
72+ log_is_file=True, checkbox_msg=checkbox_msg,
73+ checkbox_checked=False)
74+ else:
75+ self.apply_downloaded_metadata(payload)
76
77 def apply_downloaded_metadata(self, payload, *args):
78- good_ids, tdir, log_file, lm_map, failed_ids = payload
79+ good_ids, tdir, log_file, lm_map, failed_ids, old_metadata = payload
80 if not good_ids:
81 return
82
83@@ -135,8 +145,7 @@
84 db = self.gui.current_db
85
86 for i in good_ids:
87- lm = db.metadata_last_modified(i, index_is_id=True)
88- if lm is not None and lm_map[i] is not None and lm > lm_map[i]:
89+ if db.check_if_standard_metadata_modified(i, index_is_id=True, other=old_metadata[i]):
90 title = db.title(i, index_is_id=True)
91 authors = db.authors(i, index_is_id=True)
92 if authors:
93
94=== modified file 'src/calibre/gui2/add.py'
95--- src/calibre/gui2/add.py 2013-01-06 08:22:38 +0000
96+++ src/calibre/gui2/add.py 2013-02-01 04:56:24 +0000
97@@ -9,7 +9,7 @@
98
99 from calibre.gui2.dialogs.progress import ProgressDialog
100 from calibre.gui2 import (error_dialog, info_dialog, gprefs,
101- warning_dialog, available_width)
102+ warning_dialog, available_width, Dispatcher)
103 from calibre.ebooks.metadata.opf2 import OPF
104 from calibre.ebooks.metadata import MetaInformation
105 from calibre.constants import preferred_encoding, filesystem_encoding, DEBUG
106@@ -111,15 +111,49 @@
107 self.auto_convert_books = set()
108
109 def end(self):
110+ from calibre.ebooks.metadata.sources.base import msprefs
111+ callback_done = None
112+ ids_add_metadata = set()
113+
114+ # check if metadata should be added
115+ if msprefs['auto_overwrite'] or msprefs['auto_clear']:
116+ ids_add_metadata = self.auto_convert_books
117+ dl_identify = True
118+ dl_covers = True
119+
120+ if msprefs['auto_add'] and not (msprefs['auto_overwrite'] or msprefs['auto_clear']):
121+ dl_identify = False
122+ dl_covers = False
123+ for id in self.auto_convert_books:
124+ mi = self.db.get_metadata(id, index_is_id=True, get_cover=True)
125+ missing_identify = bool(not (mi and mi.isbn and mi.pubdate and mi.comments))
126+ missing_cover = bool(not (mi and mi.cover))
127+ if missing_identify: dl_identify = True
128+ if missing_cover: dl_covers = True
129+ if missing_identify or missing_cover:
130+ ids_add_metadata.add(id)
131+
132+ # auto convert now or after metadata is added
133 if (gprefs['manual_add_auto_convert'] and
134 self.auto_convert_books):
135+ if ids_add_metadata:
136+ callback_done = Dispatcher(self.auto_convert)
137+ else:
138+ self.auto_convert()
139+
140+ if ids_add_metadata:
141 from calibre.gui2.ui import get_gui
142 gui = get_gui()
143- gui.iactions['Convert Books'].auto_convert_auto_add(
144- self.auto_convert_books)
145+ gui.iactions['Edit Metadata'].download_metadata(ids_add_metadata, confirm=False, clear=msprefs['auto_clear'], identify=dl_identify, covers=dl_covers, callback_done=callback_done)
146
147 self.input_queue.put((None, None, None))
148
149+ def auto_convert(self):
150+ from calibre.gui2.ui import get_gui
151+ gui = get_gui()
152+ gui.iactions['Convert Books'].auto_convert_auto_add(
153+ self.auto_convert_books)
154+
155 def start(self):
156 try:
157 id, opf, cover = self.input_queue.get_nowait()
158
159=== modified file 'src/calibre/gui2/metadata/bulk_download.py'
160--- src/calibre/gui2/metadata/bulk_download.py 2012-04-12 09:50:24 +0000
161+++ src/calibre/gui2/metadata/bulk_download.py 2013-02-01 04:56:24 +0000
162@@ -77,8 +77,8 @@
163 l.setColumnStretch(1, 100)
164
165 self.identify = self.covers = True
166- self.bb = QDialogButtonBox(QDialogButtonBox.Cancel)
167- self.bb.rejected.connect(self.reject)
168+ self.clear = False
169+ self.bb = QDialogButtonBox()
170 b = self.bb.addButton(_('Download only &metadata'),
171 self.bb.AcceptRole)
172 b.clicked.connect(self.only_metadata)
173@@ -87,20 +87,36 @@
174 self.bb.AcceptRole)
175 b.clicked.connect(self.only_covers)
176 b.setIcon(QIcon(I('default_cover.png')))
177- b = self.b = self.bb.addButton(_('&Configure download'), self.bb.ActionRole)
178- b.setIcon(QIcon(I('config.png')))
179- b.clicked.connect(partial(show_config, parent, self))
180- l.addWidget(self.bb, 1, 0, 1, 2)
181- b = self.bb.addButton(_('Download &both'),
182- self.bb.AcceptRole)
183+
184+ self.bb2 = QDialogButtonBox()
185+ b = self.bb2.addButton(_('Download &both'),
186+ self.bb2.AcceptRole)
187 b.clicked.connect(self.accept)
188 b.setDefault(True)
189 b.setAutoDefault(True)
190 b.setIcon(QIcon(I('ok.png')))
191+ b = self.bb2.addButton(_('Clear &IDs and download both'),
192+ self.bb2.AcceptRole)
193+ b.clicked.connect(self.clear_ids)
194+ b.setIcon(QIcon(I('trash.png')))
195
196+ self.bb3 = QDialogButtonBox(QDialogButtonBox.Cancel)
197+ self.bb3.rejected.connect(self.reject)
198+ b = self.b = self.bb3.addButton(_('&Configure download'), self.bb3.ActionRole)
199+ b.setIcon(QIcon(I('config.png')))
200+ b.clicked.connect(partial(show_config, parent, self))
201+
202+ l.addWidget(self.bb, 1, 0, 1, 2, Qt.AlignHCenter)
203+ l.addWidget(self.bb2, 2, 0, 1, 2, Qt.AlignHCenter)
204+ l.addWidget(self.bb3, 3, 0, 1, 2, Qt.AlignHCenter)
205+
206 self.resize(self.sizeHint())
207 b.setFocus(Qt.OtherFocusReason)
208
209+ def clear_ids(self):
210+ self.clear = True
211+ self.accept()
212+
213 def only_metadata(self):
214 self.covers = False
215 self.accept()
216@@ -118,20 +134,34 @@
217 ids = ids[batch_size:]
218 return ans
219
220-def start_download(gui, ids, callback, ensure_fields=None):
221- d = ConfirmDialog(ids, gui)
222- ret = d.exec_()
223- d.b.clicked.disconnect()
224- if ret != d.Accepted:
225- return
226+def start_download(gui, ids, callback, ensure_fields=None, confirm=True, clear=False, identify=True, covers=True, callback_done=None):
227+ if confirm:
228+ d = ConfirmDialog(ids, gui)
229+ ret = d.exec_()
230+ d.b.clicked.disconnect()
231+ if ret != d.Accepted:
232+ return
233+ identify = d.identify
234+ covers = d.covers
235+ clear = d.clear
236 tf = PersistentTemporaryFile('_metadata_bulk.log')
237 tf.close()
238
239+ # clear ids
240+ if clear:
241+ for id in ids:
242+ gui.current_db.clear_identifiers(id)
243+
244 job = Job('metadata bulk download',
245 _('Download metadata for %d books')%len(ids),
246- download, (ids, tf.name, gui.current_db, d.identify, d.covers,
247+ download, (ids, tf.name, gui.current_db, identify, covers,
248 ensure_fields), {}, callback)
249 job.download_debug_log = tf.name
250+ job.callback_done = callback_done
251+ # save current metadata for modification check
252+ job.old_metadata = {}
253+ for id in ids:
254+ job.old_metadata[id] = gui.current_db.get_metadata(id, index_is_id=True, get_cover=False)
255 gui.job_manager.run_threaded_job(job)
256 gui.status_bar.show_message(_('Metadata download started'), 3000)
257
258
259=== modified file 'src/calibre/gui2/preferences/metadata_sources.py'
260--- src/calibre/gui2/preferences/metadata_sources.py 2012-10-06 07:32:50 +0000
261+++ src/calibre/gui2/preferences/metadata_sources.py 2013-02-01 04:56:24 +0000
262@@ -290,6 +290,10 @@
263
264 def genesis(self, gui):
265 r = self.register
266+ r('confirm', msprefs)
267+ r('auto_add', msprefs)
268+ r('auto_overwrite', msprefs)
269+ r('auto_clear', msprefs)
270 r('txt_comments', msprefs)
271 r('max_tags', msprefs)
272 r('wait_after_first_identify_result', msprefs)
273
274=== modified file 'src/calibre/gui2/preferences/metadata_sources.ui'
275--- src/calibre/gui2/preferences/metadata_sources.ui 2012-10-06 07:45:50 +0000
276+++ src/calibre/gui2/preferences/metadata_sources.ui 2013-02-01 04:56:24 +0000
277@@ -126,20 +126,48 @@
278 </widget>
279 </item>
280 <item row="1" column="1" colspan="2">
281+ <widget class="QCheckBox" name="opt_confirm">
282+ <property name="text">
283+ <string>Confirm before updating metadata in library</string>
284+ </property>
285+ </widget>
286+ </item>
287+ <item row="2" column="1" colspan="2">
288+ <widget class="QCheckBox" name="opt_auto_add">
289+ <property name="text">
290+ <string>Automatically add missing metadata on import</string>
291+ </property>
292+ </widget>
293+ </item>
294+ <item row="3" column="1" colspan="2">
295+ <widget class="QCheckBox" name="opt_auto_overwrite">
296+ <property name="text">
297+ <string>Automatically overwrite metadata on import</string>
298+ </property>
299+ </widget>
300+ </item>
301+ <item row="4" column="1" colspan="2">
302+ <widget class="QCheckBox" name="opt_auto_clear">
303+ <property name="text">
304+ <string>Automatically clear IDs and overwrite metadata on import</string>
305+ </property>
306+ </widget>
307+ </item>
308+ <item row="5" column="1" colspan="2">
309 <widget class="QCheckBox" name="opt_txt_comments">
310 <property name="text">
311 <string>Convert all downloaded comments to plain &amp;text</string>
312 </property>
313 </widget>
314 </item>
315- <item row="2" column="1" colspan="2">
316+ <item row="6" column="1" colspan="2">
317 <widget class="QCheckBox" name="opt_swap_author_names">
318 <property name="text">
319 <string>Swap author names from FN LN to LN, FN</string>
320 </property>
321 </widget>
322 </item>
323- <item row="5" column="1">
324+ <item row="9" column="1">
325 <widget class="QLabel" name="label_2">
326 <property name="text">
327 <string>Max. number of &amp;tags to download:</string>
328@@ -149,10 +177,10 @@
329 </property>
330 </widget>
331 </item>
332- <item row="5" column="2">
333+ <item row="9" column="2">
334 <widget class="QSpinBox" name="opt_max_tags"/>
335 </item>
336- <item row="6" column="1">
337+ <item row="10" column="1">
338 <widget class="QLabel" name="label_3">
339 <property name="text">
340 <string>Max. &amp;time to wait after first match is found:</string>
341@@ -162,14 +190,14 @@
342 </property>
343 </widget>
344 </item>
345- <item row="6" column="2">
346+ <item row="10" column="2">
347 <widget class="QSpinBox" name="opt_wait_after_first_identify_result">
348 <property name="suffix">
349 <string> secs</string>
350 </property>
351 </widget>
352 </item>
353- <item row="7" column="1">
354+ <item row="11" column="1">
355 <widget class="QLabel" name="label_4">
356 <property name="text">
357 <string>Max. time to wait after first &amp;cover is found:</string>
358@@ -179,14 +207,14 @@
359 </property>
360 </widget>
361 </item>
362- <item row="7" column="2">
363+ <item row="11" column="2">
364 <widget class="QSpinBox" name="opt_wait_after_first_cover_result">
365 <property name="suffix">
366 <string> secs</string>
367 </property>
368 </widget>
369 </item>
370- <item row="4" column="1" colspan="2">
371+ <item row="8" column="1" colspan="2">
372 <widget class="QCheckBox" name="opt_fewer_tags">
373 <property name="toolTip">
374 <string>&lt;p&gt;Different metadata sources have different sets of tags for the same book. If this option is checked, then calibre will use the smaller tag sets. These tend to be more like genres, while the larger tag sets tend to describe the books content.
375@@ -197,7 +225,7 @@
376 </property>
377 </widget>
378 </item>
379- <item row="3" column="1" colspan="2">
380+ <item row="7" column="1" colspan="2">
381 <widget class="QCheckBox" name="opt_find_first_edition_date">
382 <property name="text">
383 <string>Use published date of &quot;first edition&quot; (from worldcat.org)</string>
384
385=== modified file 'src/calibre/library/database2.py'
386--- src/calibre/library/database2.py 2013-01-29 06:26:38 +0000
387+++ src/calibre/library/database2.py 2013-02-01 04:56:24 +0000
388@@ -532,6 +532,10 @@
389 self.refresh()
390 self.refresh_format_cache()
391 self.last_update_check = utcnow()
392+
393+ def check_if_standard_metadata_modified(self, index, index_is_id, other):
394+ mi = self.get_metadata(index, index_is_id=index_is_id, get_cover=False)
395+ return mi.get_all_standard_metadata(True) != other.get_all_standard_metadata(True)
396
397 def path(self, index, index_is_id=False):
398 'Return the relative path to the directory containing this books files as a unicode string.'
399@@ -1504,6 +1508,7 @@
400 self.refresh_ids([id])
401 if notify:
402 self.notify('metadata', [id])
403+ run_plugins_on_postimport(self, id, format)
404 return True
405
406 def save_original_format(self, book_id, fmt, notify=True):
407@@ -3296,6 +3301,9 @@
408 if notify:
409 self.notify('metadata', [id_])
410
411+ def clear_identifiers(self, id_):
412+ self.set_identifiers(id_, {})
413+
414 def set_isbn(self, id_, isbn, notify=True, commit=True):
415 self.set_identifier(id_, 'isbn', isbn, notify=notify, commit=commit)
416

Subscribers

People subscribed via source and target branches