On windows when changing title or author via the main book list, handle the case of one of the books files being open in naother program more gracefully. Fixes #880585 (Changing the case of title generates "OSError:[Errno 13] Permission Denied...")

This commit is contained in:
Kovid Goyal 2011-11-10 12:35:24 +05:30
parent 794f010dc0
commit 36e40ee553
2 changed files with 75 additions and 56 deletions

View File

@ -5,13 +5,13 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import functools, re, os, traceback import functools, re, os, traceback, errno
from collections import defaultdict from collections import defaultdict
from PyQt4.Qt import (QAbstractTableModel, Qt, pyqtSignal, QIcon, QImage, from PyQt4.Qt import (QAbstractTableModel, Qt, pyqtSignal, QIcon, QImage,
QModelIndex, QVariant, QDateTime, QColor) QModelIndex, QVariant, QDateTime, QColor)
from calibre.gui2 import NONE, UNDEFINED_QDATETIME from calibre.gui2 import NONE, UNDEFINED_QDATETIME, error_dialog
from calibre.utils.pyparsing import ParseException from calibre.utils.pyparsing import ParseException
from calibre.ebooks.metadata import fmt_sidx, authors_to_string, string_to_authors from calibre.ebooks.metadata import fmt_sidx, authors_to_string, string_to_authors
from calibre.ebooks.metadata.book.base import SafeFormat from calibre.ebooks.metadata.book.base import SafeFormat
@ -851,6 +851,25 @@ class BooksModel(QAbstractTableModel): # {{{
def setData(self, index, value, role): def setData(self, index, value, role):
if role == Qt.EditRole: if role == Qt.EditRole:
from calibre.gui2.ui import get_gui
try:
return self._set_data(index, value)
except (IOError, OSError) as err:
if getattr(err, 'errno', None) == errno.EACCES: # Permission denied
import traceback
error_dialog(get_gui(), _('Permission denied'),
_('Could not change the on disk location of this'
' book. Is it open in another program?'),
det_msg=traceback.format_exc(), show=True)
except:
import traceback
traceback.print_exc()
error_dialog(get_gui(), _('Failed to set data'),
_('Could not set data, click Show Details to see why.'),
det_msg=traceback.format_exc(), show=True)
return False
def _set_data(self, index, value):
row, col = index.row(), index.column() row, col = index.row(), index.column()
column = self.column_map[col] column = self.column_map[col]
if self.is_custom_column(column): if self.is_custom_column(column):
@ -859,9 +878,9 @@ class BooksModel(QAbstractTableModel): # {{{
else: else:
if column not in self.editable_cols: if column not in self.editable_cols:
return False return False
val = int(value.toInt()[0]) if column == 'rating' else \ val = (int(value.toInt()[0]) if column == 'rating' else
value.toDateTime() if column in ('timestamp', 'pubdate') else \ value.toDateTime() if column in ('timestamp', 'pubdate')
unicode(value.toString()).strip() else unicode(value.toString()).strip())
id = self.db.id(row) id = self.db.id(row)
books_to_refresh = set([id]) books_to_refresh = set([id])
if column == 'rating': if column == 'rating':

View File

@ -440,8 +440,8 @@ class MetadataSingleDialogBase(ResizableDialog):
return False return False
self.books_to_refresh |= getattr(widget, 'books_to_refresh', self.books_to_refresh |= getattr(widget, 'books_to_refresh',
set([])) set([]))
except IOError as err: except (IOError, OSError) as err:
if err.errno == errno.EACCES: # Permission denied if getattr(err, 'errno', None) == errno.EACCES: # Permission denied
import traceback import traceback
fname = err.filename if err.filename else 'file' fname = err.filename if err.filename else 'file'
error_dialog(self, _('Permission denied'), error_dialog(self, _('Permission denied'),