mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Fix #6165 (Error communicating with the device)
This commit is contained in:
parent
60c86d4744
commit
c56a4a5aaf
@ -1,24 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="128"
|
||||
height="128"
|
||||
id="svg1307"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.43"
|
||||
inkscape:version="0.47 r22583"
|
||||
version="1.0"
|
||||
sodipodi:docbase="/home/pinheiro/Documents/pics/new oxygen/svg"
|
||||
sodipodi:docname="love.svg">
|
||||
sodipodi:docname="donate.svg">
|
||||
<defs
|
||||
id="defs1309">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 64 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="128 : 64 : 1"
|
||||
inkscape:persp3d-origin="64 : 42.666667 : 1"
|
||||
id="perspective44" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2231">
|
||||
@ -180,8 +187,8 @@
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="7.851329"
|
||||
inkscape:cx="92.691163"
|
||||
inkscape:cy="92.473338"
|
||||
inkscape:cx="60.937831"
|
||||
inkscape:cy="61.488995"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:document-units="px"
|
||||
@ -189,10 +196,11 @@
|
||||
guidetolerance="0.1px"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:window-width="1106"
|
||||
inkscape:window-height="958"
|
||||
inkscape:window-x="597"
|
||||
inkscape:window-y="25">
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="997"
|
||||
inkscape:window-x="-4"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1">
|
||||
<sodipodi:guide
|
||||
orientation="horizontal"
|
||||
position="32.487481"
|
||||
@ -245,26 +253,19 @@
|
||||
id="path2276"
|
||||
d="M 50.892799,3.2812959 L 50.892799,0.48658747 L 50.892799,3.2812959 z "
|
||||
style="fill:#ffffff;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.38139535;fill:url(#radialGradient3297);fill-opacity:1.0;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1"
|
||||
id="path3289"
|
||||
sodipodi:cx="63.912209"
|
||||
sodipodi:cy="115.70919"
|
||||
sodipodi:rx="63.912209"
|
||||
sodipodi:ry="12.641975"
|
||||
d="M 127.82442 115.70919 A 63.912209 12.641975 0 1 1 0,115.70919 A 63.912209 12.641975 0 1 1 127.82442 115.70919 z"
|
||||
transform="matrix(1,0,0,0.416667,0,74.87151)" />
|
||||
<path
|
||||
style="fill:url(#radialGradient2335);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 35.325021,6.2016208 C 32.278871,6.2210338 29.045555,6.6687791 25.645673,7.6089386 C 5.9380713,13.058619 0.404709,29.342113 5.3805953,48.506873 C 12.126047,74.487157 36.855395,101.02725 64.150803,115.92895 L 64.150803,116.02417 C 64.162016,116.00826 64.173539,115.99248 64.184766,115.97656 C 64.195995,115.99248 64.207516,116.00826 64.218732,116.02417 L 64.218732,115.92895 C 90.473794,101.59521 116.24349,74.487157 122.98895,48.506873 C 127.96481,29.342113 122.43148,13.058619 102.72386,7.6089386 C 83.422254,2.2715258 69.549778,12.840101 64.184766,27.183808 C 59.764775,15.366673 49.572303,6.1108179 35.325021,6.2016208 z "
|
||||
id="path2245"
|
||||
sodipodi:nodetypes="cssccsccsscc" />
|
||||
<path
|
||||
id="path2369"
|
||||
d="M 35.325021,6.2016208 C 32.278871,6.2210338 29.045555,6.6687791 25.645673,7.6089386 C 5.9380713,13.058619 0.404709,29.342113 5.3805953,48.506873 C 12.126047,74.487157 37.113186,101.16799 64.150803,115.92895 L 64.150803,116.02417 C 64.162016,116.00826 64.173539,115.99248 64.184766,115.97656 C 64.195995,115.99248 64.207516,116.00826 64.218732,116.02417 L 64.218732,115.92895 C 90.398445,101.63635 116.24349,74.487157 122.98895,48.506873 C 127.96481,29.342113 122.43148,13.058619 102.72386,7.6089386 C 83.422254,2.2715258 69.549778,12.840101 64.184766,27.183808 C 59.764775,15.366673 49.572303,6.1108179 35.325021,6.2016208 z "
|
||||
style="opacity:0.4713115;fill:url(#linearGradient2379);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
sodipodi:nodetypes="cssccsccsscc" />
|
||||
<g
|
||||
id="g2850">
|
||||
<path
|
||||
sodipodi:nodetypes="cssccsccsscc"
|
||||
style="opacity:0.4713115;fill:url(#linearGradient2379);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 35.325021,6.2016208 C 32.278871,6.2210338 29.045555,6.6687791 25.645673,7.6089386 C 5.9380713,13.058619 0.404709,29.342113 5.3805953,48.506873 C 12.126047,74.487157 37.113186,101.16799 64.150803,115.92895 L 64.150803,116.02417 C 64.162016,116.00826 64.173539,115.99248 64.184766,115.97656 C 64.195995,115.99248 64.207516,116.00826 64.218732,116.02417 L 64.218732,115.92895 C 90.398445,101.63635 116.24349,74.487157 122.98895,48.506873 C 127.96481,29.342113 122.43148,13.058619 102.72386,7.6089386 C 83.422254,2.2715258 69.549778,12.840101 64.184766,27.183808 C 59.764775,15.366673 49.572303,6.1108179 35.325021,6.2016208 z "
|
||||
id="path2369" />
|
||||
</g>
|
||||
<path
|
||||
style="opacity:0.1762295;fill:url(#linearGradient2331);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.29999995;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 34.451605,6.2067207 C 31.659392,6.2976073 28.7301,6.7682297 25.648957,7.6202497 C 7.7889432,12.559022 1.5815371,26.389172 4.2759909,43.204304 C 27.13595,75.72273 65.297627,95.42612 91.41193,91.971053 C 105.43169,77.948778 119.04939,63.70497 122.99185,48.520401 C 127.96773,29.355639 122.42255,13.069929 102.71494,7.6202497 C 83.413331,2.2828362 69.546961,12.850845 64.181949,27.194552 C 59.761957,15.377418 49.555176,6.1159177 35.307894,6.2067207 C 35.022317,6.2085406 34.740456,6.1973187 34.451605,6.2067207 z "
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
BIN
resources/images/lt.png
Normal file
BIN
resources/images/lt.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
@ -10,10 +10,10 @@ from base64 import b64decode
|
||||
from uuid import uuid4
|
||||
from lxml import etree
|
||||
|
||||
from calibre import prints, guess_type
|
||||
from calibre import prints, guess_type, isbytestring
|
||||
from calibre.devices.errors import DeviceError
|
||||
from calibre.devices.usbms.driver import debug_print
|
||||
from calibre.constants import DEBUG
|
||||
from calibre.constants import DEBUG, preferred_encoding
|
||||
from calibre.ebooks.chardet import xml_to_unicode
|
||||
from calibre.ebooks.metadata import authors_to_string, title_sort
|
||||
|
||||
@ -473,6 +473,13 @@ class XMLCache(object):
|
||||
# if the case of a tie, and hope it is right.
|
||||
timestamp = os.path.getmtime(path)
|
||||
rec_date = record.get('date', None)
|
||||
|
||||
def clean(x):
|
||||
if isbytestring(x):
|
||||
x = x.decode(preferred_encoding, 'replace')
|
||||
x.replace(u'\0', '')
|
||||
return x
|
||||
|
||||
if not getattr(book, '_new_book', False): # book is not new
|
||||
if strftime(timestamp, zone=time.gmtime) == rec_date:
|
||||
gtz_count += 1
|
||||
@ -486,19 +493,19 @@ class XMLCache(object):
|
||||
tz = time.gmtime
|
||||
debug_print("Using GMT TZ for new book", book.lpath)
|
||||
date = strftime(timestamp, zone=tz)
|
||||
record.set('date', date)
|
||||
record.set('date', clean(date))
|
||||
|
||||
record.set('size', str(os.stat(path).st_size))
|
||||
record.set('size', clean(str(os.stat(path).st_size)))
|
||||
title = book.title if book.title else _('Unknown')
|
||||
record.set('title', title)
|
||||
record.set('title', clean(title))
|
||||
ts = book.title_sort
|
||||
if not ts:
|
||||
ts = title_sort(title)
|
||||
record.set('titleSorter', ts)
|
||||
record.set('titleSorter', clean(ts))
|
||||
if self.use_author_sort and book.author_sort is not None:
|
||||
record.set('author', book.author_sort)
|
||||
record.set('author', clean(book.author_sort))
|
||||
else:
|
||||
record.set('author', authors_to_string(book.authors))
|
||||
record.set('author', clean(authors_to_string(book.authors)))
|
||||
ext = os.path.splitext(path)[1]
|
||||
if ext:
|
||||
ext = ext[1:].lower()
|
||||
@ -506,7 +513,7 @@ class XMLCache(object):
|
||||
if mime is None:
|
||||
mime = guess_type('a.'+ext)[0]
|
||||
if mime is not None:
|
||||
record.set('mime', mime)
|
||||
record.set('mime', clean(mime))
|
||||
if 'sourceid' not in record.attrib:
|
||||
record.set('sourceid', '1')
|
||||
if 'id' not in record.attrib:
|
||||
|
@ -765,6 +765,7 @@ class DeviceMixin(object): # {{{
|
||||
self.book_details.reset_info()
|
||||
self.location_view.setCurrentIndex(self.location_view.model().index(0))
|
||||
self.refresh_ondevice_info (device_connected = False)
|
||||
self.tool_bar.device_status_changed(bool(connected))
|
||||
|
||||
def info_read(self, job):
|
||||
'''
|
||||
|
@ -334,7 +334,6 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
|
||||
|
||||
def __init__(self, parent, library_view, server=None):
|
||||
ResizableDialog.__init__(self, parent)
|
||||
self.ICON_SIZES = {0:QSize(48, 48), 1:QSize(32,32), 2:QSize(24,24)}
|
||||
self._category_model = CategoryModel()
|
||||
|
||||
self.category_view.currentChanged = self.category_current_changed
|
||||
@ -389,10 +388,6 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
|
||||
self.add_custcol_button.clicked.connect(self.add_custcol)
|
||||
self.edit_custcol_button.clicked.connect(self.edit_custcol)
|
||||
|
||||
icons = config['toolbar_icon_size']
|
||||
self.toolbar_button_size.setCurrentIndex(0 if icons == self.ICON_SIZES[0] else 1 if icons == self.ICON_SIZES[1] else 2)
|
||||
self.show_toolbar_text.setChecked(config['show_text_in_toolbar'])
|
||||
|
||||
output_formats = sorted(available_output_formats())
|
||||
output_formats.remove('oeb')
|
||||
for f in output_formats:
|
||||
@ -845,8 +840,6 @@ class ConfigDialog(ResizableDialog, Ui_Dialog):
|
||||
|
||||
must_restart = self.apply_custom_column_changes()
|
||||
|
||||
config['toolbar_icon_size'] = self.ICON_SIZES[self.toolbar_button_size.currentIndex()]
|
||||
config['show_text_in_toolbar'] = bool(self.show_toolbar_text.isChecked())
|
||||
config['separate_cover_flow'] = bool(self.separate_cover_flow.isChecked())
|
||||
config['disable_tray_notification'] = not self.systray_notifications.isChecked()
|
||||
p = {0:'normal', 1:'high', 2:'low'}[self.priority.currentIndex()]
|
||||
|
@ -422,54 +422,6 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Toolbar</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="toolbar_button_size">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Large</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Medium</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Small</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>&Button size in toolbar</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>toolbar_button_size</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="show_toolbar_text">
|
||||
<property name="text">
|
||||
<string>Show &text in toolbar buttons</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
|
@ -176,12 +176,6 @@ class ToolbarMixin(object): # {{{
|
||||
def show_help(self, *args):
|
||||
open_url(QUrl('http://calibre-ebook.com/user_manual'))
|
||||
|
||||
def read_toolbar_settings(self):
|
||||
self.tool_bar.setIconSize(config['toolbar_icon_size'])
|
||||
self.tool_bar.setToolButtonStyle(
|
||||
Qt.ToolButtonTextUnderIcon if \
|
||||
config['show_text_in_toolbar'] else \
|
||||
Qt.ToolButtonIconOnly)
|
||||
|
||||
# }}}
|
||||
|
||||
|
@ -5,6 +5,8 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
from operator import attrgetter
|
||||
|
||||
from PyQt4.Qt import QIcon, Qt, QWidget, QAction, QToolBar, QSize, QVariant, \
|
||||
QAbstractListModel, QFont, QApplication, QPalette, pyqtSignal, QToolButton, \
|
||||
QModelIndex, QListView, QAbstractButton, QPainter, QPixmap, QColor, \
|
||||
@ -13,41 +15,11 @@ from PyQt4.Qt import QIcon, Qt, QWidget, QAction, QToolBar, QSize, QVariant, \
|
||||
from calibre.constants import __appname__, filesystem_encoding
|
||||
from calibre.gui2.search_box import SearchBox2, SavedSearchBox
|
||||
from calibre.gui2.throbber import ThrobbingButton
|
||||
from calibre.gui2 import NONE
|
||||
from calibre.gui2 import NONE, config
|
||||
from calibre.gui2.widgets import ComboBoxWithHelp
|
||||
from calibre import human_readable
|
||||
|
||||
class ToolBar(QToolBar): # {{{
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QToolBar.__init__(self, parent)
|
||||
self.setContextMenuPolicy(Qt.PreventContextMenu)
|
||||
self.setMovable(False)
|
||||
self.setFloatable(False)
|
||||
self.setOrientation(Qt.Horizontal)
|
||||
self.setAllowedAreas(Qt.TopToolBarArea|Qt.BottomToolBarArea)
|
||||
self.setIconSize(QSize(48, 48))
|
||||
self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
|
||||
|
||||
def add_actions(self, *args):
|
||||
self.left_space = QWidget(self)
|
||||
self.left_space.setSizePolicy(QSizePolicy.Expanding,
|
||||
QSizePolicy.Minimum)
|
||||
self.addWidget(self.left_space)
|
||||
for action in args:
|
||||
if action is None:
|
||||
self.addSeparator()
|
||||
else:
|
||||
self.addAction(action)
|
||||
self.right_space = QWidget(self)
|
||||
self.right_space.setSizePolicy(QSizePolicy.Expanding,
|
||||
QSizePolicy.Minimum)
|
||||
self.addWidget(self.right_space)
|
||||
|
||||
def contextMenuEvent(self, *args):
|
||||
pass
|
||||
|
||||
# }}}
|
||||
ICON_SIZE = 48
|
||||
|
||||
# Location View {{{
|
||||
|
||||
@ -191,14 +163,15 @@ class LocationView(QListView):
|
||||
self.setTabKeyNavigation(True)
|
||||
self.setProperty("showDropIndicator", True)
|
||||
self.setSelectionMode(self.SingleSelection)
|
||||
self.setIconSize(QSize(40, 40))
|
||||
self.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
|
||||
self.setMovement(self.Static)
|
||||
self.setFlow(self.LeftToRight)
|
||||
self.setGridSize(QSize(175, 90))
|
||||
self.setGridSize(QSize(175, ICON_SIZE))
|
||||
self.setViewMode(self.ListMode)
|
||||
self.setWordWrap(True)
|
||||
self.setObjectName("location_view")
|
||||
self.setMaximumHeight(74)
|
||||
self.setMaximumSize(QSize(600, ICON_SIZE+16))
|
||||
self.setMinimumWidth(400)
|
||||
|
||||
def eject_clicked(self, *args):
|
||||
self.unmount_device.emit()
|
||||
@ -207,6 +180,10 @@ class LocationView(QListView):
|
||||
self.model().count = new_count
|
||||
self.model().reset()
|
||||
|
||||
@property
|
||||
def book_count(self):
|
||||
return self.model().count
|
||||
|
||||
def current_changed(self, current, previous):
|
||||
if current.isValid():
|
||||
i = current.row()
|
||||
@ -248,12 +225,15 @@ class EjectButton(QAbstractButton):
|
||||
def __init__(self, parent):
|
||||
QAbstractButton.__init__(self, parent)
|
||||
self.mouse_over = False
|
||||
self.setMouseTracking(True)
|
||||
|
||||
def enterEvent(self, event):
|
||||
self.mouse_over = True
|
||||
QAbstractButton.enterEvent(self, event)
|
||||
|
||||
def leaveEvent(self, event):
|
||||
self.mouse_over = False
|
||||
QAbstractButton.leaveEvent(self, event)
|
||||
|
||||
def paintEvent(self, event):
|
||||
painter = QPainter(self)
|
||||
@ -344,33 +324,84 @@ class SearchBar(QWidget): # {{{
|
||||
|
||||
# }}}
|
||||
|
||||
class LocationBar(ToolBar): # {{{
|
||||
class ToolBar(QToolBar): # {{{
|
||||
|
||||
def __init__(self, actions, donate, location_view, parent=None):
|
||||
ToolBar.__init__(self, parent)
|
||||
|
||||
for ac in actions:
|
||||
self.addAction(ac)
|
||||
|
||||
self.addWidget(location_view)
|
||||
self.w = QWidget()
|
||||
self.w.setLayout(QVBoxLayout())
|
||||
self.w.layout().addWidget(donate)
|
||||
donate.setAutoRaise(True)
|
||||
donate.setCursor(Qt.PointingHandCursor)
|
||||
self.addWidget(self.w)
|
||||
self.setIconSize(QSize(50, 50))
|
||||
QToolBar.__init__(self, parent)
|
||||
self.setContextMenuPolicy(Qt.PreventContextMenu)
|
||||
self.setMovable(False)
|
||||
self.setFloatable(False)
|
||||
self.setOrientation(Qt.Horizontal)
|
||||
self.setAllowedAreas(Qt.TopToolBarArea|Qt.BottomToolBarArea)
|
||||
self.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
|
||||
self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
|
||||
|
||||
def button_for_action(self, ac):
|
||||
b = QToolButton(self)
|
||||
b.setDefaultAction(ac)
|
||||
for x in ('ToolTip', 'StatusTip', 'WhatsThis'):
|
||||
getattr(b, 'set'+x)(b.text())
|
||||
self.showing_device = False
|
||||
self.all_actions = actions
|
||||
self.donate = donate
|
||||
self.location_view = location_view
|
||||
self.d_widget = QWidget()
|
||||
self.d_widget.setLayout(QVBoxLayout())
|
||||
self.d_widget.layout().addWidget(donate)
|
||||
donate.setAutoRaise(True)
|
||||
donate.setCursor(Qt.PointingHandCursor)
|
||||
self.build_bar()
|
||||
|
||||
def contextMenuEvent(self, *args):
|
||||
pass
|
||||
|
||||
def device_status_changed(self, connected):
|
||||
self.showing_device = connected
|
||||
self.build_bar()
|
||||
|
||||
def build_bar(self):
|
||||
order_field = 'device' if self.showing_device else 'normal'
|
||||
o = attrgetter(order_field+'_order')
|
||||
sepvals = [2] if self.showing_device else [1]
|
||||
sepvals += [3]
|
||||
actions = [x for x in self.all_actions if o(x) > -1]
|
||||
actions.sort(cmp=lambda x,y : cmp(o(x), o(y)))
|
||||
self.clear()
|
||||
for x in actions:
|
||||
self.addAction(x)
|
||||
ch = self.widgetForAction(x)
|
||||
ch.setCursor(Qt.PointingHandCursor)
|
||||
ch.setAutoRaise(True)
|
||||
|
||||
if x.action_name == 'choose_library':
|
||||
self.location_action = self.addWidget(self.location_view)
|
||||
self.choose_action = x
|
||||
if config['show_donate_button']:
|
||||
self.addWidget(self.d_widget)
|
||||
if x.action_name not in ('choose_library', 'help'):
|
||||
ch.setPopupMode(ch.MenuButtonPopup)
|
||||
|
||||
|
||||
for x in actions:
|
||||
if x.separator_before in sepvals:
|
||||
self.insertSeparator(x)
|
||||
|
||||
|
||||
self.location_action.setVisible(self.showing_device)
|
||||
self.choose_action.setVisible(not self.showing_device)
|
||||
|
||||
def count_changed(self, new_count):
|
||||
text = _('%d books')%new_count
|
||||
a = self.choose_action
|
||||
a.setText(text)
|
||||
|
||||
def resizeEvent(self, ev):
|
||||
style = Qt.ToolButtonTextUnderIcon
|
||||
if self.size().width() < 1260:
|
||||
style = Qt.ToolButtonIconOnly
|
||||
self.setToolButtonStyle(style)
|
||||
QToolBar.resizeEvent(self, ev)
|
||||
|
||||
return b
|
||||
# }}}
|
||||
|
||||
class Action(QAction):
|
||||
pass
|
||||
|
||||
class MainWindowMixin(object):
|
||||
|
||||
def __init__(self):
|
||||
@ -385,12 +416,19 @@ class MainWindowMixin(object):
|
||||
self.centralwidget.setLayout(self._central_widget_layout)
|
||||
self.resize(1012, 740)
|
||||
self.donate_button = ThrobbingButton(self.centralwidget)
|
||||
self.donate_button.set_normal_icon_size(64, 64)
|
||||
self.donate_button.set_normal_icon_size(ICON_SIZE, ICON_SIZE)
|
||||
|
||||
# Actions {{{
|
||||
|
||||
def ac(name, text, icon, shortcut=None, tooltip=None):
|
||||
action = QAction(QIcon(I(icon)), text, self)
|
||||
all_actions = []
|
||||
|
||||
def ac(normal_order, device_order, separator_before,
|
||||
name, text, icon, shortcut=None, tooltip=None):
|
||||
action = Action(QIcon(I(icon)), text, self)
|
||||
action.normal_order = normal_order
|
||||
action.device_order = device_order
|
||||
action.separator_before = separator_before
|
||||
action.action_name = name
|
||||
text = tooltip if tooltip else text
|
||||
action.setToolTip(text)
|
||||
action.setStatusTip(text)
|
||||
@ -400,56 +438,46 @@ class MainWindowMixin(object):
|
||||
if shortcut:
|
||||
action.setShortcut(shortcut)
|
||||
setattr(self, 'action_'+name, action)
|
||||
all_actions.append(action)
|
||||
|
||||
ac('add', _('Add books'), 'add_book.svg', _('A'))
|
||||
ac('del', _('Remove books'), 'trash.svg', _('Del'))
|
||||
ac('edit', _('Edit metadata'), 'edit_input.svg', _('E'))
|
||||
ac('merge', _('Merge book records'), 'merge_books.svg', _('M'))
|
||||
ac('sync', _('Send to device'), 'sync.svg')
|
||||
ac('save', _('Save to disk'), 'save.svg', _('S'))
|
||||
ac('news', _('Fetch news'), 'news.svg', _('F'))
|
||||
ac('convert', _('Convert books'), 'convert.svg', _('C'))
|
||||
ac('view', _('View'), 'view.svg', _('V'))
|
||||
ac('open_containing_folder', _('Open containing folder'),
|
||||
ac(0, 7, 0, 'add', _('Add books'), 'add_book.svg', _('A'))
|
||||
ac(1, 1, 0, 'edit', _('Edit metadata'), 'edit_input.svg', _('E'))
|
||||
ac(2, 2, 3, 'convert', _('Convert books'), 'convert.svg', _('C'))
|
||||
ac(3, 3, 0, 'view', _('View'), 'view.svg', _('V'))
|
||||
ac(4, 4, 3, 'choose_library', _('%d books')%0, 'lt.png',
|
||||
tooltip=_('Choose calibre library to work with'))
|
||||
ac(5, 5, 3, 'news', _('Fetch news'), 'news.svg', _('F'))
|
||||
ac(6, 6, 0, 'save', _('Save to disk'), 'save.svg', _('S'))
|
||||
ac(7, 0, 0, 'sync', _('Send to device'), 'sync.svg')
|
||||
ac(8, 8, 3, 'del', _('Remove books'), 'trash.svg', _('Del'))
|
||||
ac(9, 9, 3, 'help', _('Help'), 'help.svg', _('F1'), _("Browse the calibre User Manual"))
|
||||
ac(10, 10, 0, 'preferences', _('Preferences'), 'config.svg', _('Ctrl+P'))
|
||||
|
||||
ac(-1, -1, 0, 'merge', _('Merge book records'), 'merge_books.svg', _('M'))
|
||||
ac(-1, -1, 0, 'open_containing_folder', _('Open containing folder'),
|
||||
'document_open.svg')
|
||||
ac('show_book_details', _('Show book details'),
|
||||
ac(-1, -1, 0, 'show_book_details', _('Show book details'),
|
||||
'dialog_information.svg')
|
||||
ac('books_by_same_author', _('Books by same author'),
|
||||
ac(-1, -1, 0, 'books_by_same_author', _('Books by same author'),
|
||||
'user_profile.svg')
|
||||
ac('books_in_this_series', _('Books in this series'),
|
||||
ac(-1, -1, 0, 'books_in_this_series', _('Books in this series'),
|
||||
'books_in_series.svg')
|
||||
ac('books_by_this_publisher', _('Books by this publisher'),
|
||||
ac(-1, -1, 0, 'books_by_this_publisher', _('Books by this publisher'),
|
||||
'publisher.png')
|
||||
ac('books_with_the_same_tags', _('Books with the same tags'),
|
||||
ac(-1, -1, 0, 'books_with_the_same_tags', _('Books with the same tags'),
|
||||
'tags.svg')
|
||||
ac('preferences', _('Preferences'), 'config.svg', _('Ctrl+P'))
|
||||
ac('help', _('Help'), 'help.svg', _('F1'), _("Browse the calibre User Manual"))
|
||||
|
||||
# }}}
|
||||
|
||||
self.tool_bar = ToolBar(self)
|
||||
self.addToolBar(Qt.BottomToolBarArea, self.tool_bar)
|
||||
self.tool_bar.add_actions(self.action_convert, self.action_view,
|
||||
None, self.action_edit, None,
|
||||
self.action_save, self.action_del,
|
||||
None,
|
||||
self.action_help, None, self.action_preferences)
|
||||
|
||||
self.location_view = LocationView(self.centralwidget)
|
||||
self.search_bar = SearchBar(self)
|
||||
self.location_bar = LocationBar([self.action_add, self.action_sync,
|
||||
self.action_news], self.donate_button, self.location_view, self)
|
||||
self.addToolBar(Qt.TopToolBarArea, self.location_bar)
|
||||
self.tool_bar = ToolBar(all_actions, self.donate_button, self.location_view, self)
|
||||
self.addToolBar(Qt.TopToolBarArea, self.tool_bar)
|
||||
|
||||
l = self.centralwidget.layout()
|
||||
l.addWidget(self.search_bar)
|
||||
|
||||
for ch in list(self.tool_bar.children()) + list(self.location_bar.children()):
|
||||
if isinstance(ch, QToolButton):
|
||||
ch.setCursor(Qt.PointingHandCursor)
|
||||
ch.setAutoRaise(True)
|
||||
if ch is not self.donate_button:
|
||||
ch.setPopupMode(ch.MenuButtonPopup)
|
||||
|
||||
|
||||
def read_toolbar_settings(self):
|
||||
pass
|
||||
|
||||
|
@ -13,6 +13,7 @@ class SearchRestrictionMixin(object):
|
||||
self.search_restriction.setSizeAdjustPolicy(self.search_restriction.AdjustToMinimumContentsLengthWithIcon)
|
||||
self.search_restriction.setMinimumContentsLength(10)
|
||||
self.search_restriction.setStatusTip(self.search_restriction.toolTip())
|
||||
self.search_count.setText(_("(all books)"))
|
||||
|
||||
'''
|
||||
Adding and deleting books while restricted creates a complexity. When added,
|
||||
|
@ -167,8 +167,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, ToolbarMixin, # {{{
|
||||
self.eject_action = self.system_tray_menu.addAction(
|
||||
QIcon(I('eject.svg')), _('&Eject connected device'))
|
||||
self.eject_action.setEnabled(False)
|
||||
if not config['show_donate_button']:
|
||||
self.donate_button.setVisible(False)
|
||||
self.addAction(self.quit_action)
|
||||
self.action_restart = QAction(_('&Restart'), self)
|
||||
self.addAction(self.action_restart)
|
||||
@ -220,8 +218,9 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, ToolbarMixin, # {{{
|
||||
|
||||
if self.system_tray_icon.isVisible() and opts.start_in_tray:
|
||||
self.hide_windows()
|
||||
self.library_view.model().count_changed_signal.connect \
|
||||
(self.location_view.count_changed)
|
||||
for t in (self.location_view, self.tool_bar):
|
||||
self.library_view.model().count_changed_signal.connect \
|
||||
(t.count_changed)
|
||||
if not gprefs.get('quick_start_guide_added', False):
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
mi = MetaInformation(_('Calibre Quick Start Guide'), ['John Schember'])
|
||||
@ -274,8 +273,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, ToolbarMixin, # {{{
|
||||
SIGNAL('start_recipe_fetch(PyQt_PyObject)'),
|
||||
self.download_scheduled_recipe, Qt.QueuedConnection)
|
||||
|
||||
self.location_view.setCurrentIndex(self.location_view.model().index(0))
|
||||
|
||||
self.keyboard_interrupt.connect(self.quit, type=Qt.QueuedConnection)
|
||||
AddAction.__init__(self)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user