From b1f10f305902429e08d2ebb77f53dcc906712e24 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 25 Aug 2007 21:24:44 +0000 Subject: [PATCH] version 0.3.106. Serialised conversion jobs. Fix export_to_dir. --- src/libprs500/__init__.py | 2 +- src/libprs500/gui2/dialogs/lrf_single.py | 10 ++++-- src/libprs500/gui2/jobs.py | 41 ++++++++++++++++++------ src/libprs500/gui2/main.py | 12 ++++--- src/libprs500/library/database.py | 13 +++++--- 5 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/libprs500/__init__.py b/src/libprs500/__init__.py index 1c2971fd7f..781c34acb1 100644 --- a/src/libprs500/__init__.py +++ b/src/libprs500/__init__.py @@ -13,7 +13,7 @@ ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ''' E-book management software''' -__version__ = "0.3.105" +__version__ = "0.3.106" __docformat__ = "epytext" __author__ = "Kovid Goyal " __appname__ = 'libprs500' diff --git a/src/libprs500/gui2/dialogs/lrf_single.py b/src/libprs500/gui2/dialogs/lrf_single.py index 316f55b2f7..e376e0c5f7 100644 --- a/src/libprs500/gui2/dialogs/lrf_single.py +++ b/src/libprs500/gui2/dialogs/lrf_single.py @@ -58,7 +58,7 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog): self.setup_tooltips() self.initialize_options() self.db = db - self.row = row.row() + self.row = row self.id = self.db.id(self.row) self.cover_changed = False self.cpixmap = None @@ -266,7 +266,13 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog): au = qstring_to_unicode(self.gui_author.text()).split(',') if au: self.db.set_authors(self.id, au) 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_tags(self.id, qstring_to_unicode(self.tags.text()).split(',')) self.db.set_series(self.id, qstring_to_unicode(self.series.currentText())) diff --git a/src/libprs500/gui2/jobs.py b/src/libprs500/gui2/jobs.py index eaae0d79de..ab21606d30 100644 --- a/src/libprs500/gui2/jobs.py +++ b/src/libprs500/gui2/jobs.py @@ -12,7 +12,7 @@ ## 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., ## 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, \ QVariant, QThread, QModelIndex @@ -43,6 +43,7 @@ class Job(QThread): self.percent_done = 0 self.logger = logging.getLogger('Job #'+str(id)) self.logger.setLevel(logging.DEBUG) + self.is_locked = False self.log_dest = cStringIO.StringIO() handler = logging.StreamHandler(self.log_dest) handler.setLevel(logging.DEBUG) @@ -50,6 +51,18 @@ class Job(QThread): 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): self.percent_done = 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. ''' def run(self): - if self.mutex != None: - self.mutex.lock() + self.lock() last_traceback, exception = None, None try: try: @@ -69,15 +81,15 @@ class DeviceJob(Job): exception = err last_traceback = traceback.format_exc() finally: - if self.mutex != None: - self.mutex.unlock() + self.unlock() self.emit(SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'), self.id, self.description, self.result, exception, last_traceback) class ConversionJob(Job): - ''' Jobs that invlove conversion of content. Asynchronous. ''' + ''' Jobs that invlove conversion of content. Synchronous. ''' def run(self): + self.lock() last_traceback, exception = None, None try: try: @@ -87,6 +99,7 @@ class ConversionJob(Job): exception = err last_traceback = traceback.format_exc() finally: + self.unlock() 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()) @@ -101,6 +114,7 @@ class JobManager(QAbstractTableModel): self.job_create_lock = QMutex() self.job_remove_lock = QMutex() self.device_lock = QMutex() + self.conversion_lock = QMutex() self.cleanup_lock = QMutex() self.cleanup = {} self.device_job_icon = QVariant(QIcon(':/images/reader.svg')) @@ -143,8 +157,16 @@ class JobManager(QAbstractTableModel): return len(self.jobs.values()) > 0 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', '') - 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)'), self.job_done) if slot: @@ -156,8 +178,7 @@ class JobManager(QAbstractTableModel): def run_device_job(self, slot, callable, *args, **kwargs): ''' Run a job to communicate with the device. - @param slot: The function to call with the job result. It is called with - the parameters id, result, exception, formatted_traceback + @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 @@ -237,7 +258,7 @@ class JobManager(QAbstractTableModel): return QVariant(job.description) if col == 1: status = 'Waiting' - if job.isRunning(): + if job.isRunning() and not job.is_locked: status = 'Working' if job.isFinished(): status = 'Done' diff --git a/src/libprs500/gui2/main.py b/src/libprs500/gui2/main.py index 6aa7d7370d..e5e064ee56 100644 --- a/src/libprs500/gui2/main.py +++ b/src/libprs500/gui2/main.py @@ -536,14 +536,14 @@ class Main(QObject, Ui_MainWindow): d.exec_() 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) if d.selected_format: d.exec_() if d.result() == QDialog.Accepted: changed = True 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.write(data) pt.close() @@ -551,6 +551,7 @@ class Main(QObject, Ui_MainWindow): of.close() cmdline.extend(['-o', of.name]) cmdline.append(pt.name) + id = self.job_manager.run_conversion_job(self.book_converted, any2lrf, args=cmdline, job_description='Convert book:'+d.title()) @@ -642,8 +643,9 @@ class Main(QObject, Ui_MainWindow): settings.setValue("size", QVariant(self.window.size())) settings.endGroup() settings.beginGroup('Book Views') - for view in (self.library_view, self.memory_view): - view.write_settings() + self.library_view.write_settings() + if self.device_connected: + self.memory_view.write_settings() settings.endGroup() def close_event(self, e): @@ -686,7 +688,7 @@ def main(): QCoreApplication.setApplicationName(APP_TITLE) initialize_file_icon_provider() - main = Main(window) + main = Main(window) sys.excepthook = main.unhandled_exception return app.exec_() diff --git a/src/libprs500/library/database.py b/src/libprs500/library/database.py index a3a4c32b5a..9ac1dd4097 100644 --- a/src/libprs500/library/database.py +++ b/src/libprs500/library/database.py @@ -694,9 +694,11 @@ class LibraryDatabase(object): def title(self, index): 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''' - 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): id = self.id(index) @@ -1002,13 +1004,14 @@ class LibraryDatabase(object): au = self.conn.execute('SELECT author_sort FROM books WHERE id=?', (id,)).fetchone()[0] 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): by_author[au] = [] by_author[au].append(index) for au in by_author.keys(): - if not au: - au = 'Unknown' apath = os.path.join(dir, au) if not os.path.exists(apath): os.mkdir(apath)