mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Fix cover not being detected for HTML RARballs. Plug possible hole in books database implementation. Add initial device job support to gui2.
This commit is contained in:
parent
2ed012f023
commit
fe2e72d699
@ -13,7 +13,7 @@
|
|||||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
''' E-book management software'''
|
''' E-book management software'''
|
||||||
__version__ = "0.3.56"
|
__version__ = "0.3.57"
|
||||||
__docformat__ = "epytext"
|
__docformat__ = "epytext"
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
__appname__ = 'libprs500'
|
__appname__ = 'libprs500'
|
||||||
|
@ -57,7 +57,7 @@ class Book(object):
|
|||||||
size = book_metadata_field("size", formatter=int)
|
size = book_metadata_field("size", formatter=int)
|
||||||
# When setting this attribute you must use an epoch
|
# When setting this attribute you must use an epoch
|
||||||
datetime = book_metadata_field("date", \
|
datetime = book_metadata_field("date", \
|
||||||
formatter=lambda x: time.strptime(x, "%a, %d %b %Y %H:%M:%S %Z"),
|
formatter=lambda x: time.strptime(x.strip(), "%a, %d %b %Y %H:%M:%S %Z"),
|
||||||
setter=lambda x: time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(x)))
|
setter=lambda x: time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(x)))
|
||||||
|
|
||||||
@apply
|
@apply
|
||||||
|
@ -1212,11 +1212,15 @@ def try_opf(path, options):
|
|||||||
isbn.append((scheme, item.string))
|
isbn.append((scheme, item.string))
|
||||||
if not options.cover:
|
if not options.cover:
|
||||||
for item in isbn:
|
for item in isbn:
|
||||||
matches = glob.glob(re.sub('-', '', item[1])+'.*')
|
src = item[1].replace('-', '')
|
||||||
|
matches = glob.glob(os.path.join(os.path.dirname(path), src+'.*'))
|
||||||
for match in matches:
|
for match in matches:
|
||||||
if match.lower().endswith('.jpeg') or match.lower().endswith('.jpg') or \
|
test = os.path.splitext(match)[1].lower()
|
||||||
match.lower().endswith('.gif') or match.lower().endswith('.png'):
|
if test in ['.jpeg', '.jpg', '.gif', '.png']:
|
||||||
options.cover = match
|
options.cover = match
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
if not options.cover:
|
if not options.cover:
|
||||||
# Search for cover image in opf as created by convertlit
|
# Search for cover image in opf as created by convertlit
|
||||||
ref = soup.package.find('reference', {'type':'other.ms-coverimage-standard'})
|
ref = soup.package.find('reference', {'type':'other.ms-coverimage-standard'})
|
||||||
|
@ -47,7 +47,7 @@ def Error(msg, e):
|
|||||||
error_dialog.showMessage(msg)
|
error_dialog.showMessage(msg)
|
||||||
error_dialog.show()
|
error_dialog.show()
|
||||||
|
|
||||||
def human_readable(cls, size):
|
def human_readable(size):
|
||||||
""" Convert a size in bytes into a human readable form """
|
""" Convert a size in bytes into a human readable form """
|
||||||
if size < 1024:
|
if size < 1024:
|
||||||
divisor, suffix = 1, "B"
|
divisor, suffix = 1, "B"
|
||||||
|
@ -88,19 +88,18 @@ class DeviceManager(QObject):
|
|||||||
def get_info_func(self):
|
def get_info_func(self):
|
||||||
''' Return callable that returns device information and free space on device'''
|
''' Return callable that returns device information and free space on device'''
|
||||||
def get_device_information(updater):
|
def get_device_information(updater):
|
||||||
self.device.set_updater(updater)
|
self.device.set_progress_reporter(updater)
|
||||||
info = self.device.get_device_information(end_session=False)
|
info = self.device.get_device_information(end_session=False)
|
||||||
info = {'name':info[0], 'version':info[1], 'swversion':[2], 'mimetype':info[3]}
|
info = [i.replace('\x00', '').replace('\x01', '') for i in info]
|
||||||
cp = self.device.card_prefix(end_session=False)
|
cp = self.device.card_prefix(end_session=False)
|
||||||
fs = self.device.free_space()
|
fs = self.device.free_space()
|
||||||
fs = {'main':fs[0], 'carda':fs[1], 'cardb':fs[2]}
|
|
||||||
return info, cp, fs
|
return info, cp, fs
|
||||||
return get_device_information
|
return get_device_information
|
||||||
|
|
||||||
def books_func(self):
|
def books_func(self):
|
||||||
'''Return callable that returns the list of books on device as two booklists'''
|
'''Return callable that returns the list of books on device as two booklists'''
|
||||||
def books(updater):
|
def books(updater):
|
||||||
self.device.set_updater(updater)
|
self.device.set_progress_reporter(updater)
|
||||||
mainlist = self.device.books(oncard=False, end_session=False)
|
mainlist = self.device.books(oncard=False, end_session=False)
|
||||||
cardlist = self.device.books(oncard=True)
|
cardlist = self.device.books(oncard=True)
|
||||||
return mainlist, cardlist
|
return mainlist, cardlist
|
||||||
|
@ -39,7 +39,10 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
self.job_manager = JobManager()
|
self.job_manager = JobManager()
|
||||||
self.device_manager = None
|
self.device_manager = None
|
||||||
self.temporary_slots = {}
|
self.temporary_slots = {}
|
||||||
self.df.setText(self.df.text().arg(VERSION))
|
|
||||||
|
####################### Vanity ########################
|
||||||
|
self.vanity_template = self.vanity.text().arg(VERSION)
|
||||||
|
self.vanity.setText(self.vanity_template.arg(' '))
|
||||||
|
|
||||||
####################### Status Bar #####################
|
####################### Status Bar #####################
|
||||||
self.status_bar = StatusBar()
|
self.status_bar = StatusBar()
|
||||||
@ -64,18 +67,25 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
self.detector.start(QThread.InheritPriority)
|
self.detector.start(QThread.InheritPriority)
|
||||||
|
|
||||||
|
|
||||||
|
def job_exception(self, id, exception, formatted_traceback):
|
||||||
|
raise JobException, str(exception) + '\n\r' + formatted_traceback
|
||||||
|
|
||||||
def device_detected(self, cls, connected):
|
def device_detected(self, cls, connected):
|
||||||
if connected:
|
if connected:
|
||||||
def info_read(id, result, exception, formatted_traceback):
|
|
||||||
if exception:
|
|
||||||
pass #TODO: Handle error
|
|
||||||
info, cp, fs = result
|
|
||||||
print self, id, result, exception, formatted_traceback
|
|
||||||
self.temporary_slots['device_info_read'] = info_read
|
|
||||||
self.device_manager = DeviceManager(cls)
|
self.device_manager = DeviceManager(cls)
|
||||||
func = self.device_manager.get_info_func()
|
func = self.device_manager.get_info_func()
|
||||||
self.job_manager.run_device_job(info_read, func)
|
|
||||||
|
self.job_manager.run_device_job(self.info_read, func)
|
||||||
|
|
||||||
|
def info_read(self, id, result, exception, formatted_traceback):
|
||||||
|
if exception:
|
||||||
|
self.job_exception(id, exception, formatted_traceback)
|
||||||
|
return
|
||||||
|
info, cp, fs = result
|
||||||
|
self.location_view.model().update_devices(cp, fs)
|
||||||
|
self.vanity.setText(self.vanity_template.arg('Connected '+' '.join(info[:-1])))
|
||||||
|
|
||||||
|
|
||||||
def read_settings(self):
|
def read_settings(self):
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="LocationView" name="device_tree" >
|
<widget class="LocationView" name="location_view" >
|
||||||
<property name="sizePolicy" >
|
<property name="sizePolicy" >
|
||||||
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
|
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -76,7 +76,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="df" >
|
<widget class="QLabel" name="vanity" >
|
||||||
<property name="sizePolicy" >
|
<property name="sizePolicy" >
|
||||||
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
|
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
@ -90,7 +90,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>For help visit <a href="https://libprs500.kovidgoyal.net/wiki/GuiUsage">http://libprs500.kovidgoyal.net</a><br><br><b>libprs500</b>: %1 by <b>Kovid Goyal</b> &copy; 2007<br>%2 %3 %4</string>
|
<string>For help visit <a href="https://libprs500.kovidgoyal.net/wiki/GuiUsage">http://libprs500.kovidgoyal.net</a><br><br><b>libprs500</b>: %1 by <b>Kovid Goyal</b> &copy; 2007<br>%2</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="textFormat" >
|
<property name="textFormat" >
|
||||||
<enum>Qt::RichText</enum>
|
<enum>Qt::RichText</enum>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'main.ui'
|
# Form implementation generated from reading ui file 'main.ui'
|
||||||
#
|
#
|
||||||
# Created: Thu Jun 21 20:31:43 2007
|
# Created: Fri Jun 22 16:40:15 2007
|
||||||
# by: PyQt4 UI code generator 4-snapshot-20070606
|
# by: PyQt4 UI code generator 4-snapshot-20070606
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# WARNING! All changes made in this file will be lost!
|
||||||
@ -32,35 +32,35 @@ class Ui_MainWindow(object):
|
|||||||
self.hboxlayout.setMargin(0)
|
self.hboxlayout.setMargin(0)
|
||||||
self.hboxlayout.setObjectName("hboxlayout")
|
self.hboxlayout.setObjectName("hboxlayout")
|
||||||
|
|
||||||
self.device_tree = LocationView(self.centralwidget)
|
self.location_view = LocationView(self.centralwidget)
|
||||||
|
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred,QtGui.QSizePolicy.Preferred)
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred,QtGui.QSizePolicy.Preferred)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.device_tree.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.location_view.sizePolicy().hasHeightForWidth())
|
||||||
self.device_tree.setSizePolicy(sizePolicy)
|
self.location_view.setSizePolicy(sizePolicy)
|
||||||
self.device_tree.setMaximumSize(QtCore.QSize(10000,90))
|
self.location_view.setMaximumSize(QtCore.QSize(10000,90))
|
||||||
self.device_tree.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
self.location_view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
self.device_tree.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
self.location_view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||||
self.device_tree.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
|
self.location_view.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
|
||||||
self.device_tree.setFlow(QtGui.QListView.TopToBottom)
|
self.location_view.setFlow(QtGui.QListView.TopToBottom)
|
||||||
self.device_tree.setSpacing(20)
|
self.location_view.setSpacing(20)
|
||||||
self.device_tree.setViewMode(QtGui.QListView.IconMode)
|
self.location_view.setViewMode(QtGui.QListView.IconMode)
|
||||||
self.device_tree.setObjectName("device_tree")
|
self.location_view.setObjectName("location_view")
|
||||||
self.hboxlayout.addWidget(self.device_tree)
|
self.hboxlayout.addWidget(self.location_view)
|
||||||
|
|
||||||
self.df = QtGui.QLabel(self.centralwidget)
|
self.vanity = QtGui.QLabel(self.centralwidget)
|
||||||
|
|
||||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred,QtGui.QSizePolicy.Preferred)
|
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred,QtGui.QSizePolicy.Preferred)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.df.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.vanity.sizePolicy().hasHeightForWidth())
|
||||||
self.df.setSizePolicy(sizePolicy)
|
self.vanity.setSizePolicy(sizePolicy)
|
||||||
self.df.setMaximumSize(QtCore.QSize(16777215,90))
|
self.vanity.setMaximumSize(QtCore.QSize(16777215,90))
|
||||||
self.df.setTextFormat(QtCore.Qt.RichText)
|
self.vanity.setTextFormat(QtCore.Qt.RichText)
|
||||||
self.df.setOpenExternalLinks(True)
|
self.vanity.setOpenExternalLinks(True)
|
||||||
self.df.setObjectName("df")
|
self.vanity.setObjectName("vanity")
|
||||||
self.hboxlayout.addWidget(self.df)
|
self.hboxlayout.addWidget(self.vanity)
|
||||||
self.gridlayout.addLayout(self.hboxlayout,0,0,1,1)
|
self.gridlayout.addLayout(self.hboxlayout,0,0,1,1)
|
||||||
|
|
||||||
self.hboxlayout1 = QtGui.QHBoxLayout()
|
self.hboxlayout1 = QtGui.QHBoxLayout()
|
||||||
@ -184,7 +184,7 @@ class Ui_MainWindow(object):
|
|||||||
|
|
||||||
def retranslateUi(self, MainWindow):
|
def retranslateUi(self, MainWindow):
|
||||||
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "libprs500", None, QtGui.QApplication.UnicodeUTF8))
|
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "libprs500", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.df.setText(QtGui.QApplication.translate("MainWindow", "For help visit <a href=\"https://libprs500.kovidgoyal.net/wiki/GuiUsage\">http://libprs500.kovidgoyal.net</a><br><br><b>libprs500</b>: %1 by <b>Kovid Goyal</b> © 2007<br>%2 %3 %4", None, QtGui.QApplication.UnicodeUTF8))
|
self.vanity.setText(QtGui.QApplication.translate("MainWindow", "For help visit <a href=\"https://libprs500.kovidgoyal.net/wiki/GuiUsage\">http://libprs500.kovidgoyal.net</a><br><br><b>libprs500</b>: %1 by <b>Kovid Goyal</b> © 2007<br>%2", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.label.setText(QtGui.QApplication.translate("MainWindow", "&Search:", None, QtGui.QApplication.UnicodeUTF8))
|
self.label.setText(QtGui.QApplication.translate("MainWindow", "&Search:", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.search.setToolTip(QtGui.QApplication.translate("MainWindow", "Search the list of books by title or author<br><br>Words separated by spaces are ANDed", None, QtGui.QApplication.UnicodeUTF8))
|
self.search.setToolTip(QtGui.QApplication.translate("MainWindow", "Search the list of books by title or author<br><br>Words separated by spaces are ANDed", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
self.search.setWhatsThis(QtGui.QApplication.translate("MainWindow", "Search the list of books by title, author, publisher, tags and comments<br><br>Words separated by spaces are ANDed", None, QtGui.QApplication.UnicodeUTF8))
|
self.search.setWhatsThis(QtGui.QApplication.translate("MainWindow", "Search the list of books by title, author, publisher, tags and comments<br><br>Words separated by spaces are ANDed", None, QtGui.QApplication.UnicodeUTF8))
|
||||||
|
@ -45,7 +45,7 @@ class LocationModel(QAbstractListModel):
|
|||||||
data = self.icons[row]
|
data = self.icons[row]
|
||||||
elif role == Qt.SizeHintRole:
|
elif role == Qt.SizeHintRole:
|
||||||
if row == 1:
|
if row == 1:
|
||||||
return QVariant(QSize(150, 70))
|
return QVariant(QSize(150, 65))
|
||||||
elif role == Qt.FontRole:
|
elif role == Qt.FontRole:
|
||||||
font = QFont()
|
font = QFont()
|
||||||
font.setBold(True)
|
font.setBold(True)
|
||||||
@ -55,13 +55,13 @@ class LocationModel(QAbstractListModel):
|
|||||||
def headerData(self, section, orientation, role):
|
def headerData(self, section, orientation, role):
|
||||||
return NONE
|
return NONE
|
||||||
|
|
||||||
def update_devices(self, cp, fs):
|
def update_devices(self, cp=None, fs=[-1, -1, -1]):
|
||||||
self.free[0] = fs[0]
|
self.free[0] = fs[0]
|
||||||
self.free[1] = max(fs[1:])
|
self.free[1] = max(fs[1:])
|
||||||
if cp == None:
|
if cp == None:
|
||||||
self.free[1] = -1
|
self.free[1] = -1
|
||||||
self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"),
|
print self.free, self.rowCount(None)
|
||||||
self.index(1), self.index(2))
|
self.reset()
|
||||||
|
|
||||||
class LocationView(QListView):
|
class LocationView(QListView):
|
||||||
|
|
||||||
|
@ -31,10 +31,9 @@ def build_windows():
|
|||||||
vm.loginInGuest('kovid', 'et tu brutus')
|
vm.loginInGuest('kovid', 'et tu brutus')
|
||||||
vm.loginInGuest(VIX_CONSOLE_USER_NAME, '')
|
vm.loginInGuest(VIX_CONSOLE_USER_NAME, '')
|
||||||
vm.runProgramInGuest('C:\\Users\kovid\Desktop\libprs500.bat', '')
|
vm.runProgramInGuest('C:\\Users\kovid\Desktop\libprs500.bat', '')
|
||||||
vm.runProgramInGuest('C:\Windows\system32\shutdown.exe', '/s')
|
|
||||||
|
|
||||||
if not glob.glob('dist/*.exe'):
|
if not glob.glob('dist/*.exe'):
|
||||||
raise Exception('Windows build has failed')
|
raise Exception('Windows build has failed')
|
||||||
|
vm.runProgramInGuest('C:\Windows\system32\shutdown.exe', '/s')
|
||||||
return os.path.basename(glob.glob('dist/*.exe')[-1])
|
return os.path.basename(glob.glob('dist/*.exe')[-1])
|
||||||
|
|
||||||
def build_osx():
|
def build_osx():
|
||||||
@ -53,6 +52,7 @@ def build_osx():
|
|||||||
c -= 10
|
c -= 10
|
||||||
if c%60==0:
|
if c%60==0:
|
||||||
print c/60, ',',
|
print c/60, ',',
|
||||||
|
sys.stdout.flush()
|
||||||
print
|
print
|
||||||
|
|
||||||
if not os.path.exists('dist/dmgdone'):
|
if not os.path.exists('dist/dmgdone'):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user