mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
An option to automatically convert any added book to the current output format, found under Preferences->Adding books
E-book viewer: Fix restoring from fullscreen not respecting maximized window state E-book viewer: Add many more controls to the context menu, particularly useful in full screen mode E-book viewer: Allow easy searching of the selected word or phrase in google via the context menu Add a new type of FileType plugin, postimport, that runs after a book has been added to the database.
This commit is contained in:
commit
694c8a654b
@ -308,6 +308,10 @@ class FileTypePlugin(Plugin): # {{{
|
||||
#: to the database
|
||||
on_import = False
|
||||
|
||||
#: If True, this plugin is run after books are added
|
||||
#: to the database
|
||||
on_postimport = False
|
||||
|
||||
#: If True, this plugin is run just before a conversion
|
||||
on_preprocess = False
|
||||
|
||||
@ -337,6 +341,16 @@ class FileTypePlugin(Plugin): # {{{
|
||||
# Default implementation does nothing
|
||||
return path_to_ebook
|
||||
|
||||
def postimport(self, book_id, book_format, db):
|
||||
'''
|
||||
Called post import, i.e., after the book file has been added to the database.
|
||||
|
||||
:param book_id: Database id of the added book.
|
||||
:param book_format: The file type of the book that was added.
|
||||
:param db: Library database.
|
||||
'''
|
||||
pass # Default implementation does nothing
|
||||
|
||||
# }}}
|
||||
|
||||
class MetadataReaderPlugin(Plugin): # {{{
|
||||
|
@ -104,14 +104,17 @@ def is_disabled(plugin):
|
||||
# File type plugins {{{
|
||||
|
||||
_on_import = {}
|
||||
_on_postimport = {}
|
||||
_on_preprocess = {}
|
||||
_on_postprocess = {}
|
||||
|
||||
def reread_filetype_plugins():
|
||||
global _on_import
|
||||
global _on_postimport
|
||||
global _on_preprocess
|
||||
global _on_postprocess
|
||||
_on_import = {}
|
||||
_on_postimport = {}
|
||||
_on_preprocess = {}
|
||||
_on_postprocess = {}
|
||||
|
||||
@ -122,6 +125,10 @@ def reread_filetype_plugins():
|
||||
if not _on_import.has_key(ft):
|
||||
_on_import[ft] = []
|
||||
_on_import[ft].append(plugin)
|
||||
if plugin.on_postimport:
|
||||
if not _on_postimport.has_key(ft):
|
||||
_on_postimport[ft] = []
|
||||
_on_postimport[ft].append(plugin)
|
||||
if plugin.on_preprocess:
|
||||
if not _on_preprocess.has_key(ft):
|
||||
_on_preprocess[ft] = []
|
||||
@ -163,6 +170,22 @@ run_plugins_on_preprocess = functools.partial(_run_filetype_plugins,
|
||||
occasion='preprocess')
|
||||
run_plugins_on_postprocess = functools.partial(_run_filetype_plugins,
|
||||
occasion='postprocess')
|
||||
|
||||
def run_plugins_on_postimport(db, book_id, fmt):
|
||||
customization = config['plugin_customization']
|
||||
fmt = fmt.lower()
|
||||
for plugin in _on_postimport.get(fmt, []):
|
||||
if is_disabled(plugin):
|
||||
continue
|
||||
plugin.site_customization = customization.get(plugin.name, '')
|
||||
with plugin:
|
||||
try:
|
||||
plugin.postimport(book_id, fmt, db)
|
||||
except:
|
||||
print ('Running file type plugin %s failed with traceback:'%
|
||||
plugin.name)
|
||||
traceback.print_exc()
|
||||
|
||||
# }}}
|
||||
|
||||
# Plugin customization {{{
|
||||
|
@ -49,8 +49,9 @@ class EbookIterator(BookmarksMixin):
|
||||
|
||||
CHARACTERS_PER_PAGE = 1000
|
||||
|
||||
def __init__(self, pathtoebook, log=None):
|
||||
def __init__(self, pathtoebook, log=None, exclude_cover=False):
|
||||
self.log = log or default_log
|
||||
self.exclude_cover = exclude_cover
|
||||
pathtoebook = pathtoebook.strip()
|
||||
self.pathtoebook = os.path.abspath(pathtoebook)
|
||||
self.config = DynamicConfig(name='iterator')
|
||||
@ -142,8 +143,9 @@ class EbookIterator(BookmarksMixin):
|
||||
self.log.warn('Missing spine item:', repr(spath))
|
||||
|
||||
cover = self.opf.cover
|
||||
if cover and self.ebook_ext in {'lit', 'mobi', 'prc', 'opf', 'fb2',
|
||||
'azw', 'azw3'}:
|
||||
if cover:
|
||||
if not self.exclude_cover and self.ebook_ext in {
|
||||
'lit', 'mobi', 'prc', 'opf', 'fb2', 'azw', 'azw3'}:
|
||||
cfile = os.path.join(self.base, 'calibre_iterator_cover.html')
|
||||
rcpath = os.path.relpath(cover, self.base).replace(os.sep, '/')
|
||||
chtml = (TITLEPAGE%prepare_string_for_xml(rcpath, True)).encode('utf-8')
|
||||
@ -152,6 +154,12 @@ class EbookIterator(BookmarksMixin):
|
||||
self.spine[0:0] = [Spiny(cfile,
|
||||
mime_type='application/xhtml+xml')]
|
||||
self.delete_on_exit.append(cfile)
|
||||
elif self.exclude_cover and self.ebook_ext == 'epub':
|
||||
try:
|
||||
if (len(self.spine) > 1 and self.spine.index(cover) == 0):
|
||||
self.spine = self.spine[1:]
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if self.opf.path_to_html_toc is not None and \
|
||||
self.opf.path_to_html_toc not in self.spine:
|
||||
|
@ -93,6 +93,7 @@ gprefs.defaults['tag_browser_dont_collapse'] = []
|
||||
gprefs.defaults['edit_metadata_single_layout'] = 'default'
|
||||
gprefs.defaults['default_author_link'] = 'http://en.wikipedia.org/w/index.php?search={author}'
|
||||
gprefs.defaults['preserve_date_on_ctl'] = True
|
||||
gprefs.defaults['manual_add_auto_convert'] = False
|
||||
gprefs.defaults['cb_fullscreen'] = False
|
||||
gprefs.defaults['worker_max_time'] = 0
|
||||
gprefs.defaults['show_files_after_save'] = True
|
||||
|
@ -267,8 +267,8 @@ class ViewAction(InterfaceAction):
|
||||
|
||||
def _view_books(self, rows):
|
||||
if not rows or len(rows) == 0:
|
||||
self._launch_viewer()
|
||||
return
|
||||
return error_dialog(self.gui, _('Cannot view'),
|
||||
_('No books selected'), show=True)
|
||||
|
||||
if not self._view_check(len(rows)):
|
||||
return
|
||||
|
@ -42,6 +42,7 @@ class DuplicatesAdder(QObject): # {{{
|
||||
# here we add all the formats for dupe book record created above
|
||||
self.db_adder.add_formats(id, formats)
|
||||
self.db_adder.number_of_books_added += 1
|
||||
self.db_adder.auto_convert_books.add(id)
|
||||
self.count += 1
|
||||
self.added.emit(self.count)
|
||||
single_shot(self.add_one)
|
||||
@ -107,8 +108,16 @@ class DBAdder(QObject): # {{{
|
||||
self.input_queue = Queue()
|
||||
self.output_queue = Queue()
|
||||
self.merged_books = set([])
|
||||
self.auto_convert_books = set()
|
||||
|
||||
def end(self):
|
||||
if (gprefs['manual_add_auto_convert'] and
|
||||
self.auto_convert_books):
|
||||
from calibre.gui2.ui import get_gui
|
||||
gui = get_gui()
|
||||
gui.iactions['Convert Books'].auto_convert_auto_add(
|
||||
self.auto_convert_books)
|
||||
|
||||
self.input_queue.put((None, None, None))
|
||||
|
||||
def start(self):
|
||||
@ -152,7 +161,6 @@ class DBAdder(QObject): # {{{
|
||||
fmts[-1] = fmt
|
||||
return fmts
|
||||
|
||||
|
||||
def add(self, id, opf, cover, name):
|
||||
formats = self.ids.pop(id)
|
||||
if opf.endswith('.error'):
|
||||
@ -219,6 +227,7 @@ class DBAdder(QObject): # {{{
|
||||
self.duplicates.append((mi, cover, orig_formats))
|
||||
else:
|
||||
self.add_formats(id_, formats)
|
||||
self.auto_convert_books.add(id_)
|
||||
self.number_of_books_added += 1
|
||||
else:
|
||||
self.names.append(name)
|
||||
|
@ -28,6 +28,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
||||
r('swap_author_names', prefs)
|
||||
r('add_formats_to_existing', prefs)
|
||||
r('preserve_date_on_ctl', gprefs)
|
||||
r('manual_add_auto_convert', gprefs)
|
||||
choices = [
|
||||
(_('Ignore duplicate incoming formats'), 'ignore'),
|
||||
(_('Overwrite existing duplicate formats'), 'overwrite'),
|
||||
|
@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>753</width>
|
||||
<width>1035</width>
|
||||
<height>547</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -24,6 +24,36 @@
|
||||
<string>The Add &Process</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="opt_add_formats_to_existing">
|
||||
<property name="toolTip">
|
||||
<string>Automerge: If books with similar titles and authors found, merge the incoming formats automatically into
|
||||
existing book records. The box to the right controls what happens when an existing record already has
|
||||
the incoming format. Note that this option also affects the Copy to library action.
|
||||
|
||||
Title match ignores leading indefinite articles ("the", "a", "an"), punctuation, case, etc. Author match is exact.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Automerge added books if they already exist in the calibre library:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QComboBox" name="opt_automerge">
|
||||
<property name="toolTip">
|
||||
<string>Automerge: If books with similar titles and authors found, merge the incoming formats automatically into
|
||||
existing book records. This box controls what happens when an existing record already has
|
||||
the incoming format:
|
||||
|
||||
Ignore duplicate incoming files - means that existing files in your calibre library will not be replaced
|
||||
Overwrite existing duplicate files - means that existing files in your calibre library will be replaced
|
||||
Create new record for each duplicate file - means that a new book entry will be created for each duplicate file
|
||||
|
||||
Title matching ignores leading indefinite articles ("the", "a", "an"), punctuation, case, etc.
|
||||
Author matching is exact.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
@ -68,44 +98,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="opt_preserve_date_on_ctl">
|
||||
<property name="text">
|
||||
<string>When using the "&Copy to library" action to copy books between libraries, preserve the date</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="opt_add_formats_to_existing">
|
||||
<property name="toolTip">
|
||||
<string>Automerge: If books with similar titles and authors found, merge the incoming formats automatically into
|
||||
existing book records. The box to the right controls what happens when an existing record already has
|
||||
the incoming format. Note that this option also affects the Copy to library action.
|
||||
|
||||
Title match ignores leading indefinite articles ("the", "a", "an"), punctuation, case, etc. Author match is exact.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Automerge added books if they already exist in the calibre library:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QComboBox" name="opt_automerge">
|
||||
<property name="toolTip">
|
||||
<string>Automerge: If books with similar titles and authors found, merge the incoming formats automatically into
|
||||
existing book records. This box controls what happens when an existing record already has
|
||||
the incoming format:
|
||||
|
||||
Ignore duplicate incoming files - means that existing files in your calibre library will not be replaced
|
||||
Overwrite existing duplicate files - means that existing files in your calibre library will be replaced
|
||||
Create new record for each duplicate file - means that a new book entry will be created for each duplicate file
|
||||
|
||||
Title matching ignores leading indefinite articles ("the", "a", "an"), punctuation, case, etc.
|
||||
Author matching is exact.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_230">
|
||||
<property name="text">
|
||||
<string>&Tags to apply when adding a book:</string>
|
||||
@ -115,14 +108,14 @@ Author matching is exact.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<item row="5" column="2">
|
||||
<widget class="QLineEdit" name="opt_new_book_tags">
|
||||
<property name="toolTip">
|
||||
<string>A comma-separated list of tags that will be applied to books added to the library</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="3">
|
||||
<item row="6" column="0" colspan="3">
|
||||
<widget class="QGroupBox" name="metadata_box">
|
||||
<property name="title">
|
||||
<string>&Configure metadata from file name</string>
|
||||
@ -144,6 +137,20 @@ Author matching is exact.</string>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="opt_preserve_date_on_ctl">
|
||||
<property name="text">
|
||||
<string>When using the "&Copy to library" action to copy books between libraries, preserve the date</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="opt_manual_add_auto_convert">
|
||||
<property name="text">
|
||||
<string>Automatically &convert added books to the current output format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_4">
|
||||
|
@ -16,6 +16,7 @@ from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings
|
||||
|
||||
from calibre.gui2.viewer.flip import SlideFlip
|
||||
from calibre.gui2.shortcuts import Shortcuts
|
||||
from calibre.gui2 import open_url
|
||||
from calibre import prints
|
||||
from calibre.customize.ui import all_viewer_plugins
|
||||
from calibre.gui2.viewer.keys import SHORTCUTS
|
||||
@ -481,7 +482,12 @@ class DocumentView(QWebView): # {{{
|
||||
d = self.document
|
||||
self.unimplemented_actions = list(map(self.pageAction,
|
||||
[d.DownloadImageToDisk, d.OpenLinkInNewWindow, d.DownloadLinkToDisk,
|
||||
d.OpenImageInNewWindow, d.OpenLink, d.Reload]))
|
||||
d.OpenImageInNewWindow, d.OpenLink, d.Reload, d.InspectElement]))
|
||||
|
||||
self.search_online_action = QAction(QIcon(I('search.png')), '', self)
|
||||
self.search_online_action.setShortcut(Qt.CTRL+Qt.Key_E)
|
||||
self.search_online_action.triggered.connect(self.search_online)
|
||||
self.addAction(self.search_online_action)
|
||||
self.dictionary_action = QAction(QIcon(I('dictionary.png')),
|
||||
_('&Lookup in dictionary'), self)
|
||||
self.dictionary_action.setShortcut(Qt.CTRL+Qt.Key_L)
|
||||
@ -526,6 +532,10 @@ class DocumentView(QWebView): # {{{
|
||||
self.goto_location_action.setMenu(self.goto_location_menu)
|
||||
self.grabGesture(Qt.SwipeGesture)
|
||||
|
||||
self.restore_fonts_action = QAction(_('Normal font size'), self)
|
||||
self.restore_fonts_action.setCheckable(True)
|
||||
self.restore_fonts_action.triggered.connect(self.restore_font_size)
|
||||
|
||||
def goto_next_section(self, *args):
|
||||
if self.manager is not None:
|
||||
self.manager.goto_next_section()
|
||||
@ -582,6 +592,15 @@ class DocumentView(QWebView): # {{{
|
||||
if self.manager is not None:
|
||||
self.manager.selection_changed(unicode(self.document.selectedText()))
|
||||
|
||||
def _selectedText(self):
|
||||
t = unicode(self.selectedText()).strip()
|
||||
if not t:
|
||||
return u''
|
||||
if len(t) > 40:
|
||||
t = t[:40] + u'...'
|
||||
t = t.replace(u'&', u'&&')
|
||||
return _("S&earch Google for '%s'")%t
|
||||
|
||||
def contextMenuEvent(self, ev):
|
||||
mf = self.document.mainFrame()
|
||||
r = mf.hitTestContent(ev.pos())
|
||||
@ -591,17 +610,48 @@ class DocumentView(QWebView): # {{{
|
||||
menu = self.document.createStandardContextMenu()
|
||||
for action in self.unimplemented_actions:
|
||||
menu.removeAction(action)
|
||||
text = unicode(self.selectedText())
|
||||
if text:
|
||||
menu.insertAction(list(menu.actions())[0], self.dictionary_action)
|
||||
menu.insertAction(list(menu.actions())[0], self.search_action)
|
||||
|
||||
if not img.isNull():
|
||||
menu.addAction(self.view_image_action)
|
||||
|
||||
text = self._selectedText()
|
||||
if text and img.isNull():
|
||||
self.search_online_action.setText(text)
|
||||
menu.addAction(self.search_online_action)
|
||||
menu.addAction(self.dictionary_action)
|
||||
menu.addAction(self.search_action)
|
||||
|
||||
if not text and img.isNull():
|
||||
menu.addSeparator()
|
||||
if self.manager.action_back.isEnabled():
|
||||
menu.addAction(self.manager.action_back)
|
||||
if self.manager.action_forward.isEnabled():
|
||||
menu.addAction(self.manager.action_forward)
|
||||
menu.addAction(self.goto_location_action)
|
||||
if self.document.in_fullscreen_mode and self.manager is not None:
|
||||
|
||||
if self.manager is not None:
|
||||
menu.addSeparator()
|
||||
menu.addAction(self.manager.action_table_of_contents)
|
||||
|
||||
menu.addSeparator()
|
||||
menu.addAction(self.manager.action_font_size_larger)
|
||||
self.restore_fonts_action.setChecked(self.multiplier == 1)
|
||||
menu.addAction(self.restore_fonts_action)
|
||||
menu.addAction(self.manager.action_font_size_smaller)
|
||||
|
||||
menu.addSeparator()
|
||||
inspectAction = self.pageAction(self.document.InspectElement)
|
||||
menu.addAction(inspectAction)
|
||||
|
||||
if not text and img.isNull() and self.manager is not None:
|
||||
menu.addSeparator()
|
||||
if self.document.in_fullscreen_mode and self.manager is not None:
|
||||
menu.addAction(self.manager.toggle_toolbar_action)
|
||||
menu.addAction(self.manager.action_full_screen)
|
||||
|
||||
menu.addSeparator()
|
||||
menu.addAction(self.manager.action_quit)
|
||||
|
||||
menu.exec_(ev.globalPos())
|
||||
|
||||
def lookup(self, *args):
|
||||
@ -616,6 +666,12 @@ class DocumentView(QWebView): # {{{
|
||||
if t:
|
||||
self.manager.search.set_search_string(t)
|
||||
|
||||
def search_online(self):
|
||||
t = unicode(self.selectedText()).strip()
|
||||
if t:
|
||||
url = 'https://www.google.com/search?q=' + QUrl().toPercentEncoding(t)
|
||||
open_url(QUrl.fromEncoded(url))
|
||||
|
||||
def set_manager(self, manager):
|
||||
self.manager = manager
|
||||
self.scrollbar = manager.horizontal_scrollbar
|
||||
@ -993,6 +1049,11 @@ class DocumentView(QWebView): # {{{
|
||||
self.multiplier -= amount
|
||||
return self.document.scroll_fraction
|
||||
|
||||
def restore_font_size(self):
|
||||
with self.document.page_position:
|
||||
self.multiplier = 1
|
||||
return self.document.scroll_fraction
|
||||
|
||||
def changeEvent(self, event):
|
||||
if event.type() == event.EnabledChange:
|
||||
self.update()
|
||||
|
@ -178,6 +178,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
||||
self.pending_restore = False
|
||||
self.existing_bookmarks= []
|
||||
self.selected_text = None
|
||||
self.was_maximized = False
|
||||
self.read_settings()
|
||||
self.dictionary_box.hide()
|
||||
self.close_dictionary_view.clicked.connect(lambda
|
||||
@ -207,7 +208,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
||||
self.view.set_manager(self)
|
||||
self.pi = ProgressIndicator(self)
|
||||
self.toc.setVisible(False)
|
||||
self.action_quit = QAction(self)
|
||||
self.action_quit = QAction(_('&Quit'), self)
|
||||
self.addAction(self.action_quit)
|
||||
self.view_resized_timer = QTimer(self)
|
||||
self.view_resized_timer.timeout.connect(self.viewport_resize_finished)
|
||||
@ -299,6 +300,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
||||
''')
|
||||
self.window_mode_changed = None
|
||||
self.toggle_toolbar_action = QAction(_('Show/hide controls'), self)
|
||||
self.toggle_toolbar_action.setCheckable(True)
|
||||
self.toggle_toolbar_action.triggered.connect(self.toggle_toolbars)
|
||||
self.addAction(self.toggle_toolbar_action)
|
||||
self.full_screen_label_anim = QPropertyAnimation(
|
||||
@ -421,6 +423,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
||||
def save_state(self):
|
||||
state = bytearray(self.saveState(self.STATE_VERSION))
|
||||
vprefs['viewer_toolbar_state'] = state
|
||||
if not self.isFullScreen():
|
||||
vprefs.set('viewer_window_geometry', bytearray(self.saveGeometry()))
|
||||
if self.current_book_has_toc:
|
||||
vprefs.set('viewer_toc_isvisible', bool(self.toc.isVisible()))
|
||||
@ -488,6 +491,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
||||
self.window_mode_changed = 'fullscreen'
|
||||
self.tool_bar.setVisible(False)
|
||||
self.tool_bar2.setVisible(False)
|
||||
self.was_maximized = self.isMaximized()
|
||||
if not self.view.document.fullscreen_scrollbar:
|
||||
self.vertical_scrollbar.setVisible(False)
|
||||
self.frame.layout().setSpacing(0)
|
||||
@ -574,6 +578,9 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
||||
om = self._original_frame_margins
|
||||
self.centralwidget.layout().setContentsMargins(om[0])
|
||||
self.frame.layout().setContentsMargins(om[1])
|
||||
if self.was_maximized:
|
||||
super(EbookViewer, self).showMaximized()
|
||||
else:
|
||||
super(EbookViewer, self).showNormal()
|
||||
|
||||
def handle_window_mode_toggle(self):
|
||||
@ -681,13 +688,9 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
||||
|
||||
def font_size_larger(self):
|
||||
self.view.magnify_fonts()
|
||||
self.action_font_size_larger.setEnabled(self.view.multiplier < 3)
|
||||
self.action_font_size_smaller.setEnabled(self.view.multiplier > 0.2)
|
||||
|
||||
def font_size_smaller(self):
|
||||
self.view.shrink_fonts()
|
||||
self.action_font_size_larger.setEnabled(self.view.multiplier < 3)
|
||||
self.action_font_size_smaller.setEnabled(self.view.multiplier > 0.2)
|
||||
|
||||
def magnification_changed(self, val):
|
||||
tt = _('Make font size %(which)s\nCurrent magnification: %(mag).1f')
|
||||
@ -695,6 +698,8 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
||||
tt %dict(which=_('larger'), mag=val))
|
||||
self.action_font_size_smaller.setToolTip(
|
||||
tt %dict(which=_('smaller'), mag=val))
|
||||
self.action_font_size_larger.setEnabled(self.view.multiplier < 3)
|
||||
self.action_font_size_smaller.setEnabled(self.view.multiplier > 0.2)
|
||||
|
||||
def find(self, text, repeat=False, backwards=False):
|
||||
if not text:
|
||||
|
@ -28,7 +28,8 @@ from calibre.ebooks.metadata.book.base import Metadata
|
||||
from calibre.constants import preferred_encoding, iswindows, filesystem_encoding
|
||||
from calibre.ptempfile import (PersistentTemporaryFile,
|
||||
base_dir, SpooledTemporaryFile)
|
||||
from calibre.customize.ui import run_plugins_on_import
|
||||
from calibre.customize.ui import (run_plugins_on_import,
|
||||
run_plugins_on_postimport)
|
||||
from calibre import isbytestring
|
||||
from calibre.utils.filenames import (ascii_filename, samefile,
|
||||
WindowsAtomicFolderMove, hardlink_file)
|
||||
@ -1495,8 +1496,10 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
format = os.path.splitext(npath)[-1].lower().replace('.', '').upper()
|
||||
stream = lopen(npath, 'rb')
|
||||
format = check_ebook_format(stream, format)
|
||||
return self.add_format(index, format, stream,
|
||||
retval = self.add_format(index, format, stream,
|
||||
index_is_id=index_is_id, path=path, notify=notify)
|
||||
run_plugins_on_postimport(self, id, format)
|
||||
return retval
|
||||
|
||||
def add_format(self, index, format, stream, index_is_id=False, path=None,
|
||||
notify=True, replace=True, copy_function=None):
|
||||
@ -3475,6 +3478,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
formats, metadata = iter(formats), iter(metadata)
|
||||
duplicates = []
|
||||
ids = []
|
||||
postimport = []
|
||||
for path in paths:
|
||||
mi = metadata.next()
|
||||
self._add_newbook_tag(mi)
|
||||
@ -3506,8 +3510,11 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
format = check_ebook_format(stream, format)
|
||||
self.add_format(id, format, stream, index_is_id=True)
|
||||
stream.close()
|
||||
postimport.append((id, format))
|
||||
self.conn.commit()
|
||||
self.data.refresh_ids(self, ids) # Needed to update format list and size
|
||||
for book_id, fmt in postimport:
|
||||
run_plugins_on_postimport(self, book_id, fmt)
|
||||
if duplicates:
|
||||
paths = list(duplicate[0] for duplicate in duplicates)
|
||||
formats = list(duplicate[1] for duplicate in duplicates)
|
||||
|
Loading…
x
Reference in New Issue
Block a user