Fix true/false searches dont work on device views (807262). Fix renaming of collections in device views (807256). Improved disaply of grouped search terms in Tag Browser

This commit is contained in:
Kovid Goyal 2011-07-08 10:26:44 -06:00
commit d7175e67bd
6 changed files with 44 additions and 21 deletions

View File

@ -446,9 +446,8 @@ class EditMetadataAction(InterfaceAction):
if d.result() == d.Accepted:
to_rename = d.to_rename # dict of new text to old ids
to_delete = d.to_delete # list of ids
for text in to_rename:
for old_id in to_rename[text]:
model.rename_collection(old_id, new_name=unicode(text))
for old_id, new_name in to_rename.iteritems():
model.rename_collection(old_id, new_name=unicode(new_name))
for item in to_delete:
model.delete_collection_using_id(item)
self.gui.upload_collections(model.db, view=view, oncard=oncard)

View File

@ -950,11 +950,11 @@ class OnDeviceSearch(SearchQueryParser): # {{{
for locvalue in locations:
accessor = q[locvalue]
if query == 'true':
if accessor(row) is not None:
if accessor(row):
matches.add(index)
continue
if query == 'false':
if accessor(row) is None:
if not accessor(row):
matches.add(index)
continue
if locvalue == 'inlibrary':

View File

@ -12,7 +12,7 @@ import traceback, cPickle, copy
from itertools import repeat
from PyQt4.Qt import (QAbstractItemModel, QIcon, QVariant, QFont, Qt,
QMimeData, QModelIndex, pyqtSignal)
QMimeData, QModelIndex, pyqtSignal, QObject)
from calibre.gui2 import NONE, gprefs, config, error_dialog
from calibre.library.database2 import Tag
@ -227,6 +227,10 @@ class TagsModel(QAbstractItemModel): # {{{
self._build_in_progress = False
self.reread_collapse_model({}, rebuild=False)
@property
def gui_parent(self):
return QObject.parent(self)
def reread_collapse_model(self, state_map, rebuild=True):
if gprefs['tags_browser_collapse_at'] == 0:
self.collapse_model = 'disable'
@ -315,9 +319,11 @@ class TagsModel(QAbstractItemModel): # {{{
for i,p in enumerate(path_parts):
path += p
if path not in category_node_map:
icon = self.category_icon_map['gst'] if is_gst else \
self.category_icon_map[key]
node = self.create_node(parent=last_category_node,
data=p[1:] if i == 0 else p,
category_icon=self.category_icon_map[key],
category_icon=icon,
tooltip=tt if path == key else path,
category_key=path,
icon_map=self.icon_state_map)
@ -375,6 +381,7 @@ class TagsModel(QAbstractItemModel): # {{{
collapse_letter = None
category_node = category
key = category_node.category_key
is_gst = category_node.is_gst
if key not in data:
return
cat_len = len(data[key])
@ -455,6 +462,7 @@ class TagsModel(QAbstractItemModel): # {{{
tooltip = None, temporary=True,
category_key=category_node.category_key,
icon_map=self.icon_state_map)
sub_cat.is_gst = is_gst
node_parent = sub_cat
else:
node_parent = category
@ -722,12 +730,12 @@ class TagsModel(QAbstractItemModel): # {{{
if (key == 'authors' and len(ids) >= 5):
if not confirm('<p>'+_('Changing the authors for several books can '
'take a while. Are you sure?')
+'</p>', 'tag_browser_drop_authors', self.parent()):
+'</p>', 'tag_browser_drop_authors', self.gui_parent):
return
elif len(ids) > 15:
if not confirm('<p>'+_('Changing the metadata for that many books '
'can take a while. Are you sure?')
+'</p>', 'tag_browser_many_changes', self.parent()):
+'</p>', 'tag_browser_many_changes', self.gui_parent):
return
fm = self.db.metadata_for_field(key)
@ -871,13 +879,13 @@ class TagsModel(QAbstractItemModel): # {{{
# we position at the parent label
val = unicode(value.toString()).strip()
if not val:
error_dialog(self.parent(), _('Item is blank'),
error_dialog(self.gui_parent, _('Item is blank'),
_('An item cannot be set to nothing. Delete it instead.')).exec_()
return False
item = self.get_node(index)
if item.type == TagTreeItem.CATEGORY and item.category_key.startswith('@'):
if val.find('.') >= 0:
error_dialog(self.parent(), _('Rename user category'),
error_dialog(self.gui_parent, _('Rename user category'),
_('You cannot use periods in the name when '
'renaming user categories'), show=True)
return False
@ -897,7 +905,7 @@ class TagsModel(QAbstractItemModel): # {{{
if len(c) == len(ckey):
if strcmp(ckey, nkey) != 0 and \
nkey_lower in user_cat_keys_lower:
error_dialog(self.parent(), _('Rename user category'),
error_dialog(self.gui_parent, _('Rename user category'),
_('The name %s is already used')%nkey, show=True)
return False
user_cats[nkey] = user_cats[ckey]
@ -906,7 +914,7 @@ class TagsModel(QAbstractItemModel): # {{{
rest = c[len(ckey):]
if strcmp(ckey, nkey) != 0 and \
icu_lower(nkey + rest) in user_cat_keys_lower:
error_dialog(self.parent(), _('Rename user category'),
error_dialog(self.gui_parent, _('Rename user category'),
_('The name %s is already used')%(nkey+rest), show=True)
return False
user_cats[nkey + rest] = user_cats[ckey + rest]
@ -921,12 +929,12 @@ class TagsModel(QAbstractItemModel): # {{{
return False
if key == 'authors':
if val.find('&') >= 0:
error_dialog(self.parent(), _('Invalid author name'),
error_dialog(self.gui_parent, _('Invalid author name'),
_('Author names cannot contain & characters.')).exec_()
return False
if key == 'search':
if val in saved_searches().names():
error_dialog(self.parent(), _('Duplicate search name'),
error_dialog(self.gui_parent, _('Duplicate search name'),
_('The saved search name %s is already used.')%val).exec_()
return False
saved_searches().rename(unicode(item.data(role).toString()), val)
@ -1161,7 +1169,10 @@ class TagsModel(QAbstractItemModel): # {{{
prefix = ' not '
else:
prefix = ''
category = tag.category if key != 'news' else 'tag'
if node.is_gst:
category = key
else:
category = tag.category if key != 'news' else 'tag'
add_colon = False
if self.db.field_metadata[tag.category]['is_csp']:
add_colon = True

View File

@ -218,7 +218,7 @@ class TagBrowserMixin(object): # {{{
d = TagListEditor(self, tag_to_match=tag, data=result, key=key)
d.exec_()
if d.result() == d.Accepted:
to_rename = d.to_rename # dict of new text to old id
to_rename = d.to_rename # dict of old id to new name
to_delete = d.to_delete # list of ids
orig_name = d.original_names # dict of id: name

View File

@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en'
The database used to store ebook metadata
'''
import os, sys, shutil, cStringIO, glob, time, functools, traceback, re, \
json, uuid, tempfile, hashlib
json, uuid, tempfile, hashlib, copy
from collections import defaultdict
import threading, random
from itertools import repeat
@ -1794,10 +1794,22 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
for user_cat in sorted(user_categories.keys(), key=sort_key):
items = []
names_seen = {}
for (name,label,ign) in user_categories[user_cat]:
n = icu_lower(name)
if label in taglist and n in taglist[label]:
items.append(taglist[label][n])
if user_cat in gst:
# for gst items, make copy and consolidate the tags by name.
if n in names_seen:
names_seen[n].id_set |= taglist[label][n].id_set
names_seen[n].count += taglist[label][n].count
else:
t = copy.copy(taglist[label][n])
t.icon = icon_map['gst']
names_seen[t.name] = t
items.append(t)
else:
items.append(taglist[label][n])
# else: do nothing, to not include nodes w zero counts
cat_name = '@' + user_cat # add the '@' to avoid name collision
# Not a problem if we accumulate entries in the icon map

View File

@ -17,7 +17,7 @@ class TagsIcons(dict):
category_icons = ['authors', 'series', 'formats', 'publisher', 'rating',
'news', 'tags', 'custom:', 'user:', 'search',
'identifiers']
'identifiers', 'gst']
def __init__(self, icon_dict):
for a in self.category_icons:
if a not in icon_dict:
@ -35,7 +35,8 @@ category_icon_map = {
'custom:' : 'column.png',
'user:' : 'tb_folder.png',
'search' : 'search.png',
'identifiers': 'identifiers.png'
'identifiers': 'identifiers.png',
'gst' : 'catalog.png',
}