diff --git a/src/calibre/gui2/tag_view.py b/src/calibre/gui2/tag_view.py index 91b07c4d7e..07f8f92114 100644 --- a/src/calibre/gui2/tag_view.py +++ b/src/calibre/gui2/tag_view.py @@ -66,6 +66,7 @@ class TagsView(QTreeView): # {{{ author_sort_edit = pyqtSignal(object, object) tag_item_renamed = pyqtSignal() search_item_renamed = pyqtSignal() + drag_drop_finished = pyqtSignal(object) def __init__(self, parent=None): QTreeView.__init__(self, parent=None) @@ -121,10 +122,12 @@ class TagsView(QTreeView): # {{{ p = m.parent(idx) if idx.isValid() and p.isValid(): item = m.data(p, Qt.UserRole) - if item.type == TagTreeItem.CATEGORY and \ - item.category_key in \ - ('tags', 'series', 'authors', 'rating', 'publisher'): - allowed = True + fm = self.db.metadata_for_field(item.category_key) + if item.category_key in \ + ('tags', 'series', 'authors', 'rating', 'publisher') or\ + (fm['is_custom'] and \ + (fm['datatype'] == 'text' or fm['datatype'] == 'rating')): + allowed = True if allowed: event.acceptProposedAction() else: @@ -136,18 +139,54 @@ class TagsView(QTreeView): # {{{ p = m.parent(idx) if idx.isValid() and p.isValid(): item = m.data(p, Qt.UserRole) - if item.type == TagTreeItem.CATEGORY and \ - item.category_key in \ - ('tags', 'series', 'authors', 'rating', 'publisher'): - child = m.data(idx, Qt.UserRole) - md = event.mimeData() - mime = 'application/calibre+from_library' - ids = list(map(int, str(md.data(mime)).split())) - self.handle_drop(item, child, ids) - event.accept() + if item.type == TagTreeItem.CATEGORY: + fm = self.db.metadata_for_field(item.category_key) + if item.category_key in \ + ('tags', 'series', 'authors', 'rating', 'publisher') or\ + (fm['is_custom'] and \ + (fm['datatype'] == 'text' or fm['datatype'] == 'rating')): + child = m.data(idx, Qt.UserRole) + md = event.mimeData() + mime = 'application/calibre+from_library' + ids = list(map(int, str(md.data(mime)).split())) + self.handle_drop(item, child, ids) + event.accept() def handle_drop(self, parent, child, ids): - print 'Dropped ids:', ids + # print 'Dropped ids:', ids, parent.category_key, child.tag.name + key = parent.category_key + fm = self.db.metadata_for_field(key) + is_multiple = fm['is_multiple'] + val = child.tag.name + for id in ids: + mi = self.db.get_metadata(id, index_is_id=True) + + # Prepare to ignore the author, unless it is changed. Title is + # always ignored -- see the call to set_metadata + set_authors = False + + # Author_sort cannot change explicitly. Changing the author might + # change it. + mi.author_sort = None # Never will change by itself. + + if key == 'authors': + mi.authors = [val] + set_authors=True + elif fm['datatype'] == 'rating': + mi.set(key, len(val) * 2) + elif is_multiple: + new_val = mi.get(key, []) + if val in new_val: + # Fortunately, only one field can change, so the continue + # won't break anything + continue + new_val.append(val) + mi.set(key, new_val) + else: + mi.set(key, val) + self.db.set_metadata(id, mi, set_title=False, + set_authors=set_authors) + self.drag_drop_finished.emit(ids) @property def match_all(self): @@ -729,6 +768,7 @@ class TagBrowserMixin(object): # {{{ self.tags_view.author_sort_edit.connect(self.do_author_sort_edit) self.tags_view.tag_item_renamed.connect(self.do_tag_item_renamed) self.tags_view.search_item_renamed.connect(self.saved_searches_changed) + self.tags_view.drag_drop_finished.connect(self.drag_drop_finished) self.edit_categories.clicked.connect(lambda x: self.do_user_categories_edit()) @@ -810,6 +850,9 @@ class TagBrowserMixin(object): # {{{ self.library_view.model().refresh() self.tags_view.recount() + def drag_drop_finished(self, ids): + self.library_view.model().refresh_ids(ids) + # }}} class TagBrowserWidget(QWidget): # {{{ diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 529fd3fdc4..068f249f2a 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -1247,7 +1247,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): self.set_path(id, True) self.notify('metadata', [id]) - def set_metadata(self, id, mi, ignore_errors=False): + def set_metadata(self, id, mi, ignore_errors=False, + set_title=True, set_authors=True): ''' Set metadata for the book `id` from the `Metadata` object `mi` ''' @@ -1259,14 +1260,15 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): traceback.print_exc() else: raise - if mi.title: + if set_title and mi.title: self.set_title(id, mi.title, commit=False) - if not mi.authors: - mi.authors = [_('Unknown')] - authors = [] - for a in mi.authors: - authors += string_to_authors(a) - self.set_authors(id, authors, notify=False, commit=False) + if set_authors: + if not mi.authors: + mi.authors = [_('Unknown')] + authors = [] + for a in mi.authors: + authors += string_to_authors(a) + self.set_authors(id, authors, notify=False, commit=False) if mi.author_sort: doit(self.set_author_sort, id, mi.author_sort, notify=False, commit=False)