mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
ff7d60db91
@ -102,7 +102,7 @@ class MyBlockingBusy(QDialog):
|
|||||||
remove_all, remove, add, au, aus, do_aus, rating, pub, do_series, \
|
remove_all, remove, add, au, aus, do_aus, rating, pub, do_series, \
|
||||||
do_autonumber, do_remove_format, remove_format, do_swap_ta, \
|
do_autonumber, do_remove_format, remove_format, do_swap_ta, \
|
||||||
do_remove_conv, do_auto_author, series, do_series_restart, \
|
do_remove_conv, do_auto_author, series, do_series_restart, \
|
||||||
series_start_value, do_title_case, clear_series = self.args
|
series_start_value, do_title_case, cover_action, clear_series = self.args
|
||||||
|
|
||||||
|
|
||||||
# first loop: do author and title. These will commit at the end of each
|
# first loop: do author and title. These will commit at the end of each
|
||||||
@ -129,6 +129,23 @@ class MyBlockingBusy(QDialog):
|
|||||||
self.db.set_title(id, titlecase(title), notify=False)
|
self.db.set_title(id, titlecase(title), notify=False)
|
||||||
if au:
|
if au:
|
||||||
self.db.set_authors(id, string_to_authors(au), notify=False)
|
self.db.set_authors(id, string_to_authors(au), notify=False)
|
||||||
|
if cover_action == 'remove':
|
||||||
|
self.db.remove_cover(id)
|
||||||
|
elif cover_action == 'generate':
|
||||||
|
from calibre.ebooks import calibre_cover
|
||||||
|
from calibre.ebooks.metadata import fmt_sidx
|
||||||
|
from calibre.gui2 import config
|
||||||
|
mi = self.db.get_metadata(id, index_is_id=True)
|
||||||
|
series_string = None
|
||||||
|
if mi.series:
|
||||||
|
series_string = _('Book %s of %s')%(
|
||||||
|
fmt_sidx(mi.series_index,
|
||||||
|
use_roman=config['use_roman_numerals_for_series_number']),
|
||||||
|
mi.series)
|
||||||
|
|
||||||
|
cdata = calibre_cover(mi.title, mi.format_field('authors')[-1],
|
||||||
|
series_string=series_string)
|
||||||
|
self.db.set_cover(id, cdata)
|
||||||
elif self.current_phase == 2:
|
elif self.current_phase == 2:
|
||||||
# All of these just affect the DB, so we can tolerate a total rollback
|
# All of these just affect the DB, so we can tolerate a total rollback
|
||||||
if do_auto_author:
|
if do_auto_author:
|
||||||
@ -678,11 +695,16 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog):
|
|||||||
do_remove_conv = self.remove_conversion_settings.isChecked()
|
do_remove_conv = self.remove_conversion_settings.isChecked()
|
||||||
do_auto_author = self.auto_author_sort.isChecked()
|
do_auto_author = self.auto_author_sort.isChecked()
|
||||||
do_title_case = self.change_title_to_title_case.isChecked()
|
do_title_case = self.change_title_to_title_case.isChecked()
|
||||||
|
cover_action = None
|
||||||
|
if self.cover_remove.isChecked():
|
||||||
|
cover_action = 'remove'
|
||||||
|
elif self.cover_generate.isChecked():
|
||||||
|
cover_action = 'generate'
|
||||||
|
|
||||||
args = (remove_all, remove, add, au, aus, do_aus, rating, pub, do_series,
|
args = (remove_all, remove, add, au, aus, do_aus, rating, pub, do_series,
|
||||||
do_autonumber, do_remove_format, remove_format, do_swap_ta,
|
do_autonumber, do_remove_format, remove_format, do_swap_ta,
|
||||||
do_remove_conv, do_auto_author, series, do_series_restart,
|
do_remove_conv, do_auto_author, series, do_series_restart,
|
||||||
series_start_value, do_title_case, clear_series)
|
series_start_value, do_title_case, cover_action, clear_series)
|
||||||
|
|
||||||
bb = MyBlockingBusy(_('Applying changes to %d books.\nPhase {0} {1}%%.')
|
bb = MyBlockingBusy(_('Applying changes to %d books.\nPhase {0} {1}%%.')
|
||||||
%len(self.ids), args, self.db, self.ids,
|
%len(self.ids), args, self.db, self.ids,
|
||||||
|
@ -381,7 +381,7 @@ Future conversion of these books will use the default settings.</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="15" column="0" colspan="3">
|
<item row="14" column="0" colspan="3">
|
||||||
<spacer name="verticalSpacer_2">
|
<spacer name="verticalSpacer_2">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -394,6 +394,39 @@ Future conversion of these books will use the default settings.</string>
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="13" column="0" colspan="3">
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Change &cover</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="cover_no_change">
|
||||||
|
<property name="text">
|
||||||
|
<string>&No change</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="cover_remove">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Remove cover</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="cover_generate">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Generate default cover</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab">
|
<widget class="QWidget" name="tab">
|
||||||
|
@ -145,7 +145,7 @@ class TagCategories(QDialog, Ui_TagCategories):
|
|||||||
index = self.all_items[node.data(Qt.UserRole).toPyObject()].index
|
index = self.all_items[node.data(Qt.UserRole).toPyObject()].index
|
||||||
if index not in self.applied_items:
|
if index not in self.applied_items:
|
||||||
self.applied_items.append(index)
|
self.applied_items.append(index)
|
||||||
self.applied_items.sort(key=lambda x:sort_key(self.all_items[x]))
|
self.applied_items.sort(key=lambda x:sort_key(self.all_items[x].name))
|
||||||
self.display_filtered_categories(None)
|
self.display_filtered_categories(None)
|
||||||
|
|
||||||
def unapply_tags(self, node=None):
|
def unapply_tags(self, node=None):
|
||||||
|
@ -105,9 +105,13 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
|||||||
if not question_dialog(self, _('Are your sure?'),
|
if not question_dialog(self, _('Are your sure?'),
|
||||||
'<p>'+_('Are you certain you want to delete the following items?')+'<br>'+ct):
|
'<p>'+_('Are you certain you want to delete the following items?')+'<br>'+ct):
|
||||||
return
|
return
|
||||||
|
row = self.available_tags.row(deletes[0])
|
||||||
for item in deletes:
|
for item in deletes:
|
||||||
(id,ign) = item.data(Qt.UserRole).toInt()
|
(id,ign) = item.data(Qt.UserRole).toInt()
|
||||||
self.to_delete.append(id)
|
self.to_delete.append(id)
|
||||||
self.available_tags.takeItem(self.available_tags.row(item))
|
self.available_tags.takeItem(self.available_tags.row(item))
|
||||||
|
|
||||||
|
if row >= self.available_tags.count():
|
||||||
|
row = self.available_tags.count() - 1
|
||||||
|
if row >= 0:
|
||||||
|
self.available_tags.scrollToItem(self.available_tags.item(row))
|
||||||
|
@ -123,6 +123,8 @@ class Stack(QStackedWidget): # {{{
|
|||||||
_('Tag Browser'), I('tags.png'),
|
_('Tag Browser'), I('tags.png'),
|
||||||
parent=parent, side_index=0, initial_side_size=200,
|
parent=parent, side_index=0, initial_side_size=200,
|
||||||
shortcut=_('Shift+Alt+T'))
|
shortcut=_('Shift+Alt+T'))
|
||||||
|
parent.tb_splitter.state_changed.connect(
|
||||||
|
self.tb_widget.set_pane_is_visible, Qt.QueuedConnection)
|
||||||
parent.tb_splitter.addWidget(self.tb_widget)
|
parent.tb_splitter.addWidget(self.tb_widget)
|
||||||
parent.tb_splitter.addWidget(parent.cb_splitter)
|
parent.tb_splitter.addWidget(parent.cb_splitter)
|
||||||
parent.tb_splitter.setCollapsible(parent.tb_splitter.other_index, False)
|
parent.tb_splitter.setCollapsible(parent.tb_splitter.other_index, False)
|
||||||
|
@ -87,6 +87,13 @@ class TagsView(QTreeView): # {{{
|
|||||||
self.setDragDropMode(self.DropOnly)
|
self.setDragDropMode(self.DropOnly)
|
||||||
self.setDropIndicatorShown(True)
|
self.setDropIndicatorShown(True)
|
||||||
self.setAutoExpandDelay(500)
|
self.setAutoExpandDelay(500)
|
||||||
|
self.pane_is_visible = False
|
||||||
|
|
||||||
|
def set_pane_is_visible(self, to_what):
|
||||||
|
pv = self.pane_is_visible
|
||||||
|
self.pane_is_visible = to_what
|
||||||
|
if to_what and not pv:
|
||||||
|
self.recount()
|
||||||
|
|
||||||
def set_database(self, db, tag_match, sort_by):
|
def set_database(self, db, tag_match, sort_by):
|
||||||
self.hidden_categories = config['tag_browser_hidden_categories']
|
self.hidden_categories = config['tag_browser_hidden_categories']
|
||||||
@ -300,7 +307,7 @@ class TagsView(QTreeView): # {{{
|
|||||||
return self.isExpanded(idx)
|
return self.isExpanded(idx)
|
||||||
|
|
||||||
def recount(self, *args):
|
def recount(self, *args):
|
||||||
if self.disable_recounting:
|
if self.disable_recounting or not self.pane_is_visible:
|
||||||
return
|
return
|
||||||
self.refresh_signal_processed = True
|
self.refresh_signal_processed = True
|
||||||
ci = self.currentIndex()
|
ci = self.currentIndex()
|
||||||
@ -969,6 +976,7 @@ class TagBrowserWidget(QWidget): # {{{
|
|||||||
self._layout.setContentsMargins(0,0,0,0)
|
self._layout.setContentsMargins(0,0,0,0)
|
||||||
|
|
||||||
parent.tags_view = TagsView(parent)
|
parent.tags_view = TagsView(parent)
|
||||||
|
self.tags_view = parent.tags_view
|
||||||
self._layout.addWidget(parent.tags_view)
|
self._layout.addWidget(parent.tags_view)
|
||||||
|
|
||||||
parent.sort_by = QComboBox(parent)
|
parent.sort_by = QComboBox(parent)
|
||||||
@ -998,6 +1006,9 @@ class TagBrowserWidget(QWidget): # {{{
|
|||||||
_('Add your own categories to the Tag Browser'))
|
_('Add your own categories to the Tag Browser'))
|
||||||
parent.edit_categories.setStatusTip(parent.edit_categories.toolTip())
|
parent.edit_categories.setStatusTip(parent.edit_categories.toolTip())
|
||||||
|
|
||||||
|
def set_pane_is_visible(self, to_what):
|
||||||
|
self.tags_view.set_pane_is_visible(to_what)
|
||||||
|
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -119,10 +119,8 @@ class SafeFormat(TemplateFormatter):
|
|||||||
try:
|
try:
|
||||||
b = self.book.get_user_metadata(key, False)
|
b = self.book.get_user_metadata(key, False)
|
||||||
except:
|
except:
|
||||||
if DEBUG:
|
traceback.print_exc()
|
||||||
traceback.print_exc()
|
|
||||||
b = None
|
b = None
|
||||||
|
|
||||||
if b is not None and b['datatype'] == 'composite':
|
if b is not None and b['datatype'] == 'composite':
|
||||||
if key in self.composite_values:
|
if key in self.composite_values:
|
||||||
return self.composite_values[key]
|
return self.composite_values[key]
|
||||||
@ -135,8 +133,7 @@ class SafeFormat(TemplateFormatter):
|
|||||||
return val.replace('/', '_').replace('\\', '_')
|
return val.replace('/', '_').replace('\\', '_')
|
||||||
return ''
|
return ''
|
||||||
except:
|
except:
|
||||||
if DEBUG:
|
traceback.print_exc()
|
||||||
traceback.print_exc()
|
|
||||||
return key
|
return key
|
||||||
|
|
||||||
def get_components(template, mi, id, timefmt='%b %Y', length=250,
|
def get_components(template, mi, id, timefmt='%b %Y', length=250,
|
||||||
@ -155,6 +152,8 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
|
|||||||
format_args['tags'] = mi.format_tags()
|
format_args['tags'] = mi.format_tags()
|
||||||
if format_args['tags'].startswith('/'):
|
if format_args['tags'].startswith('/'):
|
||||||
format_args['tags'] = format_args['tags'][1:]
|
format_args['tags'] = format_args['tags'][1:]
|
||||||
|
else:
|
||||||
|
format_args['tags'] = ''
|
||||||
if mi.series:
|
if mi.series:
|
||||||
format_args['series'] = tsfmt(mi.series)
|
format_args['series'] = tsfmt(mi.series)
|
||||||
if mi.series_index is not None:
|
if mi.series_index is not None:
|
||||||
@ -254,6 +253,7 @@ def do_save_book_to_disk(id_, mi, cover, plugboards,
|
|||||||
if not os.path.exists(dirpath):
|
if not os.path.exists(dirpath):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
ocover = mi.cover
|
||||||
if opts.save_cover and cover and os.access(cover, os.R_OK):
|
if opts.save_cover and cover and os.access(cover, os.R_OK):
|
||||||
with open(base_path+'.jpg', 'wb') as f:
|
with open(base_path+'.jpg', 'wb') as f:
|
||||||
with open(cover, 'rb') as s:
|
with open(cover, 'rb') as s:
|
||||||
@ -267,6 +267,8 @@ def do_save_book_to_disk(id_, mi, cover, plugboards,
|
|||||||
with open(base_path+'.opf', 'wb') as f:
|
with open(base_path+'.opf', 'wb') as f:
|
||||||
f.write(opf)
|
f.write(opf)
|
||||||
|
|
||||||
|
mi.cover = ocover
|
||||||
|
|
||||||
written = False
|
written = False
|
||||||
for fmt in formats:
|
for fmt in formats:
|
||||||
global plugboard_save_to_disk_value, plugboard_any_format_value
|
global plugboard_save_to_disk_value, plugboard_any_format_value
|
||||||
|
Loading…
x
Reference in New Issue
Block a user