1) add in-place editing of author in tags view

2) editor and in-place editing of custom column
3) changed strings in tag_list_edit to be translatable
4) various cleanups
This commit is contained in:
Charles Haley 2010-06-03 15:31:29 +01:00
parent 8233bd3a89
commit f12b0ff54b
4 changed files with 80 additions and 43 deletions

View File

@ -1,11 +1,12 @@
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
from functools import partial
from PyQt4.QtCore import SIGNAL, Qt from PyQt4.QtCore import SIGNAL, Qt
from PyQt4.QtGui import QDialog, QListWidgetItem from PyQt4.QtGui import QDialog, QListWidgetItem
from calibre.gui2.dialogs.tag_list_editor_ui import Ui_TagListEditor from calibre.gui2.dialogs.tag_list_editor_ui import Ui_TagListEditor
from calibre.gui2 import question_dialog, error_dialog from calibre.gui2 import question_dialog, error_dialog
from calibre.ebooks.metadata import title_sort from calibre.ebooks.metadata import title_sort
class TagListEditor(QDialog, Ui_TagListEditor): class TagListEditor(QDialog, Ui_TagListEditor):
@ -29,6 +30,11 @@ class TagListEditor(QDialog, Ui_TagListEditor):
elif category == 'publisher': elif category == 'publisher':
result = db.get_publishers_with_ids() result = db.get_publishers_with_ids()
compare = (lambda x,y:cmp(x.lower(), y.lower())) compare = (lambda x,y:cmp(x.lower(), y.lower()))
else: # should be a custom field
self.cc_label = db.field_metadata[category]['label']
print 'here', self.cc_label
result = self.db.get_custom_items_with_ids(label=self.cc_label)
compare = (lambda x,y:cmp(x.lower(), y.lower()))
for k,v in result: for k,v in result:
self.all_tags[v] = k self.all_tags[v] = k
@ -101,6 +107,9 @@ class TagListEditor(QDialog, Ui_TagListEditor):
elif self.category == 'publisher': elif self.category == 'publisher':
rename_func = self.db.rename_publisher rename_func = self.db.rename_publisher
delete_func = self.db.delete_publisher_using_id delete_func = self.db.delete_publisher_using_id
else:
rename_func = partial(self.db.rename_custom_item, label=self.cc_label)
delete_func = partial(self.db.delete_custom_item_using_id, label=self.cc_label)
work_done = False work_done = False
if rename_func: if rename_func:

View File

@ -94,21 +94,16 @@ class TagsView(QTreeView): # {{{
if self._model.toggle(index, exclusive): if self._model.toggle(index, exclusive):
self.tags_marked.emit(self._model.tokens(), self.match_all) self.tags_marked.emit(self._model.tokens(), self.match_all)
def context_menu_handler(self, action=None, category=None, index=None): def context_menu_handler(self, action=None, category=None,
key=None, index=None):
if not action: if not action:
return return
try: try:
if action == 'edit_item': if action == 'edit_item':
self.edit(index) self.edit(index)
return return
if action == 'manage_tags': if action == 'open_editor':
self.tag_list_edit.emit(category, 'tags') self.tag_list_edit.emit(category, key)
return
if action == 'manage_series':
self.tag_list_edit.emit(category, 'series')
return
if action == 'manage_publishers':
self.tag_list_edit.emit(category, 'publisher')
return return
if action == 'manage_categories': if action == 'manage_categories':
self.user_category_edit.emit(category) self.user_category_edit.emit(category)
@ -139,10 +134,13 @@ class TagsView(QTreeView): # {{{
item = item.parent item = item.parent
if item.type == TagTreeItem.CATEGORY: if item.type == TagTreeItem.CATEGORY:
category = unicode(item.name.toString()) category = unicode(item.name.toString())
key = item.category_key
self.context_menu = QMenu(self) self.context_menu = QMenu(self)
# If the user right-clicked on a tag/series/publisher, then offer # If the user right-clicked on a tag/series/publisher, then offer
# the possibility of renaming that item # the possibility of renaming that item
if tag_name and item.category_key in ['authors', 'tags', 'series', 'publisher', 'search']: if tag_name and \
(key in ['authors', 'tags', 'series', 'publisher', 'search'] or \
self.db.field_metadata[key]['is_custom']):
self.context_menu.addAction(_('Rename item') + " '" + tag_name + "'", self.context_menu.addAction(_('Rename item') + " '" + tag_name + "'",
partial(self.context_menu_handler, action='edit_item', partial(self.context_menu_handler, action='edit_item',
category=tag_item, index=index)) category=tag_item, index=index))
@ -160,22 +158,15 @@ class TagsView(QTreeView): # {{{
# Offer specific editors for tags/series/publishers/saved searches # Offer specific editors for tags/series/publishers/saved searches
self.context_menu.addSeparator() self.context_menu.addSeparator()
if category == _('Tags'): if key in ['tags', 'publisher', 'series'] or \
self.context_menu.addAction(_('Manage Tags'), self.db.field_metadata[key]['is_custom']:
partial(self.context_menu_handler, action='manage_tags', self.context_menu.addAction(_('Manage ') + category,
category=tag_name)) partial(self.context_menu_handler, action='open_editor',
elif category == _('Searches'): category=tag_name, key=key))
elif key == 'search':
self.context_menu.addAction(_('Manage Saved Searches'), self.context_menu.addAction(_('Manage Saved Searches'),
partial(self.context_menu_handler, action='manage_searches', partial(self.context_menu_handler, action='manage_searches',
category=tag_name)) category=tag_name))
elif category == _('Publishers'):
self.context_menu.addAction(_('Manage Publishers'),
partial(self.context_menu_handler, action='manage_publishers',
category=tag_name))
elif category == _('Series'):
self.context_menu.addAction(_('Manage Series'),
partial(self.context_menu_handler, action='manage_series',
category=tag_name))
# Always show the user categories editor # Always show the user categories editor
self.context_menu.addSeparator() self.context_menu.addSeparator()
@ -441,27 +432,24 @@ class TagsModel(QAbstractItemModel): # {{{
error_dialog(self.tags_view, 'Duplicate item', error_dialog(self.tags_view, 'Duplicate item',
_('The name %s is already used.')%val).exec_() _('The name %s is already used.')%val).exec_()
return False return False
if key == 'series': if key == 'search':
self.db.rename_series(item.tag.id, val)
item.tag.name = val
self.tags_view.tag_item_renamed.emit()
elif key == 'publisher':
self.db.rename_publisher(item.tag.id, val)
item.tag.name = val
self.tags_view.tag_item_renamed.emit()
elif key == 'tags':
self.db.rename_tag(item.tag.id, val)
item.tag.name = val
self.tags_view.tag_item_renamed.emit()
elif key == 'search':
saved_searches.rename(unicode(item.data(role).toString()), val) saved_searches.rename(unicode(item.data(role).toString()), val)
item.tag.name = val
self.tags_view.search_item_renamed.emit() self.tags_view.search_item_renamed.emit()
elif key == 'authors': else:
self.db.rename_author(item.tag.id, val) if key == 'series':
item.tag.name = val self.db.rename_series(item.tag.id, val)
elif key == 'publisher':
self.db.rename_publisher(item.tag.id, val)
elif key == 'tags':
self.db.rename_tag(item.tag.id, val)
elif key == 'authors':
self.db.rename_author(item.tag.id, val)
elif self.db.field_metadata[key]['is_custom']:
self.db.rename_custom_item(item.tag.id, val,
label=self.db.field_metadata[key]['label'])
self.tags_view.tag_item_renamed.emit() self.tags_view.tag_item_renamed.emit()
self.dataChanged.emit(index, index) item.tag.name = val
self.refresh()
return True return True
def headerData(self, *args): def headerData(self, *args):

