mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
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:
parent
794f010dc0
commit
36e40ee553
@ -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,59 +851,78 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
|
|
||||||
def setData(self, index, value, role):
|
def setData(self, index, value, role):
|
||||||
if role == Qt.EditRole:
|
if role == Qt.EditRole:
|
||||||
row, col = index.row(), index.column()
|
from calibre.gui2.ui import get_gui
|
||||||
column = self.column_map[col]
|
try:
|
||||||
if self.is_custom_column(column):
|
return self._set_data(index, value)
|
||||||
if not self.set_custom_column_data(row, column, value):
|
except (IOError, OSError) as err:
|
||||||
return False
|
if getattr(err, 'errno', None) == errno.EACCES: # Permission denied
|
||||||
else:
|
import traceback
|
||||||
if column not in self.editable_cols:
|
error_dialog(get_gui(), _('Permission denied'),
|
||||||
return False
|
_('Could not change the on disk location of this'
|
||||||
val = int(value.toInt()[0]) if column == 'rating' else \
|
' book. Is it open in another program?'),
|
||||||
value.toDateTime() if column in ('timestamp', 'pubdate') else \
|
det_msg=traceback.format_exc(), show=True)
|
||||||
unicode(value.toString()).strip()
|
except:
|
||||||
id = self.db.id(row)
|
import traceback
|
||||||
books_to_refresh = set([id])
|
traceback.print_exc()
|
||||||
if column == 'rating':
|
error_dialog(get_gui(), _('Failed to set data'),
|
||||||
val = 0 if val < 0 else 5 if val > 5 else val
|
_('Could not set data, click Show Details to see why.'),
|
||||||
val *= 2
|
det_msg=traceback.format_exc(), show=True)
|
||||||
self.db.set_rating(id, val)
|
return False
|
||||||
elif column == 'series':
|
|
||||||
val = val.strip()
|
def _set_data(self, index, value):
|
||||||
if not val:
|
row, col = index.row(), index.column()
|
||||||
books_to_refresh |= self.db.set_series(id, val,
|
column = self.column_map[col]
|
||||||
allow_case_change=True)
|
if self.is_custom_column(column):
|
||||||
self.db.set_series_index(id, 1.0)
|
if not self.set_custom_column_data(row, column, value):
|
||||||
else:
|
return False
|
||||||
pat = re.compile(r'\[([.0-9]+)\]')
|
else:
|
||||||
match = pat.search(val)
|
if column not in self.editable_cols:
|
||||||
if match is not None:
|
return False
|
||||||
self.db.set_series_index(id, float(match.group(1)))
|
val = (int(value.toInt()[0]) if column == 'rating' else
|
||||||
val = pat.sub('', val).strip()
|
value.toDateTime() if column in ('timestamp', 'pubdate')
|
||||||
elif val:
|
else unicode(value.toString()).strip())
|
||||||
if tweaks['series_index_auto_increment'] != 'const':
|
id = self.db.id(row)
|
||||||
ni = self.db.get_next_series_num_for(val)
|
books_to_refresh = set([id])
|
||||||
if ni != 1:
|
if column == 'rating':
|
||||||
self.db.set_series_index(id, ni)
|
val = 0 if val < 0 else 5 if val > 5 else val
|
||||||
if val:
|
val *= 2
|
||||||
books_to_refresh |= self.db.set_series(id, val,
|
self.db.set_rating(id, val)
|
||||||
allow_case_change=True)
|
elif column == 'series':
|
||||||
elif column == 'timestamp':
|
val = val.strip()
|
||||||
if val.isNull() or not val.isValid():
|
if not val:
|
||||||
return False
|
books_to_refresh |= self.db.set_series(id, val,
|
||||||
self.db.set_timestamp(id, qt_to_dt(val, as_utc=False))
|
|
||||||
elif column == 'pubdate':
|
|
||||||
if val.isNull() or not val.isValid():
|
|
||||||
return False
|
|
||||||
self.db.set_pubdate(id, qt_to_dt(val, as_utc=False))
|
|
||||||
elif column == 'languages':
|
|
||||||
val = val.split(',')
|
|
||||||
self.db.set_languages(id, val)
|
|
||||||
else:
|
|
||||||
books_to_refresh |= self.db.set(row, column, val,
|
|
||||||
allow_case_change=True)
|
allow_case_change=True)
|
||||||
self.refresh_ids(list(books_to_refresh), row)
|
self.db.set_series_index(id, 1.0)
|
||||||
self.dataChanged.emit(index, index)
|
else:
|
||||||
|
pat = re.compile(r'\[([.0-9]+)\]')
|
||||||
|
match = pat.search(val)
|
||||||
|
if match is not None:
|
||||||
|
self.db.set_series_index(id, float(match.group(1)))
|
||||||
|
val = pat.sub('', val).strip()
|
||||||
|
elif val:
|
||||||
|
if tweaks['series_index_auto_increment'] != 'const':
|
||||||
|
ni = self.db.get_next_series_num_for(val)
|
||||||
|
if ni != 1:
|
||||||
|
self.db.set_series_index(id, ni)
|
||||||
|
if val:
|
||||||
|
books_to_refresh |= self.db.set_series(id, val,
|
||||||
|
allow_case_change=True)
|
||||||
|
elif column == 'timestamp':
|
||||||
|
if val.isNull() or not val.isValid():
|
||||||
|
return False
|
||||||
|
self.db.set_timestamp(id, qt_to_dt(val, as_utc=False))
|
||||||
|
elif column == 'pubdate':
|
||||||
|
if val.isNull() or not val.isValid():
|
||||||
|
return False
|
||||||
|
self.db.set_pubdate(id, qt_to_dt(val, as_utc=False))
|
||||||
|
elif column == 'languages':
|
||||||
|
val = val.split(',')
|
||||||
|
self.db.set_languages(id, val)
|
||||||
|
else:
|
||||||
|
books_to_refresh |= self.db.set(row, column, val,
|
||||||
|
allow_case_change=True)
|
||||||
|
self.refresh_ids(list(books_to_refresh), row)
|
||||||
|
self.dataChanged.emit(index, index)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
@ -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'),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user