Allow right clicking on an author in Book Details

Allow right clicking on an author in Book Details to manage that author,
i.e. change the author name, sort value or link. Fixes #1186192 [Book Details Author right click - no options if file](https://bugs.launchpad.net/calibre/+bug/1186192)
This commit is contained in:
Kovid Goyal 2013-05-31 18:55:53 +05:30
parent 2692326607
commit d930de8753
3 changed files with 37 additions and 18 deletions

View File

@ -28,7 +28,7 @@ from calibre.utils.date import is_date_undefined
from calibre.utils.localization import calibre_langcode_to_name from calibre.utils.localization import calibre_langcode_to_name
from calibre.utils.config import tweaks from calibre.utils.config import tweaks
def render_html(mi, css, vertical, widget, all_fields=False): # {{{ def render_html(mi, css, vertical, widget, all_fields=False): # {{{
table = render_data(mi, all_fields=all_fields, table = render_data(mi, all_fields=all_fields,
use_roman_numbers=config['use_roman_numerals_for_series_number']) use_roman_numbers=config['use_roman_numerals_for_series_number'])
@ -158,14 +158,15 @@ def render_data(mi, use_roman_numbers=True, all_fields=False):
if isdevice: if isdevice:
durl = url durl = url
if durl.startswith('mtp:::'): if durl.startswith('mtp:::'):
durl = ':::'.join( (durl.split(':::'))[2:] ) durl = ':::'.join((durl.split(':::'))[2:])
extra = '<br><span style="font-size:smaller">%s</span>'%( extra = '<br><span style="font-size:smaller">%s</span>'%(
prepare_string_for_xml(durl)) prepare_string_for_xml(durl))
link = u'<a href="%s:%s" title="%s">%s</a>%s' % (scheme, url, link = u'<a href="%s:%s" title="%s">%s</a>%s' % (scheme, url,
prepare_string_for_xml(path, True), pathstr, extra) prepare_string_for_xml(path, True), pathstr, extra)
ans.append((field, u'<td class="title">%s</td><td>%s</td>'%(name, link))) ans.append((field, u'<td class="title">%s</td><td>%s</td>'%(name, link)))
elif field == 'formats': elif field == 'formats':
if isdevice: continue if isdevice:
continue
fmts = [u'<a href="format:%s:%s">%s</a>' % (mi.id, x, x) for x fmts = [u'<a href="format:%s:%s">%s</a>' % (mi.id, x, x) for x
in mi.formats] in mi.formats]
ans.append((field, u'<td class="title">%s</td><td>%s</td>'%(name, ans.append((field, u'<td class="title">%s</td><td>%s</td>'%(name,
@ -195,7 +196,7 @@ def render_data(mi, use_roman_numbers=True, all_fields=False):
gprefs.get('default_author_link'), vals, '', vals) gprefs.get('default_author_link'), vals, '', vals)
if link: if link:
link = prepare_string_for_xml(link) link = prepare_string_for_xml(link)
authors.append(u'<a href="%s">%s</a>'%(link, aut)) authors.append(u'<a calibre-data="authors" href="%s">%s</a>'%(link, aut))
else: else:
authors.append(aut) authors.append(aut)
ans.append((field, u'<td class="title">%s</td><td>%s</td>'%(name, ans.append((field, u'<td class="title">%s</td><td>%s</td>'%(name,
@ -246,7 +247,7 @@ def render_data(mi, use_roman_numbers=True, all_fields=False):
# }}} # }}}
class CoverView(QWidget): # {{{ class CoverView(QWidget): # {{{
cover_changed = pyqtSignal(object, object) cover_changed = pyqtSignal(object, object)
cover_removed = pyqtSignal(object) cover_removed = pyqtSignal(object)
@ -314,11 +315,13 @@ class CoverView(QWidget): # {{{
canvas_size = self.rect() canvas_size = self.rect()
width = self.current_pixmap_size.width() width = self.current_pixmap_size.width()
extrax = canvas_size.width() - width extrax = canvas_size.width() - width
if extrax < 0: extrax = 0 if extrax < 0:
extrax = 0
x = int(extrax/2.) x = int(extrax/2.)
height = self.current_pixmap_size.height() height = self.current_pixmap_size.height()
extray = canvas_size.height() - height extray = canvas_size.height() - height
if extray < 0: extray = 0 if extray < 0:
extray = 0
y = int(extray/2.) y = int(extray/2.)
target = QRect(x, y, width, height) target = QRect(x, y, width, height)
p = QPainter(self) p = QPainter(self)
@ -407,6 +410,7 @@ class BookInfo(QWebView):
save_format = pyqtSignal(int, object) save_format = pyqtSignal(int, object)
restore_format = pyqtSignal(int, object) restore_format = pyqtSignal(int, object)
copy_link = pyqtSignal(object) copy_link = pyqtSignal(object)
manage_author = pyqtSignal(object)
def __init__(self, vertical, parent=None): def __init__(self, vertical, parent=None):
QWebView.__init__(self, parent) QWebView.__init__(self, parent)
@ -420,7 +424,10 @@ class BookInfo(QWebView):
palette.setBrush(QPalette.Base, Qt.transparent) palette.setBrush(QPalette.Base, Qt.transparent)
self.page().setPalette(palette) self.page().setPalette(palette)
self.css = P('templates/book_details.css', data=True).decode('utf-8') self.css = P('templates/book_details.css', data=True).decode('utf-8')
for x, icon in [('remove_format', 'trash.png'), ('save_format', 'save.png'), ('restore_format', 'edit-undo.png'), ('copy_link','edit-copy.png')]: for x, icon in [
('remove_format', 'trash.png'), ('save_format', 'save.png'),
('restore_format', 'edit-undo.png'), ('copy_link','edit-copy.png'),
('manage_author', 'user_profile.png')]:
ac = QAction(QIcon(I(icon)), '', self) ac = QAction(QIcon(I(icon)), '', self)
ac.current_fmt = None ac.current_fmt = None
ac.current_url = None ac.current_url = None
@ -448,6 +455,9 @@ class BookInfo(QWebView):
def copy_link_triggerred(self): def copy_link_triggerred(self):
self.context_action_triggered('copy_link') self.context_action_triggered('copy_link')
def manage_author_triggerred(self):
self.manage_author.emit(self.manage_author_action.current_fmt)
def link_activated(self, link): def link_activated(self, link):
self._link_clicked = True self._link_clicked = True
if unicode(link.scheme()) in ('http', 'https'): if unicode(link.scheme()) in ('http', 'https'):
@ -483,13 +493,20 @@ class BookInfo(QWebView):
if action is not ca: if action is not ca:
menu.removeAction(action) menu.removeAction(action)
if not r.isNull(): if not r.isNull():
if url.startswith('http'): if url.startswith('http') or url.startswith('file:'):
el = r.linkElement()
author = el.toPlainText() if unicode(el.attribute('calibre-data')) == u'authors' else None
for a, t in [('copy', _('&Copy Link')), for a, t in [('copy', _('&Copy Link')),
]: ]:
ac = getattr(self, '%s_link_action'%a) ac = getattr(self, '%s_link_action'%a)
ac.current_url = url ac.current_url = url
ac.setText(t) ac.setText(t)
menu.addAction(ac) menu.addAction(ac)
if author is not None:
ac = self.manage_author_action
ac.current_fmt = author
ac.setText(_('Manage %s') % author)
menu.addAction(ac)
if url.startswith('format:'): if url.startswith('format:'):
parts = url.split(':') parts = url.split(':')
@ -515,7 +532,7 @@ class BookInfo(QWebView):
# }}} # }}}
class DetailsLayout(QLayout): # {{{ class DetailsLayout(QLayout): # {{{
def __init__(self, vertical, parent): def __init__(self, vertical, parent):
QLayout.__init__(self, parent) QLayout.__init__(self, parent)
@ -558,7 +575,8 @@ class DetailsLayout(QLayout): # {{{
self.do_layout(r) self.do_layout(r)
def cover_height(self, r): def cover_height(self, r):
if not self._children[0].widget().isVisible(): return 0 if not self._children[0].widget().isVisible():
return 0
mh = min(int(r.height()/2.), int(4/3. * r.width())+1) mh = min(int(r.height()/2.), int(4/3. * r.width())+1)
try: try:
ph = self._children[0].widget().pixmap.height() ph = self._children[0].widget().pixmap.height()
@ -569,7 +587,8 @@ class DetailsLayout(QLayout): # {{{
return mh return mh
def cover_width(self, r): def cover_width(self, r):
if not self._children[0].widget().isVisible(): return 0 if not self._children[0].widget().isVisible():
return 0
mw = 1 + int(3/4. * r.height()) mw = 1 + int(3/4. * r.height())
try: try:
pw = self._children[0].widget().pixmap.width() pw = self._children[0].widget().pixmap.width()
@ -579,7 +598,6 @@ class DetailsLayout(QLayout): # {{{
mw = min(mw, pw) mw = min(mw, pw)
return mw return mw
def do_layout(self, rect): def do_layout(self, rect):
if len(self._children) != 2: if len(self._children) != 2:
return return
@ -603,7 +621,7 @@ class DetailsLayout(QLayout): # {{{
# }}} # }}}
class BookDetails(QWidget): # {{{ class BookDetails(QWidget): # {{{
show_book_info = pyqtSignal() show_book_info = pyqtSignal()
open_containing_folder = pyqtSignal(int) open_containing_folder = pyqtSignal(int)
@ -617,6 +635,7 @@ class BookDetails(QWidget): # {{{
cover_changed = pyqtSignal(object, object) cover_changed = pyqtSignal(object, object)
cover_removed = pyqtSignal(object) cover_removed = pyqtSignal(object)
view_device_book = pyqtSignal(object) view_device_book = pyqtSignal(object)
manage_author = pyqtSignal(object)
# Drag 'n drop {{{ # Drag 'n drop {{{
DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS+BOOK_EXTENSIONS DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS+BOOK_EXTENSIONS
@ -659,7 +678,6 @@ class BookDetails(QWidget): # {{{
self.remote_file_dropped.emit(urls[0], filenames[0]) self.remote_file_dropped.emit(urls[0], filenames[0])
event.accept() event.accept()
def dragMoveEvent(self, event): def dragMoveEvent(self, event):
event.acceptProposedAction() event.acceptProposedAction()
@ -683,6 +701,7 @@ class BookDetails(QWidget): # {{{
self.book_info.save_format.connect(self.save_specific_format) self.book_info.save_format.connect(self.save_specific_format)
self.book_info.restore_format.connect(self.restore_specific_format) self.book_info.restore_format.connect(self.restore_specific_format)
self.book_info.copy_link.connect(self.copy_link) self.book_info.copy_link.connect(self.copy_link)
self.book_info.manage_author.connect(self.manage_author)
self.setCursor(Qt.PointingHandCursor) self.setCursor(Qt.PointingHandCursor)
def handle_click(self, link): def handle_click(self, link):
@ -701,7 +720,6 @@ class BookDetails(QWidget): # {{{
import traceback import traceback
traceback.print_exc() traceback.print_exc()
def mouseDoubleClickEvent(self, ev): def mouseDoubleClickEvent(self, ev):
ev.accept() ev.accept()
self.show_book_info.emit() self.show_book_info.emit()

View File

@ -71,7 +71,7 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog):
self.table.setItem(row, 0, aut) self.table.setItem(row, 0, aut)
self.table.setItem(row, 1, sort) self.table.setItem(row, 1, sort)
self.table.setItem(row, 2, link) self.table.setItem(row, 2, link)
if id == id_to_select: if id_to_select in (id, author):
if select_sort: if select_sort:
select_item = sort select_item = sort
elif select_link: elif select_link:

View File

@ -305,6 +305,7 @@ class LayoutMixin(object): # {{{
type=Qt.QueuedConnection) type=Qt.QueuedConnection)
self.book_details.view_device_book.connect( self.book_details.view_device_book.connect(
self.iactions['View'].view_device_book) self.iactions['View'].view_device_book)
self.book_details.manage_author.connect(lambda author:self.do_author_sort_edit(self, author, select_sort=False, select_link=False))
m = self.library_view.model() m = self.library_view.model()
if m.rowCount(None) > 0: if m.rowCount(None) > 0: