Handle device removal

This commit is contained in:
Kovid Goyal 2007-08-05 00:39:28 +00:00
parent ef0df0e877
commit 6f8b824da9
6 changed files with 77 additions and 22 deletions

View File

@ -51,6 +51,9 @@ class DeviceManager(QObject):
self.device_class = device_class
self.device = device_class()
def device_removed(self):
self.device = None
def info_func(self):
''' Return callable that returns device information and free space on device'''
def get_device_information(updater):

View File

@ -289,7 +289,7 @@
<item>
<widget class="QToolButton" name="add_format_button" >
<property name="toolTip" >
<string>Add a new format for this book</string>
<string>Add a new format for this book to the database</string>
</property>
<property name="text" >
<string>...</string>
@ -297,6 +297,12 @@
<property name="icon" >
<iconset resource="../images.qrc" >:/images/plus.svg</iconset>
</property>
<property name="iconSize" >
<size>
<width>32</width>
<height>32</height>
</size>
</property>
</widget>
</item>
<item>
@ -324,7 +330,13 @@
<string>...</string>
</property>
<property name="icon" >
<iconset resource="../images.qrc" >:/images/list_remove.svg</iconset>
<iconset resource="../images.qrc" >:/images/trash.svg</iconset>
</property>
<property name="iconSize" >
<size>
<width>32</width>
<height>32</height>
</size>
</property>
</widget>
</item>

View File

