mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Make the path and formats data in the book details pane clickable
This commit is contained in:
parent
ac4c623c39
commit
760bc3ed37
@ -1064,6 +1064,12 @@ class ViewAction(object): # {{{
|
|||||||
if fmt_path:
|
if fmt_path:
|
||||||
self._view_file(fmt_path)
|
self._view_file(fmt_path)
|
||||||
|
|
||||||
|
def view_format_by_id(self, id_, format):
|
||||||
|
fmt_path = self.library_view.model().db.format_abspath(id_, format,
|
||||||
|
index_is_id=True)
|
||||||
|
if fmt_path:
|
||||||
|
self._view_file(fmt_path)
|
||||||
|
|
||||||
def metadata_view_format(self, fmt):
|
def metadata_view_format(self, fmt):
|
||||||
fmt_path = self.library_view.model().db.\
|
fmt_path = self.library_view.model().db.\
|
||||||
format_abspath(self._metadata_view_id,
|
format_abspath(self._metadata_view_id,
|
||||||
@ -1146,6 +1152,9 @@ class ViewAction(object): # {{{
|
|||||||
path = self.library_view.model().db.abspath(row.row())
|
path = self.library_view.model().db.abspath(row.row())
|
||||||
QDesktopServices.openUrl(QUrl.fromLocalFile(path))
|
QDesktopServices.openUrl(QUrl.fromLocalFile(path))
|
||||||
|
|
||||||
|
def view_folder_for_id(self, id_):
|
||||||
|
path = self.library_view.model().db.abspath(id_, index_is_id=True)
|
||||||
|
QDesktopServices.openUrl(QUrl.fromLocalFile(path))
|
||||||
|
|
||||||
def view_book(self, triggered):
|
def view_book(self, triggered):
|
||||||
rows = self.current_view().selectionModel().selectedRows()
|
rows = self.current_view().selectionModel().selectedRows()
|
||||||
|
@ -121,6 +121,7 @@ class BookInfo(QDialog, Ui_BookInfo):
|
|||||||
f = f.strip()
|
f = f.strip()
|
||||||
info[_('Formats')] += '<a href="%s">%s</a>, '%(f,f)
|
info[_('Formats')] += '<a href="%s">%s</a>, '%(f,f)
|
||||||
for key in info.keys():
|
for key in info.keys():
|
||||||
|
if key == 'id': continue
|
||||||
txt = info[key]
|
txt = info[key]
|
||||||
txt = u'<br />\n'.join(textwrap.wrap(txt, 120))
|
txt = u'<br />\n'.join(textwrap.wrap(txt, 120))
|
||||||
rows += u'<tr><td><b>%s:</b></td><td>%s</td></tr>'%(key, txt)
|
rows += u'<tr><td><b>%s:</b></td><td>%s</td></tr>'%(key, txt)
|
||||||
|
@ -21,7 +21,7 @@ from calibre.utils.date import dt_factory, qt_to_dt, isoformat
|
|||||||
from calibre.ebooks.metadata.meta import set_metadata as _set_metadata
|
from calibre.ebooks.metadata.meta import set_metadata as _set_metadata
|
||||||
from calibre.utils.search_query_parser import SearchQueryParser
|
from calibre.utils.search_query_parser import SearchQueryParser
|
||||||
from calibre.library.caches import _match, CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH
|
from calibre.library.caches import _match, CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH
|
||||||
from calibre import strftime, isbytestring
|
from calibre import strftime, isbytestring, prepare_string_for_xml
|
||||||
from calibre.constants import filesystem_encoding
|
from calibre.constants import filesystem_encoding
|
||||||
from calibre.gui2.library import DEFAULT_SORT
|
from calibre.gui2.library import DEFAULT_SORT
|
||||||
|
|
||||||
@ -300,6 +300,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
formats = _('None')
|
formats = _('None')
|
||||||
data[_('Formats')] = formats
|
data[_('Formats')] = formats
|
||||||
data[_('Path')] = self.db.abspath(idx)
|
data[_('Path')] = self.db.abspath(idx)
|
||||||
|
data['id'] = self.id(idx)
|
||||||
comments = self.db.comments(idx)
|
comments = self.db.comments(idx)
|
||||||
if not comments:
|
if not comments:
|
||||||
comments = _('None')
|
comments = _('None')
|
||||||
@ -308,7 +309,9 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
if series:
|
if series:
|
||||||
sidx = self.db.series_index(idx)
|
sidx = self.db.series_index(idx)
|
||||||
sidx = fmt_sidx(sidx, use_roman = self.use_roman_numbers)
|
sidx = fmt_sidx(sidx, use_roman = self.use_roman_numbers)
|
||||||
data[_('Series')] = _('Book <font face="serif">%s</font> of %s.')%(sidx, series)
|
data[_('Series')] = \
|
||||||
|
_('Book <font face="serif">%s</font> of %s.')%\
|
||||||
|
(sidx, prepare_string_for_xml(series))
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
import os, collections
|
|
||||||
|
import os
|
||||||
|
|
||||||
from PyQt4.Qt import QStatusBar, QLabel, QWidget, QHBoxLayout, QPixmap, \
|
from PyQt4.Qt import QStatusBar, QLabel, QWidget, QHBoxLayout, QPixmap, \
|
||||||
QSizePolicy, QScrollArea, Qt, QSize, pyqtSignal, \
|
QSizePolicy, QScrollArea, Qt, QSize, pyqtSignal, \
|
||||||
@ -13,6 +14,7 @@ from calibre.gui2.widgets import IMAGE_EXTENSIONS
|
|||||||
from calibre.gui2.notify import get_notifier
|
from calibre.gui2.notify import get_notifier
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
from calibre.library.comments import comments_to_html
|
from calibre.library.comments import comments_to_html
|
||||||
|
from calibre.gui2.book_details import render_rows
|
||||||
|
|
||||||
class BookInfoDisplay(QWidget):
|
class BookInfoDisplay(QWidget):
|
||||||
|
|
||||||
@ -91,24 +93,27 @@ class BookInfoDisplay(QWidget):
|
|||||||
|
|
||||||
class BookDataDisplay(QLabel):
|
class BookDataDisplay(QLabel):
|
||||||
|
|
||||||
mr = pyqtSignal(int)
|
mr = pyqtSignal(object)
|
||||||
|
link_clicked = pyqtSignal(object)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
QLabel.__init__(self)
|
QLabel.__init__(self)
|
||||||
self.setText('')
|
self.setText('')
|
||||||
self.setWordWrap(True)
|
self.setWordWrap(True)
|
||||||
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
||||||
|
self.linkActivated.connect(self.link_activated)
|
||||||
|
self._link_clicked = False
|
||||||
|
|
||||||
def mouseReleaseEvent(self, ev):
|
def mouseReleaseEvent(self, ev):
|
||||||
self.mr.emit(1)
|
QLabel.mouseReleaseEvent(self, ev)
|
||||||
|
if not self._link_clicked:
|
||||||
|
self.mr.emit(ev)
|
||||||
|
self._link_clicked = False
|
||||||
|
|
||||||
WEIGHTS = collections.defaultdict(lambda : 100)
|
def link_activated(self, link):
|
||||||
WEIGHTS[_('Path')] = 0
|
self._link_clicked = True
|
||||||
WEIGHTS[_('Formats')] = 1
|
link = unicode(link)
|
||||||
WEIGHTS[_('Collections')] = 2
|
self.link_clicked.emit(link)
|
||||||
WEIGHTS[_('Series')] = 3
|
|
||||||
WEIGHTS[_('Tags')] = 4
|
|
||||||
WEIGHTS[_('Comments')] = 5
|
|
||||||
|
|
||||||
show_book_info = pyqtSignal()
|
show_book_info = pyqtSignal()
|
||||||
|
|
||||||
@ -129,6 +134,7 @@ class BookInfoDisplay(QWidget):
|
|||||||
self._layout.setAlignment(self.cover_display, Qt.AlignTop|Qt.AlignLeft)
|
self._layout.setAlignment(self.cover_display, Qt.AlignTop|Qt.AlignLeft)
|
||||||
|
|
||||||
def mouseReleaseEvent(self, ev):
|
def mouseReleaseEvent(self, ev):
|
||||||
|
ev.accept()
|
||||||
self.show_book_info.emit()
|
self.show_book_info.emit()
|
||||||
|
|
||||||
def show_data(self, data):
|
def show_data(self, data):
|
||||||
@ -140,23 +146,11 @@ class BookInfoDisplay(QWidget):
|
|||||||
rows, comments = [], ''
|
rows, comments = [], ''
|
||||||
self.book_data.setText('')
|
self.book_data.setText('')
|
||||||
self.data = data.copy()
|
self.data = data.copy()
|
||||||
keys = data.keys()
|
rows = render_rows(self.data)
|
||||||
keys.sort(cmp=lambda x, y: cmp(self.WEIGHTS[x], self.WEIGHTS[y]))
|
|
||||||
for key in keys:
|
|
||||||
txt = data[key]
|
|
||||||
if not txt or not txt.strip() or txt == 'None':
|
|
||||||
continue
|
|
||||||
if isinstance(key, str):
|
|
||||||
key = key.decode(preferred_encoding, 'replace')
|
|
||||||
if isinstance(txt, str):
|
|
||||||
txt = txt.decode(preferred_encoding, 'replace')
|
|
||||||
if key == _('Comments'):
|
|
||||||
comments = comments_to_html(txt)
|
|
||||||
else:
|
|
||||||
rows.append((key, txt))
|
|
||||||
rows = '\n'.join([u'<tr><td valign="top"><b>%s:</b></td><td valign="top">%s</td></tr>'%(k,t) for
|
rows = '\n'.join([u'<tr><td valign="top"><b>%s:</b></td><td valign="top">%s</td></tr>'%(k,t) for
|
||||||
k, t in rows])
|
k, t in rows])
|
||||||
if comments:
|
if _('Comments') in self.data:
|
||||||
|
comments = comments_to_html(self.data[_('Comments')])
|
||||||
comments = '<b>Comments:</b>'+comments
|
comments = '<b>Comments:</b>'+comments
|
||||||
left_pane = u'<table>%s</table>'%rows
|
left_pane = u'<table>%s</table>'%rows
|
||||||
right_pane = u'<div>%s</div>'%comments
|
right_pane = u'<div>%s</div>'%comments
|
||||||
@ -193,6 +187,8 @@ class BookDetailsInterface(object):
|
|||||||
# These signals must be defined in the class implementing this interface
|
# These signals must be defined in the class implementing this interface
|
||||||
files_dropped = None
|
files_dropped = None
|
||||||
show_book_info = None
|
show_book_info = None
|
||||||
|
open_containing_folder = None
|
||||||
|
view_specific_format = None
|
||||||
|
|
||||||
def reset_info(self):
|
def reset_info(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
@ -204,7 +200,8 @@ class StatusBar(QStatusBar, StatusBarInterface, BookDetailsInterface):
|
|||||||
|
|
||||||
files_dropped = pyqtSignal(object, object)
|
files_dropped = pyqtSignal(object, object)
|
||||||
show_book_info = pyqtSignal()
|
show_book_info = pyqtSignal()
|
||||||
|
open_containing_folder = pyqtSignal(int)
|
||||||
|
view_specific_format = pyqtSignal(int, object)
|
||||||
|
|
||||||
resized = pyqtSignal(object)
|
resized = pyqtSignal(object)
|
||||||
|
|
||||||
@ -219,11 +216,21 @@ class StatusBar(QStatusBar, StatusBarInterface, BookDetailsInterface):
|
|||||||
type=Qt.QueuedConnection)
|
type=Qt.QueuedConnection)
|
||||||
self.book_info.files_dropped.connect(self.files_dropped.emit,
|
self.book_info.files_dropped.connect(self.files_dropped.emit,
|
||||||
type=Qt.QueuedConnection)
|
type=Qt.QueuedConnection)
|
||||||
|
self.book_info.book_data.link_clicked.connect(self._link_clicked)
|
||||||
self.addWidget(self.scroll_area, 100)
|
self.addWidget(self.scroll_area, 100)
|
||||||
self.setMinimumHeight(120)
|
self.setMinimumHeight(120)
|
||||||
self.resized.connect(self.book_info.cover_display.relayout)
|
self.resized.connect(self.book_info.cover_display.relayout)
|
||||||
self.book_info.cover_display.relayout(self.size())
|
self.book_info.cover_display.relayout(self.size())
|
||||||
|
|
||||||
|
|
||||||
|
def _link_clicked(self, link):
|
||||||
|
typ, _, val = link.partition(':')
|
||||||
|
if typ == 'path':
|
||||||
|
self.open_containing_folder.emit(int(val))
|
||||||
|
if typ == 'format':
|
||||||
|
id_, fmt = val.split(':')
|
||||||
|
self.view_specific_format.emit(int(id_), fmt)
|
||||||
|
|
||||||
def resizeEvent(self, ev):
|
def resizeEvent(self, ev):
|
||||||
self.resized.emit(self.size())
|
self.resized.emit(self.size())
|
||||||
|
|
||||||
|
@ -219,6 +219,8 @@ class Main(MainWindow, Ui_MainWindow, DeviceMixin, ToolbarMixin, # {{{
|
|||||||
self.status_bar.initialize(self.system_tray_icon)
|
self.status_bar.initialize(self.system_tray_icon)
|
||||||
self.book_details.show_book_info.connect(self.show_book_info)
|
self.book_details.show_book_info.connect(self.show_book_info)
|
||||||
self.book_details.files_dropped.connect(self.files_dropped_on_book)
|
self.book_details.files_dropped.connect(self.files_dropped_on_book)
|
||||||
|
self.book_details.open_containing_folder.connect(self.view_folder_for_id)
|
||||||
|
self.book_details.view_specific_format.connect(self.view_format_by_id)
|
||||||
|
|
||||||
####################### Setup Toolbar #####################
|
####################### Setup Toolbar #####################
|
||||||
ToolbarMixin.__init__(self)
|
ToolbarMixin.__init__(self)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user