This commit is contained in:
Kovid Goyal 2013-05-19 12:57:16 +05:30
parent dec4fbf398
commit 70340d8b7c

View File

@ -109,7 +109,7 @@ class ColumnIcon(object):
except: except:
pass pass
class BooksModel(QAbstractTableModel): # {{{ class BooksModel(QAbstractTableModel): # {{{
about_to_be_sorted = pyqtSignal(object, name='aboutToBeSorted') about_to_be_sorted = pyqtSignal(object, name='aboutToBeSorted')
sorting_done = pyqtSignal(object, name='sortingDone') sorting_done = pyqtSignal(object, name='sortingDone')
@ -150,7 +150,7 @@ class BooksModel(QAbstractTableModel): # {{{
self.default_image = default_image() self.default_image = default_image()
self.sorted_on = DEFAULT_SORT self.sorted_on = DEFAULT_SORT
self.sort_history = [self.sorted_on] self.sort_history = [self.sorted_on]
self.last_search = '' # The last search performed on this model self.last_search = '' # The last search performed on this model
self.column_map = [] self.column_map = []
self.headers = {} self.headers = {}
self.alignment_map = {} self.alignment_map = {}
@ -240,7 +240,6 @@ class BooksModel(QAbstractTableModel): # {{{
# Would like to to a join here, but the thread might be waiting to # Would like to to a join here, but the thread might be waiting to
# do something on the GUI thread. Deadlock. # do something on the GUI thread. Deadlock.
def refresh_ids(self, ids, current_row=-1): def refresh_ids(self, ids, current_row=-1):
self._clear_caches() self._clear_caches()
rows = self.db.refresh_ids(ids) rows = self.db.refresh_ids(ids)
@ -284,7 +283,7 @@ class BooksModel(QAbstractTableModel): # {{{
def row_indices(self, index): def row_indices(self, index):
''' Return list indices of all cells in index.row()''' ''' Return list indices of all cells in index.row()'''
return [ self.index(index.row(), c) for c in range(self.columnCount(None))] return [self.index(index.row(), c) for c in range(self.columnCount(None))]
@property @property
def by_author(self): def by_author(self):
@ -332,7 +331,7 @@ class BooksModel(QAbstractTableModel): # {{{
while True: while True:
row_ += 1 if forward else -1 row_ += 1 if forward else -1
if row_ < 0: if row_ < 0:
row_ = self.count() - 1; row_ = self.count() - 1
elif row_ >= self.count(): elif row_ >= self.count():
row_ = 0 row_ = 0
if self.id(row_) in self.ids_to_highlight_set: if self.id(row_) in self.ids_to_highlight_set:
@ -611,7 +610,7 @@ class BooksModel(QAbstractTableModel): # {{{
data = None data = None
try: try:
data = self.db.cover(row_number) data = self.db.cover(row_number)
except IndexError: # Happens if database has not yet been refreshed except IndexError: # Happens if database has not yet been refreshed
pass pass
if not data: if not data:
@ -673,7 +672,7 @@ class BooksModel(QAbstractTableModel): # {{{
return QVariant(UNDEFINED_QDATETIME) return QVariant(UNDEFINED_QDATETIME)
def bool_type(r, idx=-1): def bool_type(r, idx=-1):
return None # displayed using a decorator return None # displayed using a decorator
def bool_type_decorator(r, idx=-1, bool_cols_are_tristate=True): def bool_type_decorator(r, idx=-1, bool_cols_are_tristate=True):
val = force_to_bool(self.db.data[r][idx]) val = force_to_bool(self.db.data[r][idx])
@ -884,18 +883,18 @@ class BooksModel(QAbstractTableModel): # {{{
ans = Qt.AlignVCenter | ALIGNMENT_MAP[self.alignment_map.get(cname, ans = Qt.AlignVCenter | ALIGNMENT_MAP[self.alignment_map.get(cname,
'left')] 'left')]
return QVariant(ans) return QVariant(ans)
#elif role == Qt.ToolTipRole and index.isValid(): # elif role == Qt.ToolTipRole and index.isValid():
# if self.column_map[index.column()] in self.editable_cols: # if self.column_map[index.column()] in self.editable_cols:
# return QVariant(_("Double click to <b>edit</b> me<br><br>")) # return QVariant(_("Double click to <b>edit</b> me<br><br>"))
return NONE return NONE
def headerData(self, section, orientation, role): def headerData(self, section, orientation, role):
if orientation == Qt.Horizontal: if orientation == Qt.Horizontal:
if section >= len(self.column_map): # same problem as in data, the column_map can be wrong if section >= len(self.column_map): # same problem as in data, the column_map can be wrong
return None return None
if role == Qt.ToolTipRole: if role == Qt.ToolTipRole:
ht = self.column_map[section] ht = self.column_map[section]
if ht == 'timestamp': # change help text because users know this field as 'date' if ht == 'timestamp': # change help text because users know this field as 'date'
ht = 'date' ht = 'date'
return QVariant(_('The lookup/search name is "{0}"').format(ht)) return QVariant(_('The lookup/search name is "{0}"').format(ht))
if role == Qt.DisplayRole: if role == Qt.DisplayRole:
@ -905,11 +904,10 @@ class BooksModel(QAbstractTableModel): # {{{
col = self.db.field_metadata['uuid']['rec_index'] col = self.db.field_metadata['uuid']['rec_index']
return QVariant(_('This book\'s UUID is "{0}"').format(self.db.data[section][col])) return QVariant(_('This book\'s UUID is "{0}"').format(self.db.data[section][col]))
if role == Qt.DisplayRole: # orientation is vertical if role == Qt.DisplayRole: # orientation is vertical
return QVariant(section+1) return QVariant(section+1)
return NONE return NONE
def flags(self, index): def flags(self, index):
flags = QAbstractTableModel.flags(self, index) flags = QAbstractTableModel.flags(self, index)
if index.isValid(): if index.isValid():
@ -969,7 +967,7 @@ class BooksModel(QAbstractTableModel): # {{{
tmpl = unicode(value.toString()).strip() tmpl = unicode(value.toString()).strip()
disp = cc['display'] disp = cc['display']
disp['composite_template'] = tmpl disp['composite_template'] = tmpl
self.db.set_custom_column_metadata(cc['colnum'], display = disp) self.db.set_custom_column_metadata(cc['colnum'], display=disp)
self.refresh(reset=True) self.refresh(reset=True)
return True return True
@ -987,7 +985,7 @@ class BooksModel(QAbstractTableModel): # {{{
return self._set_data(index, value) return self._set_data(index, value)
except (IOError, OSError) as err: except (IOError, OSError) as err:
import traceback import traceback
if getattr(err, 'errno', None) == errno.EACCES: # Permission denied if getattr(err, 'errno', None) == errno.EACCES: # Permission denied
fname = getattr(err, 'filename', None) fname = getattr(err, 'filename', None)
p = 'Locked file: %s\n\n'%fname if fname else '' p = 'Locked file: %s\n\n'%fname if fname else ''
error_dialog(get_gui(), _('Permission denied'), error_dialog(get_gui(), _('Permission denied'),
@ -1065,7 +1063,7 @@ class BooksModel(QAbstractTableModel): # {{{
# }}} # }}}
class OnDeviceSearch(SearchQueryParser): # {{{ class OnDeviceSearch(SearchQueryParser): # {{{
USABLE_LOCATIONS = [ USABLE_LOCATIONS = [
'all', 'all',
@ -1078,7 +1076,6 @@ class OnDeviceSearch(SearchQueryParser): # {{{
'inlibrary' 'inlibrary'
] ]
def __init__(self, model): def __init__(self, model):
SearchQueryParser.__init__(self, locations=self.USABLE_LOCATIONS) SearchQueryParser.__init__(self, locations=self.USABLE_LOCATIONS)
self.model = model self.model = model
@ -1101,7 +1098,7 @@ class OnDeviceSearch(SearchQueryParser): # {{{
elif query.startswith('~'): elif query.startswith('~'):
matchkind = REGEXP_MATCH matchkind = REGEXP_MATCH
query = query[1:] query = query[1:]
if matchkind != REGEXP_MATCH: ### leave case in regexps because it can be significant e.g. \S \W \D if matchkind != REGEXP_MATCH: # leave case in regexps because it can be significant e.g. \S \W \D
query = query.lower() query = query.lower()
if location not in self.USABLE_LOCATIONS: if location not in self.USABLE_LOCATIONS:
@ -1133,9 +1130,9 @@ class OnDeviceSearch(SearchQueryParser): # {{{
if locvalue == 'inlibrary': if locvalue == 'inlibrary':
continue # this is bool, so can't match below continue # this is bool, so can't match below
try: try:
### Can't separate authors because comma is used for name sep and author sep # Can't separate authors because comma is used for name sep and author sep
### Exact match might not get what you want. For that reason, turn author # Exact match might not get what you want. For that reason, turn author
### exactmatch searches into contains searches. # exactmatch searches into contains searches.
if locvalue == 'author' and matchkind == EQUALS_MATCH: if locvalue == 'author' and matchkind == EQUALS_MATCH:
m = CONTAINS_MATCH m = CONTAINS_MATCH
else: else:
@ -1148,13 +1145,13 @@ class OnDeviceSearch(SearchQueryParser): # {{{
if _match(query, vals, m, use_primary_find_in_search=upf): if _match(query, vals, m, use_primary_find_in_search=upf):
matches.add(index) matches.add(index)
break break
except ValueError: # Unicode errors except ValueError: # Unicode errors
traceback.print_exc() traceback.print_exc()
return matches return matches
# }}} # }}}
class DeviceDBSortKeyGen(object): # {{{ class DeviceDBSortKeyGen(object): # {{{
def __init__(self, attr, keyfunc, db): def __init__(self, attr, keyfunc, db):
self.attr = attr self.attr = attr
@ -1169,7 +1166,7 @@ class DeviceDBSortKeyGen(object): # {{{
return ans return ans
# }}} # }}}
class DeviceBooksModel(BooksModel): # {{{ class DeviceBooksModel(BooksModel): # {{{
booklist_dirtied = pyqtSignal() booklist_dirtied = pyqtSignal()
upload_collections = pyqtSignal(object) upload_collections = pyqtSignal(object)
@ -1272,9 +1269,9 @@ class DeviceBooksModel(BooksModel): # {{{
if index.isValid(): if index.isValid():
cname = self.column_map[index.column()] cname = self.column_map[index.column()]
if cname in self.editable and \ if cname in self.editable and \
(cname != 'collections' or \ (cname != 'collections' or
(callable(getattr(self.db, 'supports_collections', None)) and \ (callable(getattr(self.db, 'supports_collections', None)) and
self.db.supports_collections() and \ self.db.supports_collections() and
device_prefs['manage_device_metadata']=='manual')): device_prefs['manage_device_metadata']=='manual')):
flags |= Qt.ItemIsEditable flags |= Qt.ItemIsEditable
return flags return flags
@ -1432,7 +1429,7 @@ class DeviceBooksModel(BooksModel): # {{{
return data return data
def paths(self, rows): def paths(self, rows):
return [self.db[self.map[r.row()]].path for r in rows ] return [self.db[self.map[r.row()]].path for r in rows]
def paths_for_db_ids(self, db_ids, as_map=False): def paths_for_db_ids(self, db_ids, as_map=False):
res = defaultdict(list) if as_map else [] res = defaultdict(list) if as_map else []
@ -1517,7 +1514,7 @@ class DeviceBooksModel(BooksModel): # {{{
elif role == Qt.ToolTipRole and index.isValid(): elif role == Qt.ToolTipRole and index.isValid():
if self.is_row_marked_for_deletion(row): if self.is_row_marked_for_deletion(row):
return QVariant(_('Marked for deletion')) return QVariant(_('Marked for deletion'))
if cname in ['title', 'authors'] or (cname == 'collections' and \ if cname in ['title', 'authors'] or (cname == 'collections' and
self.db.supports_collections()): self.db.supports_collections()):
return QVariant(_("Double click to <b>edit</b> me<br><br>")) return QVariant(_("Double click to <b>edit</b> me<br><br>"))
elif role == Qt.DecorationRole and cname == 'inlibrary': elif role == Qt.DecorationRole and cname == 'inlibrary':
@ -1586,3 +1583,4 @@ class DeviceBooksModel(BooksModel): # {{{
# }}} # }}}