mirror of
git://github.com/kovidgoyal/calibre.git
synced 2026-05-06 00:03:46 +02:00
1) add possibility to rename a user category in manage categories
2) reinitialize the search_query_parser when the user categories change 3) add code to db2 to rename user categories that differ in case only 4) fix up manage categories somewhat
This commit is contained in:
parent
7bec9e51af
commit
6e1e2fbd75
5 changed files with 211 additions and 158 deletions
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
from functools import partial
|
||||
|
||||
from PyQt4.QtCore import SIGNAL, Qt
|
||||
from PyQt4.QtGui import QDialog, QIcon, QListWidgetItem
|
||||
|
||||
from calibre.gui2.dialogs.tag_categories_ui import Ui_TagCategories
|
||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||
from calibre.gui2 import error_dialog
|
||||
from calibre.constants import islinux
|
||||
from calibre.utils.icu import sort_key, strcmp
|
||||
|
||||
|
|
@ -102,12 +104,13 @@ def __init__(self, window, db, on_category=None):
|
|||
self.category_filter_box.addItem(v)
|
||||
self.current_cat_name = None
|
||||
|
||||
self.connect(self.apply_button, SIGNAL('clicked()'), self.apply_tags)
|
||||
self.connect(self.unapply_button, SIGNAL('clicked()'), self.unapply_tags)
|
||||
self.connect(self.add_category_button, SIGNAL('clicked()'), self.add_category)
|
||||
self.connect(self.category_box, SIGNAL('currentIndexChanged(int)'), self.select_category)
|
||||
self.connect(self.category_filter_box, SIGNAL('currentIndexChanged(int)'), self.display_filtered_categories)
|
||||
self.connect(self.delete_category_button, SIGNAL('clicked()'), self.del_category)
|
||||
self.apply_button.clicked.connect(partial(self.apply_tags, node=None))
|
||||
self.unapply_button.clicked.connect(partial(self.unapply_tags, node=None))
|
||||
self.add_category_button.clicked.connect(self.add_category)
|
||||
self.rename_category_button.clicked.connect(self.rename_category)
|
||||
self.category_box.currentIndexChanged[int].connect(self.select_category)
|
||||
self.category_filter_box.currentIndexChanged[int].connect(self.display_filtered_categories)
|
||||
self.delete_category_button.clicked.connect(self.del_category)
|
||||
if islinux:
|
||||
self.available_items_box.itemDoubleClicked.connect(self.apply_tags)
|
||||
else:
|
||||
|
|
@ -119,6 +122,9 @@ def __init__(self, window, db, on_category=None):
|
|||
l = self.category_box.findText(on_category)
|
||||
if l >= 0:
|
||||
self.category_box.setCurrentIndex(l)
|
||||
if self.current_cat_name is None:
|
||||
self.category_box.setCurrentIndex(0)
|
||||
self.select_category(0)
|
||||
|
||||
def make_list_widget(self, item):
|
||||
n = item.name if item.exists else item.name + _(' (not on any book)')
|
||||
|
|
@ -162,7 +168,9 @@ def add_category(self):
|
|||
return False
|
||||
for c in self.categories:
|
||||
if strcmp(c, cat_name) == 0:
|
||||
cat_name = c
|
||||
error_dialog(self, _('Name already used'),
|
||||
_('That name is already used, perhaps with different case.')).exec_()
|
||||
return False
|
||||
if cat_name not in self.categories:
|
||||
self.category_box.clear()
|
||||
self.current_cat_name = cat_name
|
||||
|
|
@ -173,6 +181,27 @@ def add_category(self):
|
|||
self.category_box.setCurrentIndex(self.category_box.findText(cat_name))
|
||||
return True
|
||||
|
||||
def rename_category(self):
|
||||
self.save_category()
|
||||
cat_name = unicode(self.input_box.text()).strip()
|
||||
if cat_name == '':
|
||||
return False
|
||||
if not self.current_cat_name:
|
||||
return False
|
||||
for c in self.categories:
|
||||
if strcmp(c, cat_name) == 0:
|
||||
error_dialog(self, _('Name already used'),
|
||||
_('That name is already used, perhaps with different case.')).exec_()
|
||||
return False
|
||||
# The order below is important because of signals
|
||||
self.categories[cat_name] = self.categories[self.current_cat_name]
|
||||
del self.categories[self.current_cat_name]
|
||||
self.current_cat_name = None
|
||||
self.populate_category_list()
|
||||
self.input_box.clear()
|
||||
self.category_box.setCurrentIndex(self.category_box.findText(cat_name))
|
||||
return True
|
||||
|
||||
def del_category(self):
|
||||
if self.current_cat_name is not None:
|
||||
if not confirm('<p>'+_('The current tag category will be '
|
||||
|
|
@ -209,5 +238,7 @@ def save_category(self):
|
|||
self.categories[self.current_cat_name] = l
|
||||
|
||||
def populate_category_list(self):
|
||||
for n in sorted(self.categories.keys(), key=sort_key):
|
||||
self.category_box.addItem(n)
|
||||
self.category_box.blockSignals(True)
|
||||
self.category_box.clear()
|
||||
self.category_box.addItems(sorted(self.categories.keys(), key=sort_key))
|
||||
self.category_box.blockSignals(False)
|
||||
|
|
@ -18,7 +18,139 @@
|
|||
<normaloff>:/images/chapters.png</normaloff>:/images/chapters.png</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Category name: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>category_box</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="category_box">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>160</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>145</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select a category to edit</string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QToolButton" name="delete_category_button">
|
||||
<property name="toolTip">
|
||||
<string>Delete this selected tag category</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/images/minus.png</normaloff>:/images/minus.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="input_box">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>60</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Enter a category name, then use the add button or the rename button</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="add_category_button">
|
||||
<property name="toolTip">
|
||||
<string>Add a new category</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/images/plus.png</normaloff>:/images/plus.png
|
||||
</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QToolButton" name="rename_category_button">
|
||||
<property name="toolTip">
|
||||
<string>Rename the current category to the 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>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Category filter: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="category_filter_box">
|
||||
<property name="toolTip">
|
||||
<string>Select the content kind of the new category</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
|
|
@ -66,7 +198,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<spacer>
|
||||
|
|
@ -110,7 +242,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<item row="2" column="2">
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
|
|
@ -151,7 +283,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<item row="2" column="3">
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<spacer>
|
||||
|
|
@ -195,7 +327,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="4">
|
||||
<item row="4" column="0" colspan="4">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
|
@ -208,141 +340,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="4">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Category name: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>category_box</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="category_box">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>160</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>145</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select a category to edit</string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QToolButton" name="delete_category_button">
|
||||
<property name="toolTip">
|
||||
<string>Delete this selected tag category</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/images/minus.png</normaloff>:/images/minus.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QLineEdit" name="input_box">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>60</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Enter a new category name. Select the kind before adding it.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QToolButton" name="add_category_button">
|
||||
<property name="toolTip">
|
||||
<string>Add the new category</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/images/plus.png</normaloff>:/images/plus.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Category filter: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="category_filter_box">
|
||||
<property name="toolTip">
|
||||
<string>Select the content kind of the new category</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
|
|
|
|||
|
|
@ -576,10 +576,7 @@ def __init__(self, db, parent, hidden_categories=None,
|
|||
for i, r in enumerate(self.row_map):
|
||||
if self.hidden_categories and self.categories[i] in self.hidden_categories:
|
||||
continue
|
||||
if self.db.field_metadata[r]['kind'] != 'user':
|
||||
tt = _('The lookup/search name is "{0}"').format(r)
|
||||
else:
|
||||
tt = ''
|
||||
tt = _(u'The lookup/search name is "{0}"').format(r)
|
||||
TagTreeItem(parent=self.root_item,
|
||||
data=self.categories[i],
|
||||
category_icon=self.category_icon_map[r],
|
||||
|
|
@ -1192,12 +1189,9 @@ def do_user_categories_edit(self, on_category=None):
|
|||
d.exec_()
|
||||
if d.result() == d.Accepted:
|
||||
db.prefs.set('user_categories', d.categories)
|
||||
st = db.field_metadata.get_search_terms()
|
||||
db.field_metadata.remove_user_categories()
|
||||
for k in d.categories:
|
||||
key = '@' + k
|
||||
if key in st:
|
||||
continue
|
||||
db.field_metadata.add_user_category(key, k)
|
||||
db.field_metadata.add_user_category('@' + k, k)
|
||||
db.data.sqp_initialize(db.field_metadata.get_search_terms(),
|
||||
optimize=True)
|
||||
self.tags_view.set_new_model()
|
||||
|
|
|
|||
|
|
@ -186,6 +186,29 @@ def migrate_preference(key, default):
|
|||
migrate_preference('saved_searches', {})
|
||||
set_saved_searches(self, 'saved_searches')
|
||||
|
||||
# Rename any user categories with names that differ only in case
|
||||
user_cats = self.prefs.get('user_categories', [])
|
||||
catmap = {}
|
||||
for uc in user_cats:
|
||||
ucl = icu_lower(uc)
|
||||
if ucl not in catmap:
|
||||
catmap[ucl] = []
|
||||
catmap[ucl].append(uc)
|
||||
cats_changed = False
|
||||
for uc in catmap:
|
||||
if len(catmap[uc]) > 1:
|
||||
prints('found user category case overlap', catmap[uc])
|
||||
cat = catmap[uc][0]
|
||||
suffix = 1
|
||||
while icu_lower((cat + unicode(suffix))) in catmap:
|
||||
suffix += 1
|
||||
prints('Renaming user category %s to %s'%(cat, cat+unicode(suffix)))
|
||||
user_cats[cat + unicode(suffix)] = user_cats[cat]
|
||||
del user_cats[cat]
|
||||
cats_changed = True
|
||||
if cats_changed:
|
||||
self.prefs.set('user_categories', user_cats)
|
||||
|
||||
load_user_template_functions(self.prefs.get('user_template_functions', []))
|
||||
|
||||
self.conn.executescript('''
|
||||
|
|
|
|||
|
|
@ -479,6 +479,15 @@ def remove_dynamic_categories(self):
|
|||
del self._search_term_map[k]
|
||||
del self._tb_cats[key]
|
||||
|
||||
def remove_user_categories(self):
|
||||
for key in list(self._tb_cats.keys()):
|
||||
val = self._tb_cats[key]
|
||||
if val['is_category'] and val['kind'] == 'user':
|
||||
for k in self._tb_cats[key]['search_terms']:
|
||||
if k in self._search_term_map:
|
||||
del self._search_term_map[k]
|
||||
del self._tb_cats[key]
|
||||
|
||||
def cc_series_index_column_for(self, key):
|
||||
return self._tb_cats[key]['rec_index'] + 1
|
||||
|
||||
|
|
@ -526,7 +535,6 @@ def _add_search_terms_to_map(self, key, terms):
|
|||
if terms is not None:
|
||||
for t in terms:
|
||||
if t in self._search_term_map:
|
||||
print self._search_term_map
|
||||
raise ValueError('Attempt to add duplicate search term "%s"'%t)
|
||||
self._search_term_map[t] = key
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue