mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
All the more obvious bugs have been ironed out of gui2
This commit is contained in:
parent
65681cf015
commit
3b6141f135
@ -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.86"
|
__version__ = "0.3.87"
|
||||||
__docformat__ = "epytext"
|
__docformat__ = "epytext"
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
__appname__ = 'libprs500'
|
__appname__ = 'libprs500'
|
||||||
|
@ -905,7 +905,7 @@ class PRS500(Device):
|
|||||||
space = self.free_space(end_session=False)
|
space = self.free_space(end_session=False)
|
||||||
mspace = space[0]
|
mspace = space[0]
|
||||||
cspace = space[1] if space[1] >= space[2] else space[2]
|
cspace = space[1] if space[1] >= space[2] else space[2]
|
||||||
if oncard and size > cspace - 1024*1024:
|
if oncard and size > cspace - 1024*1024:
|
||||||
raise FreeSpaceError("There is insufficient free space "+\
|
raise FreeSpaceError("There is insufficient free space "+\
|
||||||
"on the storage card")
|
"on the storage card")
|
||||||
if not oncard and size > mspace - 1024*1024:
|
if not oncard and size > mspace - 1024*1024:
|
||||||
|
@ -12,9 +12,16 @@
|
|||||||
## You should have received a copy of the GNU General Public License along
|
## You should have received a copy of the GNU General Public License along
|
||||||
## 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.Warning
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.Warning
|
||||||
|
import sys
|
||||||
|
|
||||||
from PyQt4.QtCore import QThread, SIGNAL, QObject
|
from PyQt4.QtCore import QThread, SIGNAL, QObject
|
||||||
|
|
||||||
from libprs500.devices.prs500.driver import PRS500
|
_libusb_available = False
|
||||||
|
try:
|
||||||
|
from libprs500.devices.prs500.driver import PRS500
|
||||||
|
_libusb_available = True
|
||||||
|
except OSError, err: #libusb not availabe
|
||||||
|
print >>sys.stderr, err
|
||||||
|
|
||||||
class DeviceDetector(QThread):
|
class DeviceDetector(QThread):
|
||||||
'''
|
'''
|
||||||
@ -27,14 +34,20 @@ class DeviceDetector(QThread):
|
|||||||
@param sleep_time: Time to sleep between device probes in millisecs
|
@param sleep_time: Time to sleep between device probes in millisecs
|
||||||
@type sleep_time: integer
|
@type sleep_time: integer
|
||||||
'''
|
'''
|
||||||
self.devices = ([PRS500, False],)
|
self.devices = []
|
||||||
|
if _libusb_available:
|
||||||
|
for dclass in (PRS500,):
|
||||||
|
self.devices.append([dclass, False])
|
||||||
self.sleep_time = sleep_time
|
self.sleep_time = sleep_time
|
||||||
QThread.__init__(self)
|
QThread.__init__(self)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while True:
|
while True:
|
||||||
for device in self.devices:
|
for device in self.devices:
|
||||||
connected = device[0].is_connected()
|
try:
|
||||||
|
connected = device[0].is_connected()
|
||||||
|
except:
|
||||||
|
connected = False
|
||||||
if connected and not device[1]:
|
if connected and not device[1]:
|
||||||
self.emit(SIGNAL('connected(PyQt_PyObject, PyQt_PyObject)'), device[0], True)
|
self.emit(SIGNAL('connected(PyQt_PyObject, PyQt_PyObject)'), device[0], True)
|
||||||
device[1] ^= True
|
device[1] ^= True
|
||||||
|
@ -222,7 +222,11 @@ class JobManager(QAbstractTableModel):
|
|||||||
def status_update(self, id, progress):
|
def status_update(self, id, progress):
|
||||||
keys = self.jobs.keys()
|
keys = self.jobs.keys()
|
||||||
keys.sort()
|
keys.sort()
|
||||||
row = keys.index(id)
|
try:
|
||||||
index = self.index(row, 2)
|
row = keys.index(id)
|
||||||
self.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'), index, index)
|
index = self.index(row, 2)
|
||||||
|
self.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'), index, index)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
@ -12,8 +12,7 @@
|
|||||||
## You should have received a copy of the GNU General Public License along
|
## You should have received a copy of the GNU General Public License along
|
||||||
## 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.
|
||||||
from libprs500.ptempfile import PersistentTemporaryFile
|
import os, textwrap, traceback, time, re, sre_constants
|
||||||
import os, textwrap, traceback, time, re
|
|
||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from math import cos, sin, pi
|
from math import cos, sin, pi
|
||||||
@ -24,6 +23,7 @@ from PyQt4.QtGui import QTableView, QProgressDialog, QAbstractItemView, QColor,
|
|||||||
from PyQt4.QtCore import QAbstractTableModel, QVariant, Qt, QString, \
|
from PyQt4.QtCore import QAbstractTableModel, QVariant, Qt, QString, \
|
||||||
QCoreApplication, SIGNAL, QObject, QSize, QModelIndex
|
QCoreApplication, SIGNAL, QObject, QSize, QModelIndex
|
||||||
|
|
||||||
|
from libprs500.ptempfile import PersistentTemporaryFile
|
||||||
from libprs500.library.database import LibraryDatabase
|
from libprs500.library.database import LibraryDatabase
|
||||||
from libprs500.gui2 import NONE
|
from libprs500.gui2 import NONE
|
||||||
|
|
||||||
@ -118,7 +118,15 @@ class BooksModel(QAbstractTableModel):
|
|||||||
text = text.replace('"'+quot.group(1)+'"', '')
|
text = text.replace('"'+quot.group(1)+'"', '')
|
||||||
quot = re.search('"(.*?)"', text)
|
quot = re.search('"(.*?)"', text)
|
||||||
tokens += text.split(' ')
|
tokens += text.split(' ')
|
||||||
return [re.compile(i, re.IGNORECASE) for i in tokens]
|
ans = []
|
||||||
|
for i in tokens:
|
||||||
|
try:
|
||||||
|
ans.append(re.compile(i, re.IGNORECASE))
|
||||||
|
except sre_constants.error:
|
||||||
|
continue
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def search(self, text, refinement):
|
def search(self, text, refinement):
|
||||||
tokens = self.search_tokens(text)
|
tokens = self.search_tokens(text)
|
||||||
|
@ -12,15 +12,14 @@
|
|||||||
## You should have received a copy of the GNU General Public License along
|
## You should have received a copy of the GNU General Public License along
|
||||||
## 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.Warning
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.Warning
|
||||||
from libprs500.ptempfile import PersistentTemporaryFile
|
import os, sys, traceback, StringIO, textwrap
|
||||||
import os, tempfile, sys, traceback
|
|
||||||
|
|
||||||
from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \
|
from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \
|
||||||
QSettings, QVariant, QSize, QThread
|
QSettings, QVariant, QSize, QThread
|
||||||
from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon, QMessageBox
|
from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon, QMessageBox
|
||||||
from PyQt4.QtSvg import QSvgRenderer
|
from PyQt4.QtSvg import QSvgRenderer
|
||||||
|
|
||||||
from libprs500 import __version__, __appname__
|
from libprs500 import __version__, __appname__, iswindows, isosx
|
||||||
from libprs500.ebooks.metadata.meta import get_metadata
|
from libprs500.ebooks.metadata.meta import get_metadata
|
||||||
from libprs500.devices.errors import FreeSpaceError
|
from libprs500.devices.errors import FreeSpaceError
|
||||||
from libprs500.devices.interface import Device
|
from libprs500.devices.interface import Device
|
||||||
@ -30,7 +29,7 @@ from libprs500.gui2 import APP_TITLE, warning_dialog, choose_files, error_dialog
|
|||||||
from libprs500.gui2.main_ui import Ui_MainWindow
|
from libprs500.gui2.main_ui import Ui_MainWindow
|
||||||
from libprs500.gui2.device import DeviceDetector, DeviceManager
|
from libprs500.gui2.device import DeviceDetector, DeviceManager
|
||||||
from libprs500.gui2.status import StatusBar
|
from libprs500.gui2.status import StatusBar
|
||||||
from libprs500.gui2.jobs import JobManager, JobException
|
from libprs500.gui2.jobs import JobManager
|
||||||
from libprs500.gui2.dialogs.metadata_single import MetadataSingleDialog
|
from libprs500.gui2.dialogs.metadata_single import MetadataSingleDialog
|
||||||
from libprs500.gui2.dialogs.metadata_bulk import MetadataBulkDialog
|
from libprs500.gui2.dialogs.metadata_bulk import MetadataBulkDialog
|
||||||
from libprs500.gui2.dialogs.jobs import JobsDialog
|
from libprs500.gui2.dialogs.jobs import JobsDialog
|
||||||
@ -61,6 +60,7 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
self.default_thumbnail = None
|
self.default_thumbnail = None
|
||||||
self.device_error_dialog = error_dialog(self.window, 'Error communicating with device', ' ')
|
self.device_error_dialog = error_dialog(self.window, 'Error communicating with device', ' ')
|
||||||
self.device_error_dialog.setModal(Qt.NonModal)
|
self.device_error_dialog.setModal(Qt.NonModal)
|
||||||
|
self.tb_wrapper = textwrap.TextWrapper(width=40)
|
||||||
####################### Location View ########################
|
####################### Location View ########################
|
||||||
QObject.connect(self.location_view, SIGNAL('location_selected(PyQt_PyObject)'),
|
QObject.connect(self.location_view, SIGNAL('location_selected(PyQt_PyObject)'),
|
||||||
self.location_selected)
|
self.location_selected)
|
||||||
@ -436,6 +436,12 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
self.current_view().setCurrentIndex(self.current_view().model().index(0, 0))
|
self.current_view().setCurrentIndex(self.current_view().model().index(0, 0))
|
||||||
|
|
||||||
|
|
||||||
|
def wrap_traceback(self, tb):
|
||||||
|
tb = unicode(tb, 'utf8', 'replace')
|
||||||
|
if iswindows or isosx:
|
||||||
|
tb = '\n'.join(self.tb_wrapper.wrap(tb))
|
||||||
|
return tb
|
||||||
|
|
||||||
def device_job_exception(self, id, description, exception, formatted_traceback):
|
def device_job_exception(self, id, description, exception, formatted_traceback):
|
||||||
'''
|
'''
|
||||||
Handle exceptions in threaded jobs.
|
Handle exceptions in threaded jobs.
|
||||||
@ -444,10 +450,11 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
print >>sys.stderr, exception
|
print >>sys.stderr, exception
|
||||||
print >>sys.stderr, formatted_traceback
|
print >>sys.stderr, formatted_traceback
|
||||||
if not self.device_error_dialog.isVisible():
|
if not self.device_error_dialog.isVisible():
|
||||||
msg = '<p><b>%s</b>: '%(exception.__class__.__name__,) + str(exception) + '</p>'
|
msg = u'<p><b>%s</b>: '%(exception.__class__.__name__,) + unicode(str(exception), 'utf8', 'replace') + u'</p>'
|
||||||
msg += '<p>Failed to perform <b>job</b>: '+description
|
msg += u'<p>Failed to perform <b>job</b>: '+description
|
||||||
msg += '<p>Further device related error messages will not be shown while this message is visible.'
|
msg += u'<p>Further device related error messages will not be shown while this message is visible.'
|
||||||
msg += '<p>Detailed <b>traceback</b>:<pre>'+formatted_traceback+'</pre>'
|
msg += u'<p>Detailed <b>traceback</b>:<pre>'
|
||||||
|
msg += self.wrap_traceback(formatted_traceback)
|
||||||
self.device_error_dialog.setText(msg)
|
self.device_error_dialog.setText(msg)
|
||||||
self.device_error_dialog.show()
|
self.device_error_dialog.show()
|
||||||
|
|
||||||
@ -456,10 +463,10 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
def read_settings(self):
|
def read_settings(self):
|
||||||
settings = QSettings()
|
settings = QSettings()
|
||||||
settings.beginGroup("MainWindow")
|
settings.beginGroup("MainWindow")
|
||||||
self.window.resize(settings.value("size", QVariant(QSize(1000, 700))).toSize())
|
self.window.resize(settings.value("size", QVariant(QSize(800, 600))).toSize())
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
self.database_path = settings.value("database path", QVariant(os.path\
|
self.database_path = settings.value("database path",
|
||||||
.expanduser("~/library1.db"))).toString()
|
QVariant(os.path.join(os.path.expanduser('~'),'library1.db'))).toString()
|
||||||
|
|
||||||
def write_settings(self):
|
def write_settings(self):
|
||||||
settings = QSettings()
|
settings = QSettings()
|
||||||
@ -485,13 +492,15 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
e.ignore()
|
e.ignore()
|
||||||
|
|
||||||
def unhandled_exception(self, type, value, tb):
|
def unhandled_exception(self, type, value, tb):
|
||||||
traceback.print_exception(type, value, tb, file=sys.stderr)
|
sio = StringIO.StringIO()
|
||||||
|
traceback.print_exception(type, value, tb, file=sio)
|
||||||
|
fe = sio.getvalue()
|
||||||
|
print >>sys.stderr, fe
|
||||||
if type == KeyboardInterrupt:
|
if type == KeyboardInterrupt:
|
||||||
self.window.close()
|
self.window.close()
|
||||||
self.window.thread().exit(0)
|
self.window.thread().exit(0)
|
||||||
fe = '\n'.join(traceback.format_exception(type, value, tb))
|
msg = '<p><b>' + unicode(str(value), 'utf8', 'replace') + '</b></p>'
|
||||||
msg = '<p><b>' + str(value) + '</b></p>'
|
msg += '<p>Detailed <b>traceback</b>:<pre>'+self.wrap_traceback(fe)+'</pre>'
|
||||||
msg += '<p>Detailed <b>traceback</b>:<pre>'+fe+'</pre>'
|
|
||||||
d = error_dialog(self.window, 'ERROR: Unhandled exception', msg)
|
d = error_dialog(self.window, 'ERROR: Unhandled exception', msg)
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
@ -502,6 +511,7 @@ def main():
|
|||||||
window.setWindowTitle(APP_TITLE)
|
window.setWindowTitle(APP_TITLE)
|
||||||
QCoreApplication.setOrganizationName("KovidsBrain")
|
QCoreApplication.setOrganizationName("KovidsBrain")
|
||||||
QCoreApplication.setApplicationName(APP_TITLE)
|
QCoreApplication.setApplicationName(APP_TITLE)
|
||||||
|
|
||||||
initialize_file_icon_provider()
|
initialize_file_icon_provider()
|
||||||
main = Main(window)
|
main = Main(window)
|
||||||
sys.excepthook = main.unhandled_exception
|
sys.excepthook = main.unhandled_exception
|
||||||
|
@ -90,7 +90,10 @@ class LibraryDatabase(object):
|
|||||||
obj = conn.execute('INSERT INTO books(title, timestamp) VALUES (?,?)',
|
obj = conn.execute('INSERT INTO books(title, timestamp) VALUES (?,?)',
|
||||||
(book['title'], book['timestamp']))
|
(book['title'], book['timestamp']))
|
||||||
id = obj.lastrowid
|
id = obj.lastrowid
|
||||||
authors = book['authors'].split('&')
|
authors = book['authors']
|
||||||
|
if not authors:
|
||||||
|
authors = 'Unknown'
|
||||||
|
authors = authors.split('&')
|
||||||
for a in authors:
|
for a in authors:
|
||||||
author = conn.execute('SELECT id from authors WHERE name=?', (a,)).fetchone()
|
author = conn.execute('SELECT id from authors WHERE name=?', (a,)).fetchone()
|
||||||
if author:
|
if author:
|
||||||
@ -644,7 +647,7 @@ class LibraryDatabase(object):
|
|||||||
'''Cover as a data string or None'''
|
'''Cover as a data string or None'''
|
||||||
id = self.id(index)
|
id = self.id(index)
|
||||||
data = self.conn.execute('SELECT data FROM covers WHERE book=?', (id,)).fetchone()
|
data = self.conn.execute('SELECT data FROM covers WHERE book=?', (id,)).fetchone()
|
||||||
if not data:
|
if not data or not data[0]:
|
||||||
return None
|
return None
|
||||||
return(decompress(data[0]))
|
return(decompress(data[0]))
|
||||||
|
|
||||||
|
@ -58,5 +58,5 @@ def PersistentTemporaryFile(suffix="", prefix="", dir=None):
|
|||||||
prefix = ""
|
prefix = ""
|
||||||
fd, name = tempfile.mkstemp(suffix, __appname__+"_"+ __version__+"_" + prefix,
|
fd, name = tempfile.mkstemp(suffix, __appname__+"_"+ __version__+"_" + prefix,
|
||||||
dir=dir)
|
dir=dir)
|
||||||
_file = os.fdopen(fd, "wb")
|
_file = os.fdopen(fd, 'w+b')
|
||||||
return _TemporaryFileWrapper(_file, name)
|
return _TemporaryFileWrapper(_file, name)
|
||||||
|
@ -355,7 +355,8 @@ r'''<?xml version='1.0' encoding='windows-1252'?>
|
|||||||
|
|
||||||
|
|
||||||
class BuildEXE(build_exe):
|
class BuildEXE(build_exe):
|
||||||
manifest_resource_id = 0
|
manifest_resource_id = 0
|
||||||
|
QT_PREFIX = r'C:\\Qt\\4.3.0'
|
||||||
MANIFEST_TEMPLATE = '''
|
MANIFEST_TEMPLATE = '''
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
@ -393,7 +394,20 @@ class BuildEXE(build_exe):
|
|||||||
print 'Adding', qtxmldll
|
print 'Adding', qtxmldll
|
||||||
shutil.copyfile(qtxmldll,
|
shutil.copyfile(qtxmldll,
|
||||||
os.path.join(self.dist_dir, os.path.basename(qtxmldll)))
|
os.path.join(self.dist_dir, os.path.basename(qtxmldll)))
|
||||||
|
print 'Adding plugins...',
|
||||||
|
qt_prefix = self.QT_PREFIX
|
||||||
|
if qtsvgdll:
|
||||||
|
qt_prefix = os.path.dirname(os.path.dirname(qtsvgdll))
|
||||||
|
plugdir = os.path.join(qt_prefix, 'plugins')
|
||||||
|
for d in ('imageformats', 'codecs', 'iconengines'):
|
||||||
|
print d,
|
||||||
|
imfd = os.path.join(plugdir, d)
|
||||||
|
tg = os.path.join(self.dist_dir, d)
|
||||||
|
if os.path.exists(tg):
|
||||||
|
shutil.rmtree(tg)
|
||||||
|
shutil.copytree(imfd, tg)
|
||||||
|
|
||||||
|
print
|
||||||
print
|
print
|
||||||
print 'Building Installer'
|
print 'Building Installer'
|
||||||
installer = NSISInstaller(APPNAME, self.dist_dir, 'dist')
|
installer = NSISInstaller(APPNAME, self.dist_dir, 'dist')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user