@ -15,7 +15,7 @@
import traceback, textwrap
from PyQt4.QtCore import QAbstractTableModel, QMutex, QObject, SIGNAL, Qt, \
QVariant, QThread
QVariant, QThread, QModelIndex
from PyQt4.QtGui import QIcon
from libprs500.gui2 import NONE
@ -55,8 +55,8 @@ class Job(QThread):
finally:
if self.mutex != None:
self.mutex.unlock()
self.emit(SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
self.id, self.result, exception, last_traceback)
self.emit(SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
self.id, self.description, self.result, exception, last_traceback)
def progress_update(self, val):
self.percent_done = val
@ -87,6 +87,18 @@ class JobManager(QAbstractTableModel):
self.job_icon = QVariant(QIcon(':/images/jobs.svg'))
self.wrapper = textwrap.TextWrapper(width=40)
def terminate_device_jobs(self):
changed = False
for key in self.jobs.keys():
if isinstance(self.jobs[key], DeviceJob):
changed = True
job = self.jobs.pop(key)
job.terminate()
job.mutex.unlock()
self.emit(SIGNAL('job_done(int)'), job.id)
if changed:
self.reset()
def create_job(self, job_class, description, lock, *args, **kwargs):
self.job_create_lock.lock()
try:
@ -94,9 +106,10 @@ class JobManager(QAbstractTableModel):
job = job_class(self.next_id, description, lock, *args, **kwargs)
QObject.connect(job, SIGNAL('finished()'), self.cleanup_jobs)
QObject.connect(job, SIGNAL('status_update(int, int)'), self.status_update)
self.beginInsertRows(QModelIndex(), len(self.jobs), len(self.jobs))
self.jobs[self.next_id] = job
self.endInsertRows()
self.emit(SIGNAL('job_added(int)'), self.next_id)
self.reset()
return job
finally:
self.job_create_lock.unlock()
@ -122,10 +135,10 @@ class JobManager(QAbstractTableModel):
desc = callable.__doc__ if callable.__doc__ else ''
desc += kwargs.pop('job_extra_description', '')
job = self.create_job(DeviceJob, desc, self.device_lock, callable, *args, **kwargs)
QObject.connect(job, SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
QObject.connect(job, SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
self.job_done)
if slot:
QObject.connect(job, SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
QObject.connect(job, SIGNAL('jobdone(PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject, PyQt_PyObject)'),
slot)
job.start()
return job.id
@ -134,10 +147,16 @@ class JobManager(QAbstractTableModel):
'''
Slot that is called when a job is completed.
'''
keys = self.jobs.keys()
if not id in keys: # Terminated job
return
self.job_remove_lock.lock()
try:
job = self.jobs.pop(id)
self.reset()
keys.sort()
idx = keys.index(id)
self.beginRemoveRows(QModelIndex(), idx, idx)
job = self.jobs.pop(id)
self.endRemoveRows()
self.cleanup_lock.lock()
self.cleanup[id] = job
self.cleanup_lock.unlock()

View File

@ -15,8 +15,9 @@
import os, tempfile, sys
from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \
QSettings, QVariant, QSize, QThread
from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon, QMessageBox
QSettings, QVariant, QSize, QThread, QModelIndex
from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon, QMessageBox, \
QItemSelectionModel
from PyQt4.QtSvg import QSvgRenderer
from libprs500 import __version__, __appname__
@ -149,13 +150,23 @@ class Main(QObject, Ui_MainWindow):
func = self.device_manager.info_func()
self.job_manager.run_device_job(self.info_read, func)
self.set_default_thumbnail(cls.THUMBNAIL_HEIGHT)
self.status_bar.showMessage('Device: '+cls.__name__+' detected.', 3000)
self.action_sync.setEnabled(True)
else:
self.job_manager.terminate_device_jobs()
self.device_manager.device_removed()
self.location_view.model().update_devices()
self.action_sync.setEnabled(False)
if self.current_view() != self.library_view:
self.status_bar.reset_info()
self.location_selected('library')
def info_read(self, id, result, exception, formatted_traceback):
def info_read(self, id, description, result, exception, formatted_traceback):
'''
Called once device information has been read.
'''
if exception:
self.job_exception(id, exception, formatted_traceback)
self.job_exception(id, description, exception, formatted_traceback)
return
info, cp, fs = result
self.location_view.model().update_devices(cp, fs)
@ -163,12 +174,12 @@ class Main(QObject, Ui_MainWindow):
func = self.device_manager.books_func()
self.job_manager.run_device_job(self.metadata_downloaded, func)
def metadata_downloaded(self, id, result, exception, formatted_traceback):
def metadata_downloaded(self, id, description, result, exception, formatted_traceback):
'''
Called once metadata has been read for all books on the device.
'''
if exception:
self.job_exception(id, exception, formatted_traceback)
self.job_exception(id, description, exception, formatted_traceback)
return
mainlist, cardlist = result
self.memory_view.set_database(mainlist)
@ -191,12 +202,12 @@ class Main(QObject, Ui_MainWindow):
self.device_manager.sync_booklists_func(),
self.booklists())
def metadata_synced(self, id, result, exception, formatted_traceback):
def metadata_synced(self, id, description, result, exception, formatted_traceback):
'''
Called once metadata has been uploaded.
'''
if exception:
self.job_exception(id, exception, formatted_traceback)
self.job_exception(id, description, exception, formatted_traceback)
return
cp, fs = result
self.location_view.model().update_devices(cp, fs)
@ -249,7 +260,7 @@ class Main(QObject, Ui_MainWindow):
)
self.upload_memory[id] = metadata
def books_uploaded(self, id, result, exception, formatted_traceback):
def books_uploaded(self, id, description, result, exception, formatted_traceback):
'''
Called once books have been uploaded.
'''
@ -263,7 +274,7 @@ class Main(QObject, Ui_MainWindow):
'</p>\n<ul>%s</ul>'%(titles,))
d.exec_()
else:
self.job_exception(id, exception, formatted_traceback)
self.job_exception(id, description, exception, formatted_traceback)
return
self.device_manager.add_books_to_metadata(result, metadata, self.booklists())
@ -301,14 +312,14 @@ class Main(QObject, Ui_MainWindow):
self.device_manager.delete_books_func(), paths)
def books_deleted(self, id, result, exception, formatted_traceback):
def books_deleted(self, id, description, result, exception, formatted_traceback):
'''
Called once deletion is done on the device
'''
for view in (self.memory_view, self.card_view):
view.model().deletion_done(id, bool(exception))
if exception:
self.job_exception(id, exception, formatted_traceback)
self.job_exception(id, description, exception, formatted_traceback)
return
self.upload_booklists()
@ -418,6 +429,10 @@ class Main(QObject, Ui_MainWindow):
view.resizeRowsToContents()
view.resizeColumnsToContents()
view.resize_on_select = False
self.status_bar.reset_info()
self.current_view().clearSelection()
self.current_view().setCurrentIndex(view.model().index(0, 0))
def job_exception(self, id, exception, formatted_traceback):
'''

View File

@ -365,6 +365,9 @@
</property>
</action>
<action name="action_sync" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="icon" >
<iconset resource="images.qrc" >:/images/sync.svg</iconset>
</property>

View File

@ -120,6 +120,9 @@ class StatusBar(QStatusBar):
self.book_info = BookInfoDisplay(self.clearMessage)
self.addWidget(self.book_info)
def reset_info(self):
self.book_info.show_data({})
def jobs(self):
src = qstring_to_unicode(self.movie_button.jobs.text())
return int(src.rpartition(':')[2].lstrip())