diff --git a/src/calibre/customize/__init__.py b/src/calibre/customize/__init__.py
index 2570efebe1..1f57305945 100644
--- a/src/calibre/customize/__init__.py
+++ b/src/calibre/customize/__init__.py
@@ -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
@@ -336,7 +340,14 @@ class FileTypePlugin(Plugin): # {{{
'''
# Default implementation does nothing
return path_to_ebook
+
+ def postimport(self, id):
+ '''
+ Run post import.
+ :param id: Library id of the added book.
+ '''
+
# }}}
class MetadataReaderPlugin(Plugin): # {{{
diff --git a/src/calibre/customize/ui.py b/src/calibre/customize/ui.py
index 2799ed747a..15d448161e 100644
--- a/src/calibre/customize/ui.py
+++ b/src/calibre/customize/ui.py
@@ -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,21 @@ run_plugins_on_preprocess = functools.partial(_run_filetype_plugins,
occasion='preprocess')
run_plugins_on_postprocess = functools.partial(_run_filetype_plugins,
occasion='postprocess')
+
+def postimport_plugins(id, format):
+ customization = config['plugin_customization']
+ format = format.lower()
+ for plugin in _on_postimport.get(format, []):
+ if is_disabled(plugin):
+ continue
+ plugin.site_customization = customization.get(plugin.name, '')
+ with plugin:
+ try:
+ plugin.postimport(id)
+ except:
+ print 'Running file type plugin %s failed with traceback:'%plugin.name
+ traceback.print_exc()
+
# }}}
# Plugin customization {{{
diff --git a/src/calibre/ebooks/oeb/iterator/book.py b/src/calibre/ebooks/oeb/iterator/book.py
index 992d5304c6..65fc48cad7 100644
--- a/src/calibre/ebooks/oeb/iterator/book.py
+++ b/src/calibre/ebooks/oeb/iterator/book.py
@@ -49,8 +49,9 @@ class EbookIterator(BookmarksMixin):
CHARACTERS_PER_PAGE = 1000
- def __init__(self, pathtoebook, log=None):
+ def __init__(self, pathtoebook, exclude_cover=False, log=None):
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')
@@ -139,16 +140,20 @@ 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'}:
- 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')
- with open(cfile, 'wb') as f:
- f.write(chtml)
- self.spine[0:0] = [Spiny(cfile,
- mime_type='application/xhtml+xml')]
- self.delete_on_exit.append(cfile)
+ if cover:
+ if self.ebook_ext in {'lit', 'mobi', 'prc', 'opf', 'fb2',
+ 'azw', 'azw3'}:
+ if not self.exclude_cover:
+ 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')
+ with open(cfile, 'wb') as f:
+ f.write(chtml)
+ self.spine[0:0] = [Spiny(cfile,
+ mime_type='application/xhtml+xml')]
+ self.delete_on_exit.append(cfile)
+ elif self.exclude_cover:
+ self.spine.remove(self.spine[0])
if self.opf.path_to_html_toc is not None and \
self.opf.path_to_html_toc not in self.spine:
diff --git a/src/calibre/gui2/actions/view.py b/src/calibre/gui2/actions/view.py
index 5a7a991607..8672338b6a 100644
--- a/src/calibre/gui2/actions/view.py
+++ b/src/calibre/gui2/actions/view.py
@@ -267,7 +267,6 @@ class ViewAction(InterfaceAction):
def _view_books(self, rows):
if not rows or len(rows) == 0:
- self._launch_viewer()
return
if not self._view_check(len(rows)):
diff --git a/src/calibre/gui2/add.py b/src/calibre/gui2/add.py
index 234c72abf4..4336148816 100644
--- a/src/calibre/gui2/add.py
+++ b/src/calibre/gui2/add.py
@@ -99,6 +99,7 @@ class DBAdder(QObject): # {{{
def __init__(self, parent, db, ids, nmap):
QObject.__init__(self, parent)
+ self.parent = parent
self.db, self.ids, self.nmap = db, dict(**ids), dict(**nmap)
self.critical = {}
self.number_of_books_added = 0
@@ -232,6 +233,11 @@ class DBAdder(QObject): # {{{
with open(path, 'rb') as f:
self.db.add_format(id, fmt, f, index_is_id=True,
notify=False, replace=replace)
+ if gprefs['auto_add_auto_convert']:
+ of = prefs['output_format']
+ if not of == fmt.lower():
+ gui = self.parent._parent
+ gui.iactions['Convert Books'].auto_convert([id], None, of)
# }}}
diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py
index 338a558f29..adcd0fc6cf 100644
--- a/src/calibre/gui2/init.py
+++ b/src/calibre/gui2/init.py
@@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
import functools
from PyQt4.Qt import Qt, QStackedWidget, QMenu, \
- QSize, QSizePolicy, QStatusBar, QLabel, QFont
+ QSize, QSizePolicy, QStatusBar, QTimer, QLabel, QFont
from calibre.utils.config import prefs
from calibre.constants import (isosx, __appname__, preferred_encoding,
@@ -274,7 +274,7 @@ class LayoutMixin(object): # {{{
m = self.library_view.model()
if m.rowCount(None) > 0:
- self.library_view.set_current_row(0)
+ QTimer.singleShot(1, self.library_view.set_current_row)
m.current_changed(self.library_view.currentIndex(),
self.library_view.currentIndex())
self.library_view.setFocus(Qt.OtherFocusReason)
diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py
index e263e2c489..85636104cb 100644
--- a/src/calibre/gui2/library/views.py
+++ b/src/calibre/gui2/library/views.py
@@ -754,6 +754,13 @@ class BooksView(QTableView): # {{{
# }}}
+ def keyPressEvent(self, event):
+ if event.key() == Qt.Key_Return:
+ selected_rows = [r.row() for r in self.selectionModel().selectedRows()]
+ self.display_parent.iactions['View']._view_books(selected_rows)
+ else:
+ return super(BooksView, self).keyPressEvent(event)
+
@property
def column_map(self):
return self._model.column_map
@@ -777,7 +784,7 @@ class BooksView(QTableView): # {{{
self.scrollTo(self.model().index(row, i), self.PositionAtCenter)
break
- def set_current_row(self, row, select=True):
+ def set_current_row(self, row=0, select=True):
if row > -1 and row < self.model().rowCount(QModelIndex()):
h = self.horizontalHeader()
logical_indices = list(range(h.count()))
diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py
index 54a80571e6..50ead17d1d 100644
--- a/src/calibre/gui2/search_box.py
+++ b/src/calibre/gui2/search_box.py
@@ -128,7 +128,7 @@ class SearchBox2(QComboBox): # {{{
def clear(self, emit_search=True):
self.normalize_state()
self.setEditText('')
- if emit_search:
+ if self.in_a_search() and emit_search:
self.search.emit('')
self._in_a_search = False
self.cleared.emit()
@@ -159,7 +159,6 @@ class SearchBox2(QComboBox): # {{{
self.normalize_state()
if self._in_a_search:
self.changed.emit()
- self._in_a_search = False
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
self.do_search()
self.focus_to_library.emit()
@@ -424,6 +423,7 @@ class SearchBoxMixin(object): # {{{
self.tags_view.clear()
self.saved_search.clear()
self.set_number_of_books_shown()
+ self.focus_to_library()
def search_box_changed(self):
self.saved_search.clear()
@@ -440,6 +440,8 @@ class SearchBoxMixin(object): # {{{
def focus_to_library(self):
self.current_view().setFocus(Qt.OtherFocusReason)
+ if not self.current_view().get_selected_ids():
+ self.current_view().set_current_row()
# }}}
diff --git a/src/calibre/gui2/viewer/config.py b/src/calibre/gui2/viewer/config.py
index 8643ce63d0..e3726c1ecb 100644
--- a/src/calibre/gui2/viewer/config.py
+++ b/src/calibre/gui2/viewer/config.py
@@ -41,6 +41,8 @@ def config(defaults=None):
help=_('Default language for hyphenation rules'))
c.add_opt('remember_current_page', default=True,
help=_('Save the current position in the document, when quitting'))
+ c.add_opt('dont_show_cover', default=False,
+ help=_('Don\'t show the cover.'))
c.add_opt('wheel_flips_pages', default=False,
help=_('Have the mouse wheel turn pages'))
c.add_opt('line_scrolling_stops_on_pagebreaks', default=False,
@@ -177,6 +179,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
def load_options(self, opts):
self.opt_remember_window_size.setChecked(opts.remember_window_size)
self.opt_remember_current_page.setChecked(opts.remember_current_page)
+ self.opt_dont_show_cover.setChecked(opts.dont_show_cover)
self.opt_wheel_flips_pages.setChecked(opts.wheel_flips_pages)
self.opt_page_flip_duration.setValue(opts.page_flip_duration)
fms = opts.font_magnification_step
@@ -267,6 +270,7 @@ class ConfigDialog(QDialog, Ui_Dialog):
c.set('max_fs_width', int(self.max_fs_width.value()))
c.set('hyphenate', self.hyphenate.isChecked())
c.set('remember_current_page', self.opt_remember_current_page.isChecked())
+ c.set('dont_show_cover', self.opt_dont_show_cover.isChecked())
c.set('wheel_flips_pages', self.opt_wheel_flips_pages.isChecked())
c.set('page_flip_duration', self.opt_page_flip_duration.value())
c.set('font_magnification_step',
diff --git a/src/calibre/gui2/viewer/config.ui b/src/calibre/gui2/viewer/config.ui
index f91462e5b2..abc5391ebf 100644
--- a/src/calibre/gui2/viewer/config.ui
+++ b/src/calibre/gui2/viewer/config.ui
@@ -605,6 +605,13 @@ QToolBox::tab:hover {
+
'+ \ @@ -468,7 +446,12 @@ class EbookViewer(MainWindow, Ui_EbookViewer): from calibre.gui2.viewer.documentview import config c = config().parse() return c.remember_current_page - + + def get_dont_show_cover_opt(self): + from calibre.gui2.viewer.documentview import config + c = config().parse() + return c.dont_show_cover + def print_book(self): p = Printing(self.iterator, self) p.start_print() @@ -477,7 +460,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): p = Printing(self.iterator, self) p.start_preview() - def toggle_fullscreen(self, x): + def toggle_fullscreen(self): if self.isFullScreen(): self.showNormal() else: @@ -485,9 +468,12 @@ class EbookViewer(MainWindow, Ui_EbookViewer): def showFullScreen(self): self.view.document.page_position.save() + self.view.document.switch_to_fullscreen_mode() self.window_mode_changed = 'fullscreen' + self.was_maximized = super(EbookViewer, self).isMaximized() self.tool_bar.setVisible(False) self.tool_bar2.setVisible(False) + self.action_full_screen.setChecked(True) if not self.view.document.fullscreen_scrollbar: self.vertical_scrollbar.setVisible(False) self.frame.layout().setSpacing(0) @@ -500,26 +486,6 @@ class EbookViewer(MainWindow, Ui_EbookViewer): super(EbookViewer, self).showFullScreen() - def show_full_screen_label(self): - f = self.full_screen_label - self.esc_full_screen_action.setEnabled(True) - f.setVisible(True) - height = 200 - width = int(0.7*self.view.width()) - f.resize(width, height) - f.move((self.view.width() - width)//2, (self.view.height()-height)//2) - a = self.full_screen_label_anim - a.setDuration(500) - a.setStartValue(QSize(width, 0)) - a.setEndValue(QSize(width, height)) - a.start() - QTimer.singleShot(3500, self.full_screen_label.hide) - self.view.document.switch_to_fullscreen_mode() - if self.view.document.fullscreen_clock: - self.show_clock() - if self.view.document.fullscreen_pos: - self.show_pos_label() - def show_clock(self): self.clock_label.setVisible(True) self.clock_label.setText(QTime(22, 33, @@ -559,6 +525,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): def showNormal(self): self.view.document.page_position.save() + self.view.document.switch_to_window_mode() self.clock_label.setVisible(False) self.pos_label.setVisible(False) self.frame.setFrameStyle(self.original_frame_style) @@ -566,23 +533,23 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.clock_timer.stop() self.vertical_scrollbar.setVisible(True) self.window_mode_changed = 'normal' - self.esc_full_screen_action.setEnabled(False) + self.action_full_screen.setChecked(False) self.tool_bar.setVisible(True) self.tool_bar2.setVisible(True) - self.full_screen_label.setVisible(False) if hasattr(self, '_original_frame_margins'): om = self._original_frame_margins self.centralwidget.layout().setContentsMargins(om[0]) self.frame.layout().setContentsMargins(om[1]) - super(EbookViewer, self).showNormal() + if self.was_maximized: + super(EbookViewer, self).showMaximized() + else: + super(EbookViewer, self).showNormal() def handle_window_mode_toggle(self): if self.window_mode_changed: fs = self.window_mode_changed == 'fullscreen' self.window_mode_changed = None - if fs: - self.show_full_screen_label() - else: + if not fs: self.view.document.switch_to_window_mode() self.view.document.page_position.restore() self.scrolled(self.view.scroll_fraction) @@ -634,7 +601,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): if self.selected_text: QApplication.clipboard().setText(self.selected_text) - def back(self, x): + def back(self): pos = self.history.back(self.pos.value()) if pos is not None: self.goto_page(pos) @@ -643,7 +610,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): num = self.pos.value() self.goto_page(num) - def forward(self, x): + def forward(self): pos = self.history.forward() if pos is not None: self.goto_page(pos) @@ -657,6 +624,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): def goto_page(self, new_page, loaded_check=True): if self.current_page is not None or not loaded_check: for page in self.iterator.spine: + # print "goto_page", new_page, page.start_page, page.max_page if new_page >= page.start_page and new_page <= page.max_page: try: frac = float(new_page-page.start_page)/(page.pages-1) @@ -681,20 +649,21 @@ 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 font_size_restore(self): + self.view.restore_font_size() + def magnification_changed(self, val): tt = _('Make font size %(which)s\nCurrent magnification: %(mag).1f') self.action_font_size_larger.setToolTip( 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: @@ -961,7 +930,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): if self.iterator is not None: self.save_current_position() self.iterator.__exit__() - self.iterator = EbookIterator(pathtoebook) + self.iterator = EbookIterator(pathtoebook, self.get_dont_show_cover_opt()) self.open_progress_indicator(_('Loading ebook...')) worker = Worker(target=partial(self.iterator.__enter__, extract_embedded_fonts_for_qt=True)) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 5952e11e57..d7dcbac75a 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -28,7 +28,7 @@ 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, postimport_plugins from calibre import isbytestring from calibre.utils.filenames import (ascii_filename, samefile, WindowsAtomicFolderMove, hardlink_file) @@ -1534,6 +1534,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): self.refresh_ids([id]) if notify: self.notify('metadata', [id]) + postimport_plugins(id, format) return True def save_original_format(self, book_id, fmt, notify=True):