mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
version 0.3.106. Serialised conversion jobs. Fix export_to_dir.
This commit is contained in:
parent
a71d0dc341
commit
b1f10f3059
@ -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.105"
|
__version__ = "0.3.106"
|
||||||
__docformat__ = "epytext"
|
__docformat__ = "epytext"
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
__appname__ = 'libprs500'
|
__appname__ = 'libprs500'
|
||||||
|
@ -58,7 +58,7 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
|||||||
self.setup_tooltips()
|
self.setup_tooltips()
|
||||||
self.initialize_options()
|
self.initialize_options()
|
||||||
self.db = db
|
self.db = db
|
||||||
self.row = row.row()
|
self.row = row
|
||||||
self.id = self.db.id(self.row)
|
self.id = self.db.id(self.row)
|
||||||
self.cover_changed = False
|
self.cover_changed = False
|
||||||
self.cpixmap = None
|
self.cpixmap = None
|
||||||
@ -266,7 +266,13 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
|||||||
au = qstring_to_unicode(self.gui_author.text()).split(',')
|
au = qstring_to_unicode(self.gui_author.text()).split(',')
|
||||||
if au: self.db.set_authors(self.id, au)
|
if au: self.db.set_authors(self.id, au)
|
||||||
aus = qstring_to_unicode(self.gui_author_sort.text())
|
aus = qstring_to_unicode(self.gui_author_sort.text())
|
||||||
if aus: self.db.set_author_sort(self.id, aus)
|
if not aus:
|
||||||
|
t = self.db.authors(self.id, index_is_id=True)
|
||||||
|
if not t:
|
||||||
|
t = 'Unknown'
|
||||||
|
aus = t.split(',')[0].strip()
|
||||||
|
print aus
|
||||||
|
self.db.set_author_sort(self.id, aus)
|
||||||
self.db.set_publisher(self.id, qstring_to_unicode(self.gui_publisher.text()))
|
self.db.set_publisher(self.id, qstring_to_unicode(self.gui_publisher.text()))
|
||||||
self.db.set_tags(self.id, qstring_to_unicode(self.tags.text()).split(','))
|
self.db.set_tags(self.id, qstring_to_unicode(self.tags.text()).split(','))
|
||||||
self.db.set_series(self.id, qstring_to_unicode(self.series.currentText()))
|
self.db.set_series(self.id, qstring_to_unicode(self.series.currentText()))
|
||||||
|
@ -12,7 +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.
|
||||||
import traceback, textwrap, logging, cStringIO
|
import traceback, logging, cStringIO
|
||||||
|
|
||||||
from PyQt4.QtCore import QAbstractTableModel, QMutex, QObject, SIGNAL, Qt, \
|
from PyQt4.QtCore import QAbstractTableModel, QMutex, QObject, SIGNAL, Qt, \
|
||||||
QVariant, QThread, QModelIndex
|
QVariant, QThread, QModelIndex
|
||||||
@ -43,6 +43,7 @@ class Job(QThread):
|
|||||||
self.percent_done = 0
|
self.percent_done = 0
|
||||||
self.logger = logging.getLogger('Job #'+str(id))
|
self.logger = logging.getLogger('Job #'+str(id))
|
||||||
self.logger.setLevel(logging.DEBUG)
|
self.logger.setLevel(logging.DEBUG)
|
||||||
|
self.is_locked = False
|
||||||
self.log_dest = cStringIO.StringIO()
|
self.log_dest = cStringIO.StringIO()
|
||||||
handler = logging.StreamHandler(self.log_dest)
|
handler = logging.StreamHandler(self.log_dest)
|
||||||
handler.setLevel(logging.DEBUG)
|
handler.setLevel(logging.DEBUG)
|
||||||
@ -50,6 +51,18 @@ class Job(QThread):
|
|||||||
self.logger.addHandler(handler)
|
self.logger.addHandler(handler)
|
||||||
|
|
||||||
|
|
||||||
|
def lock(self):
|
||||||
|
if self.mutex is not None:
|
||||||
|
self.is_locked = True
|
||||||
|
self.mutex.lock()
|
||||||
|
self.is_locked = False
|
||||||
|
|
||||||
|
|
||||||
|
def unlock(self):
|
||||||
|
if self.mutex is not None:
|
||||||
|
self.mutex.unlock()
|
||||||
|
self.is_locked = False
|
||||||
|
|
||||||
def progress_update(self, val):
|
def progress_update(self, val):
|
||||||
self.percent_done = val
|
self.percent_done = val
|
||||||
self.emit(SIGNAL('status_update(int, int)'), self.id, int(val))
|
self.emit(SIGNAL('status_update(int, int)'), self.id, int(val))
|
||||||
@ -59,8 +72,7 @@ class DeviceJob(Job):
|
|||||||
Jobs that involve communication with the device. Synchronous.
|
Jobs that involve communication with the device. Synchronous.
|
||||||
'''
|
'''
|
||||||
def run(self):
|
def run(self):
|
||||||
if self.mutex != None:
|
self.lock()
|
||||||
self.mutex.lock()
|
|
||||||
last_traceback, exception = None, None
|
last_traceback, exception = None, None
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
@ -69,15 +81,15 @@ class DeviceJob(Job):
|
|||||||
exception = err
|
exception = err
|
||||||
last_traceback = traceback.format_exc()
|
last_traceback = traceback.format_exc()
|
||||||
finally:
|
finally:
|
||||||
if self.mutex != None:
|
self.unlock()
|
||||||
self.mutex.unlock()
|
|
||||||
self.emit(SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
|
self.emit(SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
|
||||||
self.id, self.description, self.result, exception, last_traceback)
|
self.id, self.description, self.result, exception, last_traceback)
|
||||||
|
|
||||||
|
|
||||||
class ConversionJob(Job):
|
class ConversionJob(Job):
|
||||||
''' Jobs that invlove conversion of content. Asynchronous. '''
|
''' Jobs that invlove conversion of content. Synchronous. '''
|
||||||
def run(self):
|
def run(self):
|
||||||
|
self.lock()
|
||||||
last_traceback, exception = None, None
|
last_traceback, exception = None, None
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
@ -87,6 +99,7 @@ class ConversionJob(Job):
|
|||||||
exception = err
|
exception = err
|
||||||
last_traceback = traceback.format_exc()
|
last_traceback = traceback.format_exc()
|
||||||
finally:
|
finally:
|
||||||
|
self.unlock()
|
||||||
self.emit(SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
|
self.emit(SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
|
||||||
self.id, self.description, self.result, exception, last_traceback, self.log_dest.getvalue())
|
self.id, self.description, self.result, exception, last_traceback, self.log_dest.getvalue())
|
||||||
|
|
||||||
@ -101,6 +114,7 @@ class JobManager(QAbstractTableModel):
|
|||||||
self.job_create_lock = QMutex()
|
self.job_create_lock = QMutex()
|
||||||
self.job_remove_lock = QMutex()
|
self.job_remove_lock = QMutex()
|
||||||
self.device_lock = QMutex()
|
self.device_lock = QMutex()
|
||||||
|
self.conversion_lock = QMutex()
|
||||||
self.cleanup_lock = QMutex()
|
self.cleanup_lock = QMutex()
|
||||||
self.cleanup = {}
|
self.cleanup = {}
|
||||||
self.device_job_icon = QVariant(QIcon(':/images/reader.svg'))
|
self.device_job_icon = QVariant(QIcon(':/images/reader.svg'))
|
||||||
@ -143,8 +157,16 @@ class JobManager(QAbstractTableModel):
|
|||||||
return len(self.jobs.values()) > 0
|
return len(self.jobs.values()) > 0
|
||||||
|
|
||||||
def run_conversion_job(self, slot, callable, *args, **kwargs):
|
def run_conversion_job(self, slot, callable, *args, **kwargs):
|
||||||
|
'''
|
||||||
|
Run a conversion job.
|
||||||
|
@param slot: The function to call with the job result.
|
||||||
|
@param callable: The function to call to communicate with the device.
|
||||||
|
@param args: The arguments to pass to callable
|
||||||
|
@param kwargs: The keyword arguments to pass to callable
|
||||||
|
'''
|
||||||
desc = kwargs.pop('job_description', '')
|
desc = kwargs.pop('job_description', '')
|
||||||
job = self.create_job(ConversionJob, desc, None, callable, *args, **kwargs)
|
job = self.create_job(ConversionJob, desc, self.conversion_lock,
|
||||||
|
callable, *args, **kwargs)
|
||||||
QObject.connect(job, SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
|
QObject.connect(job, SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
|
||||||
self.job_done)
|
self.job_done)
|
||||||
if slot:
|
if slot:
|
||||||
@ -156,8 +178,7 @@ class JobManager(QAbstractTableModel):
|
|||||||
def run_device_job(self, slot, callable, *args, **kwargs):
|
def run_device_job(self, slot, callable, *args, **kwargs):
|
||||||
'''
|
'''
|
||||||
Run a job to communicate with the device.
|
Run a job to communicate with the device.
|
||||||
@param slot: The function to call with the job result. It is called with
|
@param slot: The function to call with the job result.
|
||||||
the parameters id, result, exception, formatted_traceback
|
|
||||||
@param callable: The function to call to communicate with the device.
|
@param callable: The function to call to communicate with the device.
|
||||||
@param args: The arguments to pass to callable
|
@param args: The arguments to pass to callable
|
||||||
@param kwargs: The keyword arguments to pass to callable
|
@param kwargs: The keyword arguments to pass to callable
|
||||||
@ -237,7 +258,7 @@ class JobManager(QAbstractTableModel):
|
|||||||
return QVariant(job.description)
|
return QVariant(job.description)
|
||||||
if col == 1:
|
if col == 1:
|
||||||
status = 'Waiting'
|
status = 'Waiting'
|
||||||
if job.isRunning():
|
if job.isRunning() and not job.is_locked:
|
||||||
status = 'Working'
|
status = 'Working'
|
||||||
if job.isFinished():
|
if job.isFinished():
|
||||||
status = 'Done'
|
status = 'Done'
|
||||||
|
@ -536,14 +536,14 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
changed = False
|
changed = False
|
||||||
for row in rows:
|
for row in [r.row() for r in rows]:
|
||||||
d = LRFSingleDialog(self.window, self.library_view.model().db, row)
|
d = LRFSingleDialog(self.window, self.library_view.model().db, row)
|
||||||
if d.selected_format:
|
if d.selected_format:
|
||||||
d.exec_()
|
d.exec_()
|
||||||
if d.result() == QDialog.Accepted:
|
if d.result() == QDialog.Accepted:
|
||||||
changed = True
|
changed = True
|
||||||
cmdline = d.cmdline
|
cmdline = d.cmdline
|
||||||
data = self.library_view.model().db.format(row.row(), d.selected_format)
|
data = self.library_view.model().db.format(row, d.selected_format)
|
||||||
pt = PersistentTemporaryFile('.'+d.selected_format.lower())
|
pt = PersistentTemporaryFile('.'+d.selected_format.lower())
|
||||||
pt.write(data)
|
pt.write(data)
|
||||||
pt.close()
|
pt.close()
|
||||||
@ -551,6 +551,7 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
of.close()
|
of.close()
|
||||||
cmdline.extend(['-o', of.name])
|
cmdline.extend(['-o', of.name])
|
||||||
cmdline.append(pt.name)
|
cmdline.append(pt.name)
|
||||||
|
|
||||||
id = self.job_manager.run_conversion_job(self.book_converted,
|
id = self.job_manager.run_conversion_job(self.book_converted,
|
||||||
any2lrf, args=cmdline,
|
any2lrf, args=cmdline,
|
||||||
job_description='Convert book:'+d.title())
|
job_description='Convert book:'+d.title())
|
||||||
@ -642,8 +643,9 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
settings.setValue("size", QVariant(self.window.size()))
|
settings.setValue("size", QVariant(self.window.size()))
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
settings.beginGroup('Book Views')
|
settings.beginGroup('Book Views')
|
||||||
for view in (self.library_view, self.memory_view):
|
self.library_view.write_settings()
|
||||||
view.write_settings()
|
if self.device_connected:
|
||||||
|
self.memory_view.write_settings()
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
|
|
||||||
def close_event(self, e):
|
def close_event(self, e):
|
||||||
@ -686,7 +688,7 @@ def main():
|
|||||||
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
|
||||||
return app.exec_()
|
return app.exec_()
|
||||||
|
|
||||||
|
@ -694,9 +694,11 @@ class LibraryDatabase(object):
|
|||||||
def title(self, index):
|
def title(self, index):
|
||||||
return self.data[index][1]
|
return self.data[index][1]
|
||||||
|
|
||||||
def authors(self, index):
|
def authors(self, index, index_is_id=False):
|
||||||
''' Authors as a comman separated list or None'''
|
''' Authors as a comman separated list or None'''
|
||||||
return self.data[index][2]
|
if not index_is_id:
|
||||||
|
return self.data[index][2]
|
||||||
|
return self.conn.execute('SELECT authors FROM meta WHERE id=?',(index,)).fetchone()[0]
|
||||||
|
|
||||||
def author_sort(self, index):
|
def author_sort(self, index):
|
||||||
id = self.id(index)
|
id = self.id(index)
|
||||||
@ -1002,13 +1004,14 @@ class LibraryDatabase(object):
|
|||||||
au = self.conn.execute('SELECT author_sort FROM books WHERE id=?',
|
au = self.conn.execute('SELECT author_sort FROM books WHERE id=?',
|
||||||
(id,)).fetchone()[0]
|
(id,)).fetchone()[0]
|
||||||
if not au:
|
if not au:
|
||||||
au = 'Unknown'
|
au = self.authors(index)
|
||||||
|
if not au:
|
||||||
|
au = 'Unknown'
|
||||||
|
au = au.split(',')[0]
|
||||||
if not by_author.has_key(au):
|
if not by_author.has_key(au):
|
||||||
by_author[au] = []
|
by_author[au] = []
|
||||||
by_author[au].append(index)
|
by_author[au].append(index)
|
||||||
for au in by_author.keys():
|
for au in by_author.keys():
|
||||||
if not au:
|
|
||||||
au = 'Unknown'
|
|
||||||
apath = os.path.join(dir, au)
|
apath = os.path.join(dir, au)
|
||||||
if not os.path.exists(apath):
|
if not os.path.exists(apath):
|
||||||
os.mkdir(apath)
|
os.mkdir(apath)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user