View File

@ -553,7 +553,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
self.tags_view.tag_list_edit.connect(self.do_tags_list_edit) self.tags_view.tag_list_edit.connect(self.do_tags_list_edit)
self.tags_view.user_category_edit.connect(self.do_user_categories_edit) self.tags_view.user_category_edit.connect(self.do_user_categories_edit)
self.tags_view.saved_search_edit.connect(self.do_saved_search_edit) self.tags_view.saved_search_edit.connect(self.do_saved_search_edit)
self.tags_view.tag_item_renamed.connect(self.library_view.model().refresh) self.tags_view.tag_item_renamed.connect(self.do_tag_item_renamed)
self.tags_view.search_item_renamed.connect(self.saved_search.clear_to_help) self.tags_view.search_item_renamed.connect(self.saved_search.clear_to_help)
self.search.search.connect(self.tags_view.model().reinit) self.search.search.connect(self.tags_view.model().reinit)
for x in (self.location_view.count_changed, self.tags_view.recount, for x in (self.location_view.count_changed, self.tags_view.recount,
@ -673,6 +673,12 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
self.saved_search.clear_to_help() self.saved_search.clear_to_help()
self.search.clear_to_help() self.search.clear_to_help()
def do_tag_item_renamed(self):
# Clean up library view and search
self.library_view.model().refresh()
self.saved_search.clear_to_help()
self.search.clear_to_help()
def do_saved_search_edit(self, search): def do_saved_search_edit(self, search):
d = SavedSearchEditor(self, search) d = SavedSearchEditor(self, search)
d.exec_() d.exec_()

View File

@ -171,6 +171,40 @@ class CustomColumns(object):
ans.sort(cmp=lambda x,y:cmp(x.lower(), y.lower())) ans.sort(cmp=lambda x,y:cmp(x.lower(), y.lower()))
return ans return ans
# convenience methods for tag editing
def get_custom_items_with_ids(self, label=None, num=None):
if label is not None:
data = self.custom_column_label_map[label]
if num is not None:
data = self.custom_column_num_map[num]
table, lt = self.custom_table_names(data['num'])
if not data['normalized']:
return []
ans = self.conn.get('SELECT id, value FROM %s'%table)
return ans
def rename_custom_item(self, id, new_name, label=None, num=None):
if id:
if label is not None:
data = self.custom_column_label_map[label]
if num is not None:
data = self.custom_column_num_map[num]
table, lt = self.custom_table_names(data['num'])
self.conn.execute('UPDATE %s SET value=? WHERE id=?'%table, (new_name, id))
self.conn.commit()
def delete_custom_item_using_id(self, id, label=None, num=None):
if id:
if label is not None:
data = self.custom_column_label_map[label]
if num is not None:
data = self.custom_column_num_map[num]
table, lt = self.custom_table_names(data['num'])
self.conn.execute('DELETE FROM %s WHERE value=?'%lt, (id,))
self.conn.execute('DELETE FROM %s WHERE id=?'%table, (id,))
self.conn.commit()
# end convenience methods
def all_custom(self, label=None, num=None): def all_custom(self, label=None, num=None):
if label is not None: if label is not None:
data = self.custom_column_label_map[label] data = self.custom_column_label_map[label]