mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Edit book: Add a tool to browse all images in the book with their thumbnails. Useful for visually locating an image. To launch it, use View->Browse images in book.
This commit is contained in:
parent
c3df19e437
commit
89236b5100
@ -106,6 +106,7 @@ class Boss(QObject):
|
|||||||
self.gui.check_book.check_requested.connect(self.check_requested)
|
self.gui.check_book.check_requested.connect(self.check_requested)
|
||||||
self.gui.check_book.fix_requested.connect(self.fix_requested)
|
self.gui.check_book.fix_requested.connect(self.fix_requested)
|
||||||
self.gui.toc_view.navigate_requested.connect(self.link_clicked)
|
self.gui.toc_view.navigate_requested.connect(self.link_clicked)
|
||||||
|
self.gui.image_browser.image_activated.connect(self.image_activated)
|
||||||
|
|
||||||
def preferences(self):
|
def preferences(self):
|
||||||
p = Preferences(self.gui)
|
p = Preferences(self.gui)
|
||||||
@ -817,6 +818,15 @@ class Boss(QObject):
|
|||||||
replace_file(current_container(), name, path, basename, force_mt)
|
replace_file(current_container(), name, path, basename, force_mt)
|
||||||
self.apply_container_update_to_gui()
|
self.apply_container_update_to_gui()
|
||||||
|
|
||||||
|
def browse_images(self):
|
||||||
|
self.gui.image_browser.refresh()
|
||||||
|
self.gui.image_browser.show()
|
||||||
|
self.gui.image_browser.raise_()
|
||||||
|
|
||||||
|
def image_activated(self, name):
|
||||||
|
mt = current_container().mime_map.get(name, guess_type(name))
|
||||||
|
self.edit_file_requested(name, None, mt)
|
||||||
|
|
||||||
def sync_editor_to_preview(self, name, lnum):
|
def sync_editor_to_preview(self, name, lnum):
|
||||||
editor = self.edit_file(name, 'html')
|
editor = self.edit_file(name, 'html')
|
||||||
self.ignore_preview_to_editor_sync = True
|
self.ignore_preview_to_editor_sync = True
|
||||||
|
@ -12,7 +12,7 @@ from PyQt4.Qt import (
|
|||||||
QDialog, QGridLayout, QDialogButtonBox, QSize, QListView, QStyledItemDelegate,
|
QDialog, QGridLayout, QDialogButtonBox, QSize, QListView, QStyledItemDelegate,
|
||||||
QLabel, QPixmap, QApplication, QSizePolicy, QAbstractListModel, QVariant,
|
QLabel, QPixmap, QApplication, QSizePolicy, QAbstractListModel, QVariant,
|
||||||
Qt, QRect, QPainter, QModelIndex, QSortFilterProxyModel, QLineEdit,
|
Qt, QRect, QPainter, QModelIndex, QSortFilterProxyModel, QLineEdit,
|
||||||
QToolButton, QIcon, QFormLayout)
|
QToolButton, QIcon, QFormLayout, pyqtSignal)
|
||||||
|
|
||||||
from calibre import fit_image
|
from calibre import fit_image
|
||||||
from calibre.constants import plugins
|
from calibre.constants import plugins
|
||||||
@ -160,12 +160,20 @@ class Images(QAbstractListModel):
|
|||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QAbstractListModel.__init__(self, parent)
|
QAbstractListModel.__init__(self, parent)
|
||||||
self.icon_size = parent.iconSize()
|
self.icon_size = parent.iconSize()
|
||||||
|
self.build()
|
||||||
|
|
||||||
|
def build(self):
|
||||||
c = current_container()
|
c = current_container()
|
||||||
self.image_names = []
|
self.image_names = []
|
||||||
|
self.image_cache = {}
|
||||||
|
if c is not None:
|
||||||
for name in sorted(c.mime_map, key=sort_key):
|
for name in sorted(c.mime_map, key=sort_key):
|
||||||
if c.mime_map[name].startswith('image/'):
|
if c.mime_map[name].startswith('image/'):
|
||||||
self.image_names.append(name)
|
self.image_names.append(name)
|
||||||
self.image_cache = {}
|
|
||||||
|
def refresh(self):
|
||||||
|
self.build()
|
||||||
|
self.reset()
|
||||||
|
|
||||||
def rowCount(self, *args):
|
def rowCount(self, *args):
|
||||||
return len(self.image_names)
|
return len(self.image_names)
|
||||||
@ -181,8 +189,12 @@ class Images(QAbstractListModel):
|
|||||||
|
|
||||||
class InsertImage(Dialog):
|
class InsertImage(Dialog):
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
image_activated = pyqtSignal(object)
|
||||||
Dialog.__init__(self, _('Choose an image'), 'insert-image-dialog', parent)
|
|
||||||
|
def __init__(self, parent=None, for_browsing=False):
|
||||||
|
self.for_browsing = for_browsing
|
||||||
|
Dialog.__init__(self, _('Images in book') if for_browsing else _('Choose an image'),
|
||||||
|
'browse-image-dialog' if for_browsing else 'insert-image-dialog', parent)
|
||||||
self.chosen_image = None
|
self.chosen_image = None
|
||||||
self.chosen_image_is_external = False
|
self.chosen_image_is_external = False
|
||||||
|
|
||||||
@ -196,6 +208,8 @@ class InsertImage(Dialog):
|
|||||||
self.la1 = la = QLabel(_('&Existing images in the book'))
|
self.la1 = la = QLabel(_('&Existing images in the book'))
|
||||||
la.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
la.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||||
l.addWidget(la, 0, 0, 1, 2)
|
l.addWidget(la, 0, 0, 1, 2)
|
||||||
|
if self.for_browsing:
|
||||||
|
la.setVisible(False)
|
||||||
|
|
||||||
self.view = v = QListView(self)
|
self.view = v = QListView(self)
|
||||||
v.setViewMode(v.IconMode)
|
v.setViewMode(v.IconMode)
|
||||||
@ -212,10 +226,12 @@ class InsertImage(Dialog):
|
|||||||
v.setItemDelegate(self.d)
|
v.setItemDelegate(self.d)
|
||||||
self.model = Images(self.view)
|
self.model = Images(self.view)
|
||||||
self.fm = fm = QSortFilterProxyModel(self.view)
|
self.fm = fm = QSortFilterProxyModel(self.view)
|
||||||
|
self.fm.setDynamicSortFilter(self.for_browsing)
|
||||||
fm.setSourceModel(self.model)
|
fm.setSourceModel(self.model)
|
||||||
fm.setFilterCaseSensitivity(False)
|
fm.setFilterCaseSensitivity(False)
|
||||||
v.setModel(fm)
|
v.setModel(fm)
|
||||||
l.addWidget(v, 1, 0, 1, 2)
|
l.addWidget(v, 1, 0, 1, 2)
|
||||||
|
v.pressed.connect(self.pressed)
|
||||||
la.setBuddy(v)
|
la.setBuddy(v)
|
||||||
|
|
||||||
self.filter = f = QLineEdit(self)
|
self.filter = f = QLineEdit(self)
|
||||||
@ -228,11 +244,23 @@ class InsertImage(Dialog):
|
|||||||
f.textChanged.connect(self.filter_changed)
|
f.textChanged.connect(self.filter_changed)
|
||||||
|
|
||||||
l.addWidget(self.bb, 3, 0, 1, 2)
|
l.addWidget(self.bb, 3, 0, 1, 2)
|
||||||
|
if self.for_browsing:
|
||||||
|
self.bb.clear()
|
||||||
|
self.bb.addButton(self.bb.Close)
|
||||||
|
b = self.refresh_button = self.bb.addButton(_('&Refresh'), self.bb.ActionRole)
|
||||||
|
b.clicked.connect(self.refresh)
|
||||||
|
b.setIcon(QIcon(I('view-refresh.png')))
|
||||||
|
b.setToolTip(_('Refresh the displayed images'))
|
||||||
|
self.setAttribute(Qt.WA_DeleteOnClose, False)
|
||||||
|
else:
|
||||||
b = self.import_button = self.bb.addButton(_('&Import image'), self.bb.ActionRole)
|
b = self.import_button = self.bb.addButton(_('&Import image'), self.bb.ActionRole)
|
||||||
b.clicked.connect(self.import_image)
|
b.clicked.connect(self.import_image)
|
||||||
b.setIcon(QIcon(I('view-image.png')))
|
b.setIcon(QIcon(I('view-image.png')))
|
||||||
b.setToolTip(_('Import an image from elsewhere in your computer'))
|
b.setToolTip(_('Import an image from elsewhere in your computer'))
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
self.model.refresh()
|
||||||
|
|
||||||
def import_image(self):
|
def import_image(self):
|
||||||
path = choose_files(self, 'tweak-book-choose-image-for-import', _('Choose Image'),
|
path = choose_files(self, 'tweak-book-choose-image-for-import', _('Choose Image'),
|
||||||
filters=[(_('Images'), ('jpg', 'jpeg', 'png', 'gif', 'svg'))], all_files=True, select_only_single_file=True)
|
filters=[(_('Images'), ('jpg', 'jpeg', 'png', 'gif', 'svg'))], all_files=True, select_only_single_file=True)
|
||||||
@ -246,7 +274,13 @@ class InsertImage(Dialog):
|
|||||||
self.accept()
|
self.accept()
|
||||||
self.chosen_image_is_external = (d.filename, path)
|
self.chosen_image_is_external = (d.filename, path)
|
||||||
|
|
||||||
|
def pressed(self, index):
|
||||||
|
if QApplication.mouseButtons() & Qt.LeftButton:
|
||||||
|
self.activated(index)
|
||||||
|
|
||||||
def activated(self, index):
|
def activated(self, index):
|
||||||
|
if self.for_browsing:
|
||||||
|
return self.image_activated.emit(unicode(index.data().toString()))
|
||||||
self.chosen_image_is_external = False
|
self.chosen_image_is_external = False
|
||||||
self.accept()
|
self.accept()
|
||||||
|
|
||||||
|
@ -29,11 +29,12 @@ from calibre.gui2.tweak_book.search import SearchPanel
|
|||||||
from calibre.gui2.tweak_book.check import Check
|
from calibre.gui2.tweak_book.check import Check
|
||||||
from calibre.gui2.tweak_book.toc import TOCViewer
|
from calibre.gui2.tweak_book.toc import TOCViewer
|
||||||
from calibre.gui2.tweak_book.editor.widget import register_text_editor_actions
|
from calibre.gui2.tweak_book.editor.widget import register_text_editor_actions
|
||||||
|
from calibre.gui2.tweak_book.editor.insert_resource import InsertImage
|
||||||
|
|
||||||
def open_donate():
|
def open_donate():
|
||||||
open_url(QUrl('http://calibre-ebook.com/donate'))
|
open_url(QUrl('http://calibre-ebook.com/donate'))
|
||||||
|
|
||||||
class Central(QStackedWidget):
|
class Central(QStackedWidget): # {{{
|
||||||
|
|
||||||
' The central widget, hosts the editors '
|
' The central widget, hosts the editors '
|
||||||
|
|
||||||
@ -164,8 +165,9 @@ class Central(QStackedWidget):
|
|||||||
menu.exec_(self.editor_tabs.tabBar().mapToGlobal(event.pos()))
|
menu.exec_(self.editor_tabs.tabBar().mapToGlobal(event.pos()))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
# }}}
|
||||||
|
|
||||||
class CursorPositionWidget(QWidget):
|
class CursorPositionWidget(QWidget): # {{{
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QWidget.__init__(self, parent)
|
QWidget.__init__(self, parent)
|
||||||
@ -183,6 +185,7 @@ class CursorPositionWidget(QWidget):
|
|||||||
self.la.setText('')
|
self.la.setText('')
|
||||||
else:
|
else:
|
||||||
self.la.setText(_('Line: {0} : {1}').format(line, col))
|
self.la.setText(_('Line: {0} : {1}').format(line, col))
|
||||||
|
# }}}
|
||||||
|
|
||||||
class Main(MainWindow):
|
class Main(MainWindow):
|
||||||
|
|
||||||
@ -205,6 +208,7 @@ class Main(MainWindow):
|
|||||||
self.setCentralWidget(self.central)
|
self.setCentralWidget(self.central)
|
||||||
self.check_book = Check(self)
|
self.check_book = Check(self)
|
||||||
self.toc_view = TOCViewer(self)
|
self.toc_view = TOCViewer(self)
|
||||||
|
self.image_browser = InsertImage(self, for_browsing=True)
|
||||||
|
|
||||||
self.create_actions()
|
self.create_actions()
|
||||||
self.create_toolbars()
|
self.create_toolbars()
|
||||||
@ -374,6 +378,9 @@ class Main(MainWindow):
|
|||||||
self.action_help = reg(
|
self.action_help = reg(
|
||||||
'help.png', _('User &Manual'), lambda : open_url(QUrl('http://manual.calibre-ebook.com/edit.html')), 'user-manual', 'F1', _(
|
'help.png', _('User &Manual'), lambda : open_url(QUrl('http://manual.calibre-ebook.com/edit.html')), 'user-manual', 'F1', _(
|
||||||
'Show User Manual'))
|
'Show User Manual'))
|
||||||
|
self.action_browse_images = reg(
|
||||||
|
'view-image.png', _('&Browse images in book'), self.boss.browse_images, 'browse-images', (), _(
|
||||||
|
'Browse images in the books visually'))
|
||||||
|
|
||||||
def create_menubar(self):
|
def create_menubar(self):
|
||||||
p, q = self.create_application_menubar()
|
p, q = self.create_application_menubar()
|
||||||
@ -423,6 +430,7 @@ class Main(MainWindow):
|
|||||||
e.addAction(ac)
|
e.addAction(ac)
|
||||||
elif name.endswith('-bar'):
|
elif name.endswith('-bar'):
|
||||||
t.addAction(ac)
|
t.addAction(ac)
|
||||||
|
e.addAction(self.action_browse_images)
|
||||||
e.addSeparator()
|
e.addSeparator()
|
||||||
e.addAction(self.action_close_current_tab)
|
e.addAction(self.action_close_current_tab)
|
||||||
e.addAction(self.action_close_all_but_current_tab)
|
e.addAction(self.action_close_all_but_current_tab)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user