mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-31 14:33:54 -04:00
Make searches in the tag browser a possible hierarchical field.
This commit is contained in:
parent
4bfa19bbd7
commit
85214e2263
@ -9,12 +9,13 @@ from PyQt4.QtGui import QDialog
|
|||||||
from calibre.gui2.dialogs.saved_search_editor_ui import Ui_SavedSearchEditor
|
from calibre.gui2.dialogs.saved_search_editor_ui import Ui_SavedSearchEditor
|
||||||
from calibre.utils.search_query_parser import saved_searches
|
from calibre.utils.search_query_parser import saved_searches
|
||||||
from calibre.utils.icu import sort_key
|
from calibre.utils.icu import sort_key
|
||||||
|
from calibre.gui2 import error_dialog
|
||||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||||
|
|
||||||
class SavedSearchEditor(QDialog, Ui_SavedSearchEditor):
|
class SavedSearchEditor(QDialog, Ui_SavedSearchEditor):
|
||||||
|
|
||||||
def __init__(self, window, initial_search=None):
|
def __init__(self, parent, initial_search=None):
|
||||||
QDialog.__init__(self, window)
|
QDialog.__init__(self, parent)
|
||||||
Ui_SavedSearchEditor.__init__(self)
|
Ui_SavedSearchEditor.__init__(self)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
@ -22,12 +23,13 @@ class SavedSearchEditor(QDialog, Ui_SavedSearchEditor):
|
|||||||
self.connect(self.search_name_box, SIGNAL('currentIndexChanged(int)'),
|
self.connect(self.search_name_box, SIGNAL('currentIndexChanged(int)'),
|
||||||
self.current_index_changed)
|
self.current_index_changed)
|
||||||
self.connect(self.delete_search_button, SIGNAL('clicked()'), self.del_search)
|
self.connect(self.delete_search_button, SIGNAL('clicked()'), self.del_search)
|
||||||
|
self.rename_button.clicked.connect(self.rename_search)
|
||||||
|
|
||||||
self.current_search_name = None
|
self.current_search_name = None
|
||||||
self.searches = {}
|
self.searches = {}
|
||||||
self.searches_to_delete = []
|
|
||||||
for name in saved_searches().names():
|
for name in saved_searches().names():
|
||||||
self.searches[name] = saved_searches().lookup(name)
|
self.searches[name] = saved_searches().lookup(name)
|
||||||
|
self.search_names = set([icu_lower(n) for n in saved_searches().names()])
|
||||||
|
|
||||||
self.populate_search_list()
|
self.populate_search_list()
|
||||||
if initial_search is not None and initial_search in self.searches:
|
if initial_search is not None and initial_search in self.searches:
|
||||||
@ -42,6 +44,11 @@ class SavedSearchEditor(QDialog, Ui_SavedSearchEditor):
|
|||||||
search_name = unicode(self.input_box.text()).strip()
|
search_name = unicode(self.input_box.text()).strip()
|
||||||
if search_name == '':
|
if search_name == '':
|
||||||
return False
|
return False
|
||||||
|
if icu_lower(search_name) in self.search_names:
|
||||||
|
error_dialog(self, _('Saved search already exists'),
|
||||||
|
_('The saved search %s already exists, perhaps with '
|
||||||
|
'different case')%search_name).exec_()
|
||||||
|
return False
|
||||||
if search_name not in self.searches:
|
if search_name not in self.searches:
|
||||||
self.searches[search_name] = ''
|
self.searches[search_name] = ''
|
||||||
self.populate_search_list()
|
self.populate_search_list()
|
||||||
@ -57,10 +64,25 @@ class SavedSearchEditor(QDialog, Ui_SavedSearchEditor):
|
|||||||
+'</p>', 'saved_search_editor_delete', self):
|
+'</p>', 'saved_search_editor_delete', self):
|
||||||
return
|
return
|
||||||
del self.searches[self.current_search_name]
|
del self.searches[self.current_search_name]
|
||||||
self.searches_to_delete.append(self.current_search_name)
|
|
||||||
self.current_search_name = None
|
self.current_search_name = None
|
||||||
self.search_name_box.removeItem(self.search_name_box.currentIndex())
|
self.search_name_box.removeItem(self.search_name_box.currentIndex())
|
||||||
|
|
||||||
|
def rename_search(self):
|
||||||
|
new_search_name = unicode(self.input_box.text()).strip()
|
||||||
|
if new_search_name == '':
|
||||||
|
return False
|
||||||
|
if icu_lower(new_search_name) in self.search_names:
|
||||||
|
error_dialog(self, _('Saved search already exists'),
|
||||||
|
_('The saved search %s already exists, perhaps with '
|
||||||
|
'different case')%new_search_name).exec_()
|
||||||
|
return False
|
||||||
|
if self.current_search_name in self.searches:
|
||||||
|
self.searches[new_search_name] = self.searches[self.current_search_name]
|
||||||
|
del self.searches[self.current_search_name]
|
||||||
|
self.populate_search_list()
|
||||||
|
self.select_search(new_search_name)
|
||||||
|
return True
|
||||||
|
|
||||||
def select_search(self, name):
|
def select_search(self, name):
|
||||||
self.search_name_box.setCurrentIndex(self.search_name_box.findText(name))
|
self.search_name_box.setCurrentIndex(self.search_name_box.findText(name))
|
||||||
|
|
||||||
@ -78,7 +100,7 @@ class SavedSearchEditor(QDialog, Ui_SavedSearchEditor):
|
|||||||
def accept(self):
|
def accept(self):
|
||||||
if self.current_search_name:
|
if self.current_search_name:
|
||||||
self.searches[self.current_search_name] = unicode(self.search_text.toPlainText())
|
self.searches[self.current_search_name] = unicode(self.search_text.toPlainText())
|
||||||
for name in self.searches_to_delete:
|
for name in saved_searches().names():
|
||||||
saved_searches().delete(name)
|
saved_searches().delete(name)
|
||||||
for name in self.searches:
|
for name in self.searches:
|
||||||
saved_searches().add(name, self.searches[name])
|
saved_searches().add(name, self.searches[name])
|
||||||
|
@ -134,6 +134,20 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="6">
|
||||||
|
<widget class="QToolButton" name="rename_button">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Rename the current search to what is in the box</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset>
|
||||||
|
<normaloff>:/images/edit-undo.png</normaloff>:/images/edit-undo.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
|
@ -67,6 +67,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
if db.field_metadata[k]['is_category'] and
|
if db.field_metadata[k]['is_category'] and
|
||||||
db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration']])
|
db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration']])
|
||||||
choices -= set(['authors', 'publisher', 'formats', 'news', 'identifiers'])
|
choices -= set(['authors', 'publisher', 'formats', 'news', 'identifiers'])
|
||||||
|
choices |= set(['search'])
|
||||||
self.opt_categories_using_hierarchy.update_items_cache(choices)
|
self.opt_categories_using_hierarchy.update_items_cache(choices)
|
||||||
r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
|
r('categories_using_hierarchy', db.prefs, setting=CommaSeparatedList,
|
||||||
choices=sorted(list(choices), key=sort_key))
|
choices=sorted(list(choices), key=sort_key))
|
||||||
|
@ -533,7 +533,9 @@ class TagsView(QTreeView): # {{{
|
|||||||
self.setModel(self._model)
|
self.setModel(self._model)
|
||||||
except:
|
except:
|
||||||
# The DB must be gone. Set the model to None and hope that someone
|
# The DB must be gone. Set the model to None and hope that someone
|
||||||
# will call set_database later. I don't know if this in fact works
|
# will call set_database later. I don't know if this in fact works.
|
||||||
|
# But perhaps a Bad Thing Happened, so print the exception
|
||||||
|
traceback.print_exc()
|
||||||
self._model = None
|
self._model = None
|
||||||
self.setModel(None)
|
self.setModel(None)
|
||||||
# }}}
|
# }}}
|
||||||
@ -678,7 +680,8 @@ class TagTreeItem(object): # {{{
|
|||||||
break
|
break
|
||||||
elif self.tag.state == TAG_SEARCH_STATES['mark_plusplus'] or\
|
elif self.tag.state == TAG_SEARCH_STATES['mark_plusplus'] or\
|
||||||
self.tag.state == TAG_SEARCH_STATES['mark_minusminus']:
|
self.tag.state == TAG_SEARCH_STATES['mark_minusminus']:
|
||||||
if self.tag.is_hierarchical and len(self.children):
|
if self.tag.is_searchable and self.tag.is_hierarchical \
|
||||||
|
and len(self.children):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
@ -1258,19 +1261,22 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
if t.type != TagTreeItem.CATEGORY])
|
if t.type != TagTreeItem.CATEGORY])
|
||||||
if (comp,tag.category) in child_map:
|
if (comp,tag.category) in child_map:
|
||||||
node_parent = child_map[(comp,tag.category)]
|
node_parent = child_map[(comp,tag.category)]
|
||||||
node_parent.tag.is_hierarchical = True
|
node_parent.tag.is_hierarchical = key != 'search'
|
||||||
else:
|
else:
|
||||||
if i < len(components)-1:
|
if i < len(components)-1:
|
||||||
t = copy.copy(tag)
|
t = copy.copy(tag)
|
||||||
t.original_name = '.'.join(components[:i+1])
|
t.original_name = '.'.join(components[:i+1])
|
||||||
|
if key != 'search':
|
||||||
# This 'manufactured' intermediate node can
|
# This 'manufactured' intermediate node can
|
||||||
# be searched, but cannot be edited.
|
# be searched, but cannot be edited.
|
||||||
t.is_editable = False
|
t.is_editable = False
|
||||||
|
else:
|
||||||
|
t.is_searchable = t.is_editable = False
|
||||||
else:
|
else:
|
||||||
t = tag
|
t = tag
|
||||||
if not in_uc:
|
if not in_uc:
|
||||||
t.original_name = t.name
|
t.original_name = t.name
|
||||||
t.is_hierarchical = True
|
t.is_hierarchical = key != 'search'
|
||||||
t.name = comp
|
t.name = comp
|
||||||
self.beginInsertRows(category_index, 999999, 1)
|
self.beginInsertRows(category_index, 999999, 1)
|
||||||
node_parent = TagTreeItem(parent=node_parent, data=t,
|
node_parent = TagTreeItem(parent=node_parent, data=t,
|
||||||
|
@ -56,7 +56,7 @@ class Tag(object):
|
|||||||
self.is_hierarchical = False
|
self.is_hierarchical = False
|
||||||
self.is_editable = is_editable
|
self.is_editable = is_editable
|
||||||
self.is_searchable = is_searchable
|
self.is_searchable = is_searchable
|
||||||
self.id_set = id_set
|
self.id_set = id_set if id_set is not None else set([])
|
||||||
self.avg_rating = avg/2.0 if avg is not None else 0
|
self.avg_rating = avg/2.0 if avg is not None else 0
|
||||||
self.sort = sort
|
self.sort = sort
|
||||||
if self.avg_rating > 0:
|
if self.avg_rating > 0:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user