mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
Separate status bar and book details in narrow alyout as well
This commit is contained in:
parent
41c5a60920
commit
e266303706
@ -33,7 +33,7 @@
|
|||||||
<linearGradient
|
<linearGradient
|
||||||
id="linearGradient4562">
|
id="linearGradient4562">
|
||||||
<stop
|
<stop
|
||||||
style="stop-color:#44bd0f;stop-opacity:1;"
|
style="stop-color:#80f14f;stop-opacity:0.84967321;"
|
||||||
offset="0"
|
offset="0"
|
||||||
id="stop4564" />
|
id="stop4564" />
|
||||||
<stop
|
<stop
|
||||||
@ -170,7 +170,7 @@
|
|||||||
inkscape:pageopacity="0.0"
|
inkscape:pageopacity="0.0"
|
||||||
inkscape:pageshadow="2"
|
inkscape:pageshadow="2"
|
||||||
inkscape:zoom="8"
|
inkscape:zoom="8"
|
||||||
inkscape:cx="-12.249465"
|
inkscape:cx="6.9888402"
|
||||||
inkscape:cy="28.945566"
|
inkscape:cy="28.945566"
|
||||||
inkscape:current-layer="layer2"
|
inkscape:current-layer="layer2"
|
||||||
showgrid="false"
|
showgrid="false"
|
||||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@ -62,11 +62,13 @@ def render_rows(data):
|
|||||||
class CoverView(QWidget): # {{{
|
class CoverView(QWidget): # {{{
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, vertical, parent=None):
|
||||||
QWidget.__init__(self, parent)
|
QWidget.__init__(self, parent)
|
||||||
self.setMaximumSize(QSize(120, 120))
|
self.setMaximumSize(QSize(120, 120))
|
||||||
self.setMinimumSize(QSize(120, 1))
|
self.setMinimumSize(QSize(120 if vertical else 20, 120 if vertical else
|
||||||
|
20))
|
||||||
self._current_pixmap_size = self.maximumSize()
|
self._current_pixmap_size = self.maximumSize()
|
||||||
|
self.vertical = vertical
|
||||||
|
|
||||||
self.animation = QPropertyAnimation(self, 'current_pixmap_size', self)
|
self.animation = QPropertyAnimation(self, 'current_pixmap_size', self)
|
||||||
self.animation.setEasingCurve(QEasingCurve(QEasingCurve.OutExpo))
|
self.animation.setEasingCurve(QEasingCurve(QEasingCurve.OutExpo))
|
||||||
@ -74,7 +76,8 @@ class CoverView(QWidget): # {{{
|
|||||||
self.animation.setStartValue(QSize(0, 0))
|
self.animation.setStartValue(QSize(0, 0))
|
||||||
self.animation.valueChanged.connect(self.value_changed)
|
self.animation.valueChanged.connect(self.value_changed)
|
||||||
|
|
||||||
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
self.setSizePolicy(QSizePolicy.Expanding if vertical else
|
||||||
|
QSizePolicy.Minimum, QSizePolicy.Expanding)
|
||||||
|
|
||||||
self.default_pixmap = QPixmap(I('book.svg'))
|
self.default_pixmap = QPixmap(I('book.svg'))
|
||||||
self.pixmap = self.default_pixmap
|
self.pixmap = self.default_pixmap
|
||||||
@ -98,8 +101,12 @@ class CoverView(QWidget): # {{{
|
|||||||
self.animation.setEndValue(self.current_pixmap_size)
|
self.animation.setEndValue(self.current_pixmap_size)
|
||||||
|
|
||||||
def relayout(self, parent_size):
|
def relayout(self, parent_size):
|
||||||
|
if self.vertical:
|
||||||
self.setMaximumSize(parent_size.width(),
|
self.setMaximumSize(parent_size.width(),
|
||||||
min(int(parent_size.height()/2.),int(4/3. * parent_size.width())+1))
|
min(int(parent_size.height()/2.),int(4/3. * parent_size.width())+1))
|
||||||
|
else:
|
||||||
|
self.setMaximumSize(1+int(3/4. * parent_size.height()),
|
||||||
|
parent_size.height())
|
||||||
self.resize(self.maximumSize())
|
self.resize(self.maximumSize())
|
||||||
self.animation.stop()
|
self.animation.stop()
|
||||||
self.do_layout()
|
self.do_layout()
|
||||||
@ -109,8 +116,7 @@ class CoverView(QWidget): # {{{
|
|||||||
|
|
||||||
def show_data(self, data):
|
def show_data(self, data):
|
||||||
self.animation.stop()
|
self.animation.stop()
|
||||||
if data.get('id', True) == self.data.get('id', False):
|
same_item = data.get('id', True) == self.data.get('id', False)
|
||||||
return
|
|
||||||
self.data = {'id':data.get('id', None)}
|
self.data = {'id':data.get('id', None)}
|
||||||
if data.has_key('cover'):
|
if data.has_key('cover'):
|
||||||
self.pixmap = QPixmap.fromImage(data.pop('cover'))
|
self.pixmap = QPixmap.fromImage(data.pop('cover'))
|
||||||
@ -120,6 +126,7 @@ class CoverView(QWidget): # {{{
|
|||||||
self.pixmap = self.default_pixmap
|
self.pixmap = self.default_pixmap
|
||||||
self.do_layout()
|
self.do_layout()
|
||||||
self.update()
|
self.update()
|
||||||
|
if not same_item:
|
||||||
self.animation.start()
|
self.animation.start()
|
||||||
|
|
||||||
def paintEvent(self, event):
|
def paintEvent(self, event):
|
||||||
@ -147,6 +154,7 @@ class CoverView(QWidget): # {{{
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
# Book Info {{{
|
||||||
class Label(QLabel):
|
class Label(QLabel):
|
||||||
|
|
||||||
mr = pyqtSignal(object)
|
mr = pyqtSignal(object)
|
||||||
@ -174,8 +182,9 @@ class Label(QLabel):
|
|||||||
|
|
||||||
class BookInfo(QScrollArea):
|
class BookInfo(QScrollArea):
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, vertical, parent=None):
|
||||||
QScrollArea.__init__(self, parent)
|
QScrollArea.__init__(self, parent)
|
||||||
|
self.vertical = vertical
|
||||||
self.setWidgetResizable(True)
|
self.setWidgetResizable(True)
|
||||||
self.label = Label()
|
self.label = Label()
|
||||||
self.setWidget(self.label)
|
self.setWidget(self.label)
|
||||||
@ -188,13 +197,25 @@ class BookInfo(QScrollArea):
|
|||||||
rows = render_rows(data)
|
rows = render_rows(data)
|
||||||
rows = u'\n'.join([u'<tr><td valign="top"><b>%s:</b></td><td valign="top">%s</td></tr>'%(k,t) for
|
rows = u'\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 self.vertical:
|
||||||
if _('Comments') in data and data[_('Comments')]:
|
if _('Comments') in data and data[_('Comments')]:
|
||||||
comments = comments_to_html(data[_('Comments')])
|
comments = comments_to_html(data[_('Comments')])
|
||||||
rows += u'<tr><td colspan="2">%s</td></tr>'%comments
|
rows += u'<tr><td colspan="2">%s</td></tr>'%comments
|
||||||
|
|
||||||
self.label.setText(u'<table>%s</table>'%rows)
|
self.label.setText(u'<table>%s</table>'%rows)
|
||||||
|
else:
|
||||||
|
comments = ''
|
||||||
|
if _('Comments') in data:
|
||||||
|
comments = comments_to_html(data[_('Comments')])
|
||||||
|
left_pane = u'<table>%s</table>'%rows
|
||||||
|
right_pane = u'<div>%s</div>'%comments
|
||||||
|
self.label.setText(u'<table><tr><td valign="top" '
|
||||||
|
'style="padding-right:2em">%s</td><td valign="top">%s</td></tr></table>'
|
||||||
|
% (left_pane, right_pane))
|
||||||
|
|
||||||
class BookDetails(QWidget):
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
class BookDetails(QWidget): # {{{
|
||||||
|
|
||||||
resized = pyqtSignal(object)
|
resized = pyqtSignal(object)
|
||||||
show_book_info = pyqtSignal()
|
show_book_info = pyqtSignal()
|
||||||
@ -234,20 +255,26 @@ class BookDetails(QWidget):
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, vertical, parent=None):
|
||||||
QWidget.__init__(self, parent)
|
QWidget.__init__(self, parent)
|
||||||
|
self.setAcceptDrops(True)
|
||||||
self._layout = QVBoxLayout()
|
self._layout = QVBoxLayout()
|
||||||
|
if not vertical:
|
||||||
|
self._layout.setDirection(self._layout.LeftToRight)
|
||||||
self.setLayout(self._layout)
|
self.setLayout(self._layout)
|
||||||
self.cover_view = CoverView(self)
|
|
||||||
|
self.cover_view = CoverView(vertical, self)
|
||||||
self.cover_view.relayout(self.size())
|
self.cover_view.relayout(self.size())
|
||||||
self.resized.connect(self.cover_view.relayout, type=Qt.QueuedConnection)
|
self.resized.connect(self.cover_view.relayout, type=Qt.QueuedConnection)
|
||||||
self._layout.addWidget(self.cover_view, alignment=Qt.AlignHCenter)
|
self._layout.addWidget(self.cover_view)
|
||||||
self.book_info = BookInfo(self)
|
self.book_info = BookInfo(vertical, self)
|
||||||
self._layout.addWidget(self.book_info)
|
self._layout.addWidget(self.book_info)
|
||||||
self.book_info.link_clicked.connect(self._link_clicked)
|
self.book_info.link_clicked.connect(self._link_clicked)
|
||||||
self.book_info.mr.connect(self.mouseReleaseEvent)
|
self.book_info.mr.connect(self.mouseReleaseEvent)
|
||||||
|
if vertical:
|
||||||
self.setMinimumSize(QSize(190, 200))
|
self.setMinimumSize(QSize(190, 200))
|
||||||
|
else:
|
||||||
|
self.setMinimumSize(120, 120)
|
||||||
self.setCursor(Qt.PointingHandCursor)
|
self.setCursor(Qt.PointingHandCursor)
|
||||||
|
|
||||||
def _link_clicked(self, link):
|
def _link_clicked(self, link):
|
||||||
@ -277,5 +304,5 @@ class BookDetails(QWidget):
|
|||||||
def reset_info(self):
|
def reset_info(self):
|
||||||
self.show_data({})
|
self.show_data({})
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>884</width>
|
<width>1000</width>
|
||||||
<height>730</height>
|
<height>730</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -89,7 +89,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>604</width>
|
<width>720</width>
|
||||||
<height>679</height>
|
<height>679</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -370,7 +370,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="5" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="show_avg_rating">
|
<widget class="QCheckBox" name="show_avg_rating">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show &average ratings in the tags browser</string>
|
<string>Show &average ratings in the tags browser</string>
|
||||||
|
@ -8,17 +8,18 @@ __docformat__ = 'restructuredtext en'
|
|||||||
import functools
|
import functools
|
||||||
|
|
||||||
from PyQt4.Qt import QMenu, Qt, pyqtSignal, QToolButton, QIcon, QStackedWidget, \
|
from PyQt4.Qt import QMenu, Qt, pyqtSignal, QToolButton, QIcon, QStackedWidget, \
|
||||||
QWidget, QHBoxLayout, QToolBar, QSize, QSizePolicy
|
QWidget, QHBoxLayout, QToolBar, QSize, QSizePolicy, QStatusBar
|
||||||
|
|
||||||
from calibre.utils.config import prefs
|
from calibre.utils.config import prefs
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
from calibre.constants import isosx, __appname__
|
from calibre.constants import isosx, __appname__, preferred_encoding
|
||||||
from calibre.gui2 import config, is_widescreen
|
from calibre.gui2 import config, is_widescreen
|
||||||
from calibre.gui2.library.views import BooksView, DeviceBooksView
|
from calibre.gui2.library.views import BooksView, DeviceBooksView
|
||||||
from calibre.gui2.widgets import Splitter
|
from calibre.gui2.widgets import Splitter
|
||||||
from calibre.gui2.tag_view import TagBrowserWidget
|
from calibre.gui2.tag_view import TagBrowserWidget
|
||||||
from calibre.gui2.status import StatusBar, HStatusBar
|
|
||||||
from calibre.gui2.book_details import BookDetails
|
from calibre.gui2.book_details import BookDetails
|
||||||
|
from calibre.gui2.notify import get_notifier
|
||||||
|
|
||||||
|
|
||||||
_keep_refs = []
|
_keep_refs = []
|
||||||
|
|
||||||
@ -355,6 +356,27 @@ class SideBar(QToolBar): # {{{
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
class StatusBar(QStatusBar): # {{{
|
||||||
|
|
||||||
|
def initialize(self, systray=None):
|
||||||
|
self.systray = systray
|
||||||
|
self.notifier = get_notifier(systray)
|
||||||
|
|
||||||
|
def show_message(self, msg, timeout=0):
|
||||||
|
QStatusBar.showMessage(self, msg, timeout)
|
||||||
|
if self.notifier is not None and not config['disable_tray_notification']:
|
||||||
|
if isosx and isinstance(msg, unicode):
|
||||||
|
try:
|
||||||
|
msg = msg.encode(preferred_encoding)
|
||||||
|
except UnicodeEncodeError:
|
||||||
|
msg = msg.encode('utf-8')
|
||||||
|
self.notifier(msg)
|
||||||
|
|
||||||
|
def clear_message(self):
|
||||||
|
QStatusBar.clearMessage(self)
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
class LayoutMixin(object): # {{{
|
class LayoutMixin(object): # {{{
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -362,7 +384,7 @@ class LayoutMixin(object): # {{{
|
|||||||
self.setWindowTitle(__appname__)
|
self.setWindowTitle(__appname__)
|
||||||
|
|
||||||
if config['gui_layout'] == 'narrow':
|
if config['gui_layout'] == 'narrow':
|
||||||
self.status_bar = self.book_details = StatusBar(self)
|
self.book_details = BookDetails(False, self)
|
||||||
self.stack = Stack(self)
|
self.stack = Stack(self)
|
||||||
self.bd_splitter = Splitter('book_details_splitter',
|
self.bd_splitter = Splitter('book_details_splitter',
|
||||||
_('Book Details'), I('book.svg'),
|
_('Book Details'), I('book.svg'),
|
||||||
@ -375,24 +397,24 @@ class LayoutMixin(object): # {{{
|
|||||||
for x in ('bd', 'tb', 'cb')], self.jobs_button, parent=self)
|
for x in ('bd', 'tb', 'cb')], self.jobs_button, parent=self)
|
||||||
l.addWidget(self.sidebar)
|
l.addWidget(self.sidebar)
|
||||||
self.bd_splitter.addWidget(self._layout_mem[0])
|
self.bd_splitter.addWidget(self._layout_mem[0])
|
||||||
self.bd_splitter.addWidget(self.status_bar)
|
self.bd_splitter.addWidget(self.book_details)
|
||||||
self.bd_splitter.setCollapsible(self.bd_splitter.other_index, False)
|
self.bd_splitter.setCollapsible(self.bd_splitter.other_index, False)
|
||||||
self.centralwidget.layout().addWidget(self.bd_splitter)
|
self.centralwidget.layout().addWidget(self.bd_splitter)
|
||||||
else:
|
else:
|
||||||
self.status_bar = HStatusBar(self)
|
|
||||||
self.setStatusBar(self.status_bar)
|
|
||||||
self.bd_splitter = Splitter('book_details_splitter',
|
self.bd_splitter = Splitter('book_details_splitter',
|
||||||
_('Book Details'), I('book.svg'), initial_side_size=200,
|
_('Book Details'), I('book.svg'), initial_side_size=200,
|
||||||
orientation=Qt.Horizontal, parent=self, side_index=1)
|
orientation=Qt.Horizontal, parent=self, side_index=1)
|
||||||
self.stack = Stack(self)
|
self.stack = Stack(self)
|
||||||
self.bd_splitter.addWidget(self.stack)
|
self.bd_splitter.addWidget(self.stack)
|
||||||
self.book_details = BookDetails(self)
|
self.book_details = BookDetails(True, self)
|
||||||
self.bd_splitter.addWidget(self.book_details)
|
self.bd_splitter.addWidget(self.book_details)
|
||||||
self.bd_splitter.setCollapsible(self.bd_splitter.other_index, False)
|
self.bd_splitter.setCollapsible(self.bd_splitter.other_index, False)
|
||||||
self.bd_splitter.setSizePolicy(QSizePolicy(QSizePolicy.Expanding,
|
self.bd_splitter.setSizePolicy(QSizePolicy(QSizePolicy.Expanding,
|
||||||
QSizePolicy.Expanding))
|
QSizePolicy.Expanding))
|
||||||
self.centralwidget.layout().addWidget(self.bd_splitter)
|
self.centralwidget.layout().addWidget(self.bd_splitter)
|
||||||
|
|
||||||
|
self.status_bar = StatusBar(self)
|
||||||
|
self.setStatusBar(self.status_bar)
|
||||||
for x in ('cb', 'tb', 'bd'):
|
for x in ('cb', 'tb', 'bd'):
|
||||||
button = getattr(self, x+'_splitter').button
|
button = getattr(self, x+'_splitter').button
|
||||||
button.setIconSize(QSize(22, 22))
|
button.setIconSize(QSize(22, 22))
|
||||||
@ -400,6 +422,12 @@ class LayoutMixin(object): # {{{
|
|||||||
self.status_bar.addPermanentWidget(self.jobs_button)
|
self.status_bar.addPermanentWidget(self.jobs_button)
|
||||||
|
|
||||||
def finalize_layout(self):
|
def finalize_layout(self):
|
||||||
|
self.status_bar.initialize(self.system_tray_icon)
|
||||||
|
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.open_containing_folder.connect(self.view_folder_for_id)
|
||||||
|
self.book_details.view_specific_format.connect(self.view_format_by_id)
|
||||||
|
|
||||||
m = self.library_view.model()
|
m = self.library_view.model()
|
||||||
if m.rowCount(None) > 0:
|
if m.rowCount(None) > 0:
|
||||||
self.library_view.set_current_row(0)
|
self.library_view.set_current_row(0)
|
||||||
|
@ -1,253 +0,0 @@
|
|||||||
__license__ = 'GPL v3'
|
|
||||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from PyQt4.Qt import QStatusBar, QLabel, QWidget, QHBoxLayout, QPixmap, \
|
|
||||||
QSizePolicy, QScrollArea, Qt, QSize, pyqtSignal, \
|
|
||||||
QPropertyAnimation, QEasingCurve, QDesktopServices, QUrl
|
|
||||||
|
|
||||||
|
|
||||||
from calibre import fit_image, preferred_encoding, isosx
|
|
||||||
from calibre.gui2 import config
|
|
||||||
from calibre.gui2.widgets import IMAGE_EXTENSIONS
|
|
||||||
from calibre.gui2.notify import get_notifier
|
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
|
||||||
from calibre.library.comments import comments_to_html
|
|
||||||
from calibre.gui2.book_details import render_rows
|
|
||||||
|
|
||||||
class BookInfoDisplay(QWidget):
|
|
||||||
|
|
||||||
DROPABBLE_EXTENSIONS = IMAGE_EXTENSIONS+BOOK_EXTENSIONS
|
|
||||||
files_dropped = pyqtSignal(object, object)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def paths_from_event(cls, event):
|
|
||||||
'''
|
|
||||||
Accept a drop event and return a list of paths that can be read from
|
|
||||||
and represent files with extensions.
|
|
||||||
'''
|
|
||||||
if event.mimeData().hasFormat('text/uri-list'):
|
|
||||||
urls = [unicode(u.toLocalFile()) for u in event.mimeData().urls()]
|
|
||||||
urls = [u for u in urls if os.path.splitext(u)[1] and os.access(u, os.R_OK)]
|
|
||||||
return [u for u in urls if os.path.splitext(u)[1][1:].lower() in cls.DROPABBLE_EXTENSIONS]
|
|
||||||
|
|
||||||
def dragEnterEvent(self, event):
|
|
||||||
if int(event.possibleActions() & Qt.CopyAction) + \
|
|
||||||
int(event.possibleActions() & Qt.MoveAction) == 0:
|
|
||||||
return
|
|
||||||
paths = self.paths_from_event(event)
|
|
||||||
if paths:
|
|
||||||
event.acceptProposedAction()
|
|
||||||
|
|
||||||
def dropEvent(self, event):
|
|
||||||
paths = self.paths_from_event(event)
|
|
||||||
event.setDropAction(Qt.CopyAction)
|
|
||||||
self.files_dropped.emit(event, paths)
|
|
||||||
|
|
||||||
def dragMoveEvent(self, event):
|
|
||||||
event.acceptProposedAction()
|
|
||||||
|
|
||||||
|
|
||||||
class BookCoverDisplay(QLabel): # {{{
|
|
||||||
|
|
||||||
def __init__(self, coverpath=I('book.svg')):
|
|
||||||
QLabel.__init__(self)
|
|
||||||
self.animation = QPropertyAnimation(self, 'size', self)
|
|
||||||
self.animation.setEasingCurve(QEasingCurve(QEasingCurve.OutExpo))
|
|
||||||
self.animation.setDuration(1000)
|
|
||||||
self.animation.setStartValue(QSize(0, 0))
|
|
||||||
self.setMaximumWidth(81)
|
|
||||||
self.setMaximumHeight(108)
|
|
||||||
self.default_pixmap = QPixmap(coverpath)
|
|
||||||
self.setScaledContents(True)
|
|
||||||
self.statusbar_height = 120
|
|
||||||
self.setPixmap(self.default_pixmap)
|
|
||||||
|
|
||||||
def do_layout(self):
|
|
||||||
self.animation.stop()
|
|
||||||
pixmap = self.pixmap()
|
|
||||||
pwidth, pheight = pixmap.width(), pixmap.height()
|
|
||||||
width, height = fit_image(pwidth, pheight,
|
|
||||||
pwidth, self.statusbar_height-20)[1:]
|
|
||||||
self.setMaximumHeight(height)
|
|
||||||
try:
|
|
||||||
aspect_ratio = pwidth/float(pheight)
|
|
||||||
except ZeroDivisionError:
|
|
||||||
aspect_ratio = 1
|
|
||||||
self.setMaximumWidth(int(aspect_ratio*self.maximumHeight()))
|
|
||||||
self.animation.setEndValue(self.maximumSize())
|
|
||||||
|
|
||||||
def setPixmap(self, pixmap):
|
|
||||||
QLabel.setPixmap(self, pixmap)
|
|
||||||
self.do_layout()
|
|
||||||
self.animation.start()
|
|
||||||
|
|
||||||
def sizeHint(self):
|
|
||||||
return QSize(self.maximumWidth(), self.maximumHeight())
|
|
||||||
|
|
||||||
def relayout(self, statusbar_size):
|
|
||||||
self.statusbar_height = statusbar_size.height()
|
|
||||||
self.do_layout()
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
class BookDataDisplay(QLabel):
|
|
||||||
|
|
||||||
mr = pyqtSignal(object)
|
|
||||||
link_clicked = pyqtSignal(object)
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
QLabel.__init__(self)
|
|
||||||
self.setText('')
|
|
||||||
self.setWordWrap(True)
|
|
||||||
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
|
||||||
self.linkActivated.connect(self.link_activated)
|
|
||||||
self._link_clicked = False
|
|
||||||
|
|
||||||
def mouseReleaseEvent(self, ev):
|
|
||||||
QLabel.mouseReleaseEvent(self, ev)
|
|
||||||
if not self._link_clicked:
|
|
||||||
self.mr.emit(ev)
|
|
||||||
self._link_clicked = False
|
|
||||||
|
|
||||||
def link_activated(self, link):
|
|
||||||
self._link_clicked = True
|
|
||||||
link = unicode(link)
|
|
||||||
self.link_clicked.emit(link)
|
|
||||||
|
|
||||||
show_book_info = pyqtSignal()
|
|
||||||
|
|
||||||
def __init__(self, clear_message):
|
|
||||||
QWidget.__init__(self)
|
|
||||||
self.setCursor(Qt.PointingHandCursor)
|
|
||||||
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
|
||||||
self._layout = QHBoxLayout()
|
|
||||||
self.setLayout(self._layout)
|
|
||||||
self.clear_message = clear_message
|
|
||||||
self.cover_display = BookInfoDisplay.BookCoverDisplay()
|
|
||||||
self._layout.addWidget(self.cover_display)
|
|
||||||
self.book_data = BookInfoDisplay.BookDataDisplay()
|
|
||||||
self.book_data.mr.connect(self.mouseReleaseEvent)
|
|
||||||
self._layout.addWidget(self.book_data)
|
|
||||||
self.data = {}
|
|
||||||
self.setVisible(False)
|
|
||||||
self._layout.setAlignment(self.cover_display, Qt.AlignTop|Qt.AlignLeft)
|
|
||||||
|
|
||||||
def mouseReleaseEvent(self, ev):
|
|
||||||
ev.accept()
|
|
||||||
self.show_book_info.emit()
|
|
||||||
|
|
||||||
def show_data(self, data):
|
|
||||||
if data.has_key('cover'):
|
|
||||||
self.cover_display.setPixmap(QPixmap.fromImage(data.pop('cover')))
|
|
||||||
else:
|
|
||||||
self.cover_display.setPixmap(self.cover_display.default_pixmap)
|
|
||||||
|
|
||||||
rows, comments = [], ''
|
|
||||||
self.book_data.setText('')
|
|
||||||
self.data = data.copy()
|
|
||||||
rows = render_rows(self.data)
|
|
||||||
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])
|
|
||||||
if _('Comments') in self.data:
|
|
||||||
comments = comments_to_html(self.data[_('Comments')])
|
|
||||||
comments = ('<b>%s:</b>'%_('Comments'))+comments
|
|
||||||
left_pane = u'<table>%s</table>'%rows
|
|
||||||
right_pane = u'<div>%s</div>'%comments
|
|
||||||
self.book_data.setText(u'<table><tr><td valign="top" '
|
|
||||||
'style="padding-right:2em">%s</td><td valign="top">%s</td></tr></table>'
|
|
||||||
% (left_pane, right_pane))
|
|
||||||
|
|
||||||
self.clear_message()
|
|
||||||
self.book_data.updateGeometry()
|
|
||||||
self.updateGeometry()
|
|
||||||
self.setVisible(True)
|
|
||||||
self.setToolTip('<p>'+_('Click to open Book Details window') +
|
|
||||||
'<br><br>' + _('Path') + ': ' + data.get(_('Path'), ''))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class StatusBarInterface(object):
|
|
||||||
|
|
||||||
def initialize(self, systray=None):
|
|
||||||
self.systray = systray
|
|
||||||
self.notifier = get_notifier(systray)
|
|
||||||
|
|
||||||
def show_message(self, msg, timeout=0):
|
|
||||||
QStatusBar.showMessage(self, msg, timeout)
|
|
||||||
if self.notifier is not None and not config['disable_tray_notification']:
|
|
||||||
if isosx and isinstance(msg, unicode):
|
|
||||||
try:
|
|
||||||
msg = msg.encode(preferred_encoding)
|
|
||||||
except UnicodeEncodeError:
|
|
||||||
msg = msg.encode('utf-8')
|
|
||||||
self.notifier(msg)
|
|
||||||
|
|
||||||
def clear_message(self):
|
|
||||||
QStatusBar.clearMessage(self)
|
|
||||||
|
|
||||||
class BookDetailsInterface(object):
|
|
||||||
|
|
||||||
# These signals must be defined in the class implementing this interface
|
|
||||||
files_dropped = None
|
|
||||||
show_book_info = None
|
|
||||||
open_containing_folder = None
|
|
||||||
view_specific_format = None
|
|
||||||
|
|
||||||
def reset_info(self):
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
def show_data(self, data):
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
class HStatusBar(QStatusBar, StatusBarInterface):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class StatusBar(QStatusBar, StatusBarInterface, BookDetailsInterface):
|
|
||||||
|
|
||||||
files_dropped = pyqtSignal(object, object)
|
|
||||||
show_book_info = pyqtSignal()
|
|
||||||
open_containing_folder = pyqtSignal(int)
|
|
||||||
view_specific_format = pyqtSignal(int, object)
|
|
||||||
|
|
||||||
resized = pyqtSignal(object)
|
|
||||||
|
|
||||||
def initialize(self, systray=None):
|
|
||||||
StatusBarInterface.initialize(self, systray=systray)
|
|
||||||
self.book_info = BookInfoDisplay(self.clear_message)
|
|
||||||
self.book_info.setAcceptDrops(True)
|
|
||||||
self.scroll_area = QScrollArea()
|
|
||||||
self.scroll_area.setWidget(self.book_info)
|
|
||||||
self.scroll_area.setWidgetResizable(True)
|
|
||||||
self.book_info.show_book_info.connect(self.show_book_info.emit,
|
|
||||||
type=Qt.QueuedConnection)
|
|
||||||
self.book_info.files_dropped.connect(self.files_dropped.emit,
|
|
||||||
type=Qt.QueuedConnection)
|
|
||||||
self.book_info.book_data.link_clicked.connect(self._link_clicked)
|
|
||||||
self.addWidget(self.scroll_area, 100)
|
|
||||||
self.setMinimumHeight(120)
|
|
||||||
self.resized.connect(self.book_info.cover_display.relayout)
|
|
||||||
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))
|
|
||||||
elif typ == 'format':
|
|
||||||
id_, fmt = val.split(':')
|
|
||||||
self.view_specific_format.emit(int(id_), fmt)
|
|
||||||
elif typ == 'devpath':
|
|
||||||
QDesktopServices.openUrl(QUrl.fromLocalFile(val))
|
|
||||||
|
|
||||||
|
|
||||||
def resizeEvent(self, ev):
|
|
||||||
self.resized.emit(self.size())
|
|
||||||
|
|
||||||
def reset_info(self):
|
|
||||||
self.book_info.show_data({})
|
|
||||||
|
|
||||||
def show_data(self, data):
|
|
||||||
self.book_info.show_data(data)
|
|
||||||
|
|
@ -104,6 +104,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceMixin, ToolbarMixin, # {{{
|
|||||||
def __init__(self, opts, parent=None):
|
def __init__(self, opts, parent=None):
|
||||||
MainWindow.__init__(self, opts, parent)
|
MainWindow.__init__(self, opts, parent)
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
|
self.setUnifiedTitleAndToolBarOnMac(True)
|
||||||
|
|
||||||
def initialize(self, library_path, db, listener, actions):
|
def initialize(self, library_path, db, listener, actions):
|
||||||
opts = self.opts
|
opts = self.opts
|
||||||
@ -126,8 +127,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceMixin, ToolbarMixin, # {{{
|
|||||||
# Jobs Button {{{
|
# Jobs Button {{{
|
||||||
self.job_manager = JobManager()
|
self.job_manager = JobManager()
|
||||||
self.jobs_dialog = JobsDialog(self, self.job_manager)
|
self.jobs_dialog = JobsDialog(self, self.job_manager)
|
||||||
self.jobs_button = JobsButton(horizontal=config['gui_layout'] !=
|
self.jobs_button = JobsButton(horizontal=True)
|
||||||
'narrow')
|
|
||||||
self.jobs_button.initialize(self.jobs_dialog, self.job_manager)
|
self.jobs_button.initialize(self.jobs_dialog, self.job_manager)
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
@ -216,12 +216,6 @@ class Main(MainWindow, Ui_MainWindow, DeviceMixin, ToolbarMixin, # {{{
|
|||||||
self.vanity.setText(self.vanity_template%dict(version=' ', device=' '))
|
self.vanity.setText(self.vanity_template%dict(version=' ', device=' '))
|
||||||
self.device_info = ' '
|
self.device_info = ' '
|
||||||
UpdateMixin.__init__(self, opts)
|
UpdateMixin.__init__(self, opts)
|
||||||
####################### Status Bar #####################
|
|
||||||
self.status_bar.initialize(self.system_tray_icon)
|
|
||||||
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.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