mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Show book details in a nice large window, when you click on the book details panel.
This commit is contained in:
parent
6e1c7118f5
commit
39950cf06d
50
src/calibre/gui2/dialogs/book_info.py
Normal file
50
src/calibre/gui2/dialogs/book_info.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
from PyQt4.QtCore import Qt
|
||||||
|
from PyQt4.QtGui import QDialog, QPixmap, QGraphicsScene, QIcon
|
||||||
|
|
||||||
|
from calibre.gui2.dialogs.book_info_ui import Ui_BookInfo
|
||||||
|
|
||||||
|
class BookInfo(QDialog, Ui_BookInfo):
|
||||||
|
|
||||||
|
def __init__(self, parent, info):
|
||||||
|
QDialog.__init__(self, parent)
|
||||||
|
Ui_BookInfo.__init__(self)
|
||||||
|
self.setupUi(self)
|
||||||
|
|
||||||
|
self.default_pixmap = QPixmap(':/images/book.svg').scaled(80,
|
||||||
|
100,
|
||||||
|
Qt.IgnoreAspectRatio,
|
||||||
|
Qt.SmoothTransformation)
|
||||||
|
|
||||||
|
self.setWindowTitle(info[_('Title')])
|
||||||
|
self.title.setText('<b>'+info.pop(_('Title')))
|
||||||
|
self.comments.setText(info.pop(_('Comments'), ''))
|
||||||
|
|
||||||
|
cdata = info.pop('cover', '')
|
||||||
|
pixmap = QPixmap()
|
||||||
|
pixmap.loadFromData(cdata)
|
||||||
|
if pixmap.isNull():
|
||||||
|
pixmap = self.default_pixmap
|
||||||
|
|
||||||
|
self.setWindowIcon(QIcon(pixmap))
|
||||||
|
|
||||||
|
self.scene = QGraphicsScene()
|
||||||
|
self.scene.addPixmap(pixmap)
|
||||||
|
self.cover.setScene(self.scene)
|
||||||
|
|
||||||
|
rows = u''
|
||||||
|
self.text.setText('')
|
||||||
|
self.data = info
|
||||||
|
for key in info.keys():
|
||||||
|
txt = info[key]
|
||||||
|
txt = u'<br />\n'.join(textwrap.wrap(txt, 120))
|
||||||
|
rows += u'<tr><td><b>%s:</b></td><td>%s</td></tr>'%(key, txt)
|
||||||
|
self.text.setText(u'<table>'+rows+'</table>')
|
73
src/calibre/gui2/dialogs/book_info.ui
Normal file
73
src/calibre/gui2/dialogs/book_info.ui
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<ui version="4.0" >
|
||||||
|
<class>BookInfo</class>
|
||||||
|
<widget class="QDialog" name="BookInfo" >
|
||||||
|
<property name="geometry" >
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>917</width>
|
||||||
|
<height>780</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle" >
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" >
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="title" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment" >
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSplitter" name="splitter" >
|
||||||
|
<property name="sizePolicy" >
|
||||||
|
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="orientation" >
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QGraphicsView" name="cover" />
|
||||||
|
<widget class="QWidget" name="" >
|
||||||
|
<layout class="QVBoxLayout" >
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="text" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment" >
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap" >
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox" >
|
||||||
|
<property name="title" >
|
||||||
|
<string>Comments</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" >
|
||||||
|
<item row="0" column="0" >
|
||||||
|
<widget class="QTextBrowser" name="comments" />
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -194,7 +194,7 @@ class BooksModel(QAbstractTableModel):
|
|||||||
def rowCount(self, parent):
|
def rowCount(self, parent):
|
||||||
return self.db.rows() if self.db else 0
|
return self.db.rows() if self.db else 0
|
||||||
|
|
||||||
def current_changed(self, current, previous):
|
def current_changed(self, current, previous, emit_signal=True):
|
||||||
data = {}
|
data = {}
|
||||||
idx = current.row()
|
idx = current.row()
|
||||||
cdata = self.db.cover(idx)
|
cdata = self.db.cover(idx)
|
||||||
@ -221,7 +221,22 @@ class BooksModel(QAbstractTableModel):
|
|||||||
sidx = self.db.series_index(idx)
|
sidx = self.db.series_index(idx)
|
||||||
sidx = self.__class__.roman(sidx) if self.use_roman_numbers else str(sidx)
|
sidx = self.__class__.roman(sidx) if self.use_roman_numbers else str(sidx)
|
||||||
data[_('Series')] = _('Book <font face="serif">%s</font> of %s.')%(sidx, series)
|
data[_('Series')] = _('Book <font face="serif">%s</font> of %s.')%(sidx, series)
|
||||||
self.emit(SIGNAL('new_bookdisplay_data(PyQt_PyObject)'), data)
|
if emit_signal:
|
||||||
|
self.emit(SIGNAL('new_bookdisplay_data(PyQt_PyObject)'), data)
|
||||||
|
else:
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_book_info(self, index):
|
||||||
|
data = self.current_changed(index, None, False)
|
||||||
|
row = index.row()
|
||||||
|
data[_('Title')] = self.db.title(row)
|
||||||
|
au = self.db.authors(row)
|
||||||
|
if not au:
|
||||||
|
au = _('Unknown')
|
||||||
|
au = ', '.join([a.strip() for a in au.split(',')])
|
||||||
|
data[_('Author(s)')] = au
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
def get_metadata(self, rows):
|
def get_metadata(self, rows):
|
||||||
metadata = []
|
metadata = []
|
||||||
|
@ -35,6 +35,7 @@ from calibre.gui2.dialogs.config import ConfigDialog
|
|||||||
from calibre.gui2.dialogs.search import SearchDialog
|
from calibre.gui2.dialogs.search import SearchDialog
|
||||||
from calibre.gui2.dialogs.user_profiles import UserProfiles
|
from calibre.gui2.dialogs.user_profiles import UserProfiles
|
||||||
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
|
from calibre.gui2.dialogs.choose_format import ChooseFormatDialog
|
||||||
|
from calibre.gui2.dialogs.book_info import BookInfo
|
||||||
from calibre.library.database import DatabaseLocked
|
from calibre.library.database import DatabaseLocked
|
||||||
from calibre.ebooks.metadata.meta import set_metadata
|
from calibre.ebooks.metadata.meta import set_metadata
|
||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
@ -96,6 +97,7 @@ class Main(MainWindow, Ui_MainWindow):
|
|||||||
Qt.QueuedConnection)
|
Qt.QueuedConnection)
|
||||||
QObject.connect(self.job_manager, SIGNAL('job_done(int)'), self.status_bar.job_done,
|
QObject.connect(self.job_manager, SIGNAL('job_done(int)'), self.status_bar.job_done,
|
||||||
Qt.QueuedConnection)
|
Qt.QueuedConnection)
|
||||||
|
QObject.connect(self.status_bar, SIGNAL('show_book_info()'), self.show_book_info)
|
||||||
|
|
||||||
####################### Setup Toolbar #####################
|
####################### Setup Toolbar #####################
|
||||||
sm = QMenu()
|
sm = QMenu()
|
||||||
@ -905,6 +907,20 @@ class Main(MainWindow, Ui_MainWindow):
|
|||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
|
|
||||||
|
################################ Book info #################################
|
||||||
|
|
||||||
|
def show_book_info(self):
|
||||||
|
if self.current_view() is not self.library_view:
|
||||||
|
error_dialog(self, _('No detailed info available'),
|
||||||
|
_('No detailed information is available for books on the device.')).exec_()
|
||||||
|
return
|
||||||
|
index = self.library_view.currentIndex()
|
||||||
|
if index.isValid():
|
||||||
|
info = self.library_view.model().get_book_info(index)
|
||||||
|
BookInfo(self, info).show()
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
def location_selected(self, location):
|
def location_selected(self, location):
|
||||||
'''
|
'''
|
||||||
|
@ -4,7 +4,7 @@ import textwrap
|
|||||||
|
|
||||||
from PyQt4.QtGui import QStatusBar, QMovie, QLabel, QFrame, QHBoxLayout, QPixmap, \
|
from PyQt4.QtGui import QStatusBar, QMovie, QLabel, QFrame, QHBoxLayout, QPixmap, \
|
||||||
QVBoxLayout, QSizePolicy
|
QVBoxLayout, QSizePolicy
|
||||||
from PyQt4.QtCore import Qt, QSize
|
from PyQt4.QtCore import Qt, QSize, SIGNAL
|
||||||
from calibre import fit_image
|
from calibre import fit_image
|
||||||
from calibre.gui2 import qstring_to_unicode
|
from calibre.gui2 import qstring_to_unicode
|
||||||
|
|
||||||
@ -39,20 +39,29 @@ class BookInfoDisplay(QFrame):
|
|||||||
class BookDataDisplay(QLabel):
|
class BookDataDisplay(QLabel):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
QLabel.__init__(self)
|
QLabel.__init__(self)
|
||||||
self.setTextInteractionFlags(Qt.TextSelectableByMouse)
|
#self.setTextInteractionFlags(Qt.TextSelectableByMouse)
|
||||||
self.setText('')
|
self.setText('')
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, ev):
|
||||||
|
self.emit(SIGNAL('mr(int)'), 1)
|
||||||
|
|
||||||
def __init__(self, clear_message):
|
def __init__(self, clear_message):
|
||||||
QFrame.__init__(self)
|
QFrame.__init__(self)
|
||||||
|
self.setCursor(Qt.PointingHandCursor)
|
||||||
self.clear_message = clear_message
|
self.clear_message = clear_message
|
||||||
self.layout = QHBoxLayout()
|
self.layout = QHBoxLayout()
|
||||||
self.setLayout(self.layout)
|
self.setLayout(self.layout)
|
||||||
self.cover_display = BookInfoDisplay.BookCoverDisplay()
|
self.cover_display = BookInfoDisplay.BookCoverDisplay()
|
||||||
self.layout.addWidget(self.cover_display)
|
self.layout.addWidget(self.cover_display)
|
||||||
self.book_data = BookInfoDisplay.BookDataDisplay()
|
self.book_data = BookInfoDisplay.BookDataDisplay()
|
||||||
|
self.connect(self.book_data, SIGNAL('mr(int)'), self.mouseReleaseEvent)
|
||||||
self.layout.addWidget(self.book_data)
|
self.layout.addWidget(self.book_data)
|
||||||
|
self.data = {}
|
||||||
self.setVisible(False)
|
self.setVisible(False)
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, ev):
|
||||||
|
self.emit(SIGNAL('show_book_info()'))
|
||||||
|
|
||||||
def show_data(self, data):
|
def show_data(self, data):
|
||||||
if data.has_key('cover'):
|
if data.has_key('cover'):
|
||||||
cover_data = data.pop('cover')
|
cover_data = data.pop('cover')
|
||||||
@ -67,8 +76,12 @@ class BookInfoDisplay(QFrame):
|
|||||||
|
|
||||||
rows = u''
|
rows = u''
|
||||||
self.book_data.setText('')
|
self.book_data.setText('')
|
||||||
|
self.data = data
|
||||||
for key in data.keys():
|
for key in data.keys():
|
||||||
txt = '<br />\n'.join(textwrap.wrap(data[key], 120))
|
txt = data[key]
|
||||||
|
if len(txt) > 600:
|
||||||
|
txt = txt[:600]+'…'
|
||||||
|
txt = '<br />\n'.join(textwrap.wrap(txt, 120))
|
||||||
rows += '<tr><td><b>%s:</b></td><td>%s</td></tr>'%(key, txt)
|
rows += '<tr><td><b>%s:</b></td><td>%s</td></tr>'%(key, txt)
|
||||||
self.book_data.setText('<table>'+rows+'</table>')
|
self.book_data.setText('<table>'+rows+'</table>')
|
||||||
|
|
||||||
@ -115,6 +128,7 @@ class StatusBar(QStatusBar):
|
|||||||
self.movie_button = MovieButton(QMovie(':/images/jobs-animated.mng'), jobs_dialog)
|
self.movie_button = MovieButton(QMovie(':/images/jobs-animated.mng'), jobs_dialog)
|
||||||
self.addPermanentWidget(self.movie_button)
|
self.addPermanentWidget(self.movie_button)
|
||||||
self.book_info = BookInfoDisplay(self.clearMessage)
|
self.book_info = BookInfoDisplay(self.clearMessage)
|
||||||
|
self.connect(self.book_info, SIGNAL('show_book_info()'), self.show_book_info)
|
||||||
self.addWidget(self.book_info)
|
self.addWidget(self.book_info)
|
||||||
|
|
||||||
def reset_info(self):
|
def reset_info(self):
|
||||||
@ -124,6 +138,8 @@ class StatusBar(QStatusBar):
|
|||||||
src = qstring_to_unicode(self.movie_button.jobs.text())
|
src = qstring_to_unicode(self.movie_button.jobs.text())
|
||||||
return int(src.rpartition(':')[2].lstrip())
|
return int(src.rpartition(':')[2].lstrip())
|
||||||
|
|
||||||
|
def show_book_info(self):
|
||||||
|
self.emit(SIGNAL('show_book_info()'))
|
||||||
|
|
||||||
def job_added(self, id):
|
def job_added(self, id):
|
||||||
jobs = self.movie_button.jobs
|
jobs = self.movie_button.jobs
|
||||||
|
@ -908,7 +908,7 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
|||||||
return self.conn.execute('SELECT title FROM meta WHERE id=?',(index,)).fetchone()[0]
|
return self.conn.execute('SELECT title FROM meta WHERE id=?',(index,)).fetchone()[0]
|
||||||
|
|
||||||
def authors(self, index, index_is_id=False):
|
def authors(self, index, index_is_id=False):
|
||||||
''' Authors as a comman separated list or None'''
|
''' Authors as a comma separated list or None'''
|
||||||
if not index_is_id:
|
if not index_is_id:
|
||||||
return self.data[index][2]
|
return self.data[index][2]
|
||||||
return self.conn.execute('SELECT authors FROM meta WHERE id=?',(index,)).fetchone()[0]
|
return self.conn.execute('SELECT authors FROM meta WHERE id=?',(index,)).fetchone()[0]
|
||||||
|
@ -231,7 +231,8 @@ Book Details
|
|||||||
-------------
|
-------------
|
||||||
.. image:: images/book_details.png
|
.. image:: images/book_details.png
|
||||||
|
|
||||||
The Book Details display shows you extra information and the cover for the currently selected book.
|
The Book Details display shows you extra information and the cover for the currently selected book. THe comments section is truncated if the comments are too long. To see the full comments as well as
|
||||||
|
a larger image of the cover, click anywhere in the Book Details area.
|
||||||
|
|
||||||
.. _jobs:
|
.. _jobs:
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user