mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Drag & drop onto user categories
This commit is contained in:
parent
576f71b7f4
commit
4bb388216a
@ -51,7 +51,7 @@ class TagCategories(QDialog, Ui_TagCategories):
|
|||||||
|
|
||||||
cc_map = self.db.custom_column_label_map
|
cc_map = self.db.custom_column_label_map
|
||||||
for cc in cc_map:
|
for cc in cc_map:
|
||||||
if cc_map[cc]['datatype'] == 'text':
|
if cc_map[cc]['datatype'] in ['text', 'series']:
|
||||||
self.category_labels.append(db.field_metadata.label_to_key(cc))
|
self.category_labels.append(db.field_metadata.label_to_key(cc))
|
||||||
category_icons.append(cc_icon)
|
category_icons.append(cc_icon)
|
||||||
category_values.append(lambda col=cc: self.db.all_custom(label=col))
|
category_values.append(lambda col=cc: self.db.all_custom(label=col))
|
||||||
|
@ -517,6 +517,8 @@ class BooksView(QTableView): # {{{
|
|||||||
|
|
||||||
md.setUrls([url_for_id(i) for i in selected])
|
md.setUrls([url_for_id(i) for i in selected])
|
||||||
drag = QDrag(self)
|
drag = QDrag(self)
|
||||||
|
col = self.selectionModel().currentIndex().column()
|
||||||
|
md.column_name = self.column_map[col]
|
||||||
drag.setMimeData(md)
|
drag.setMimeData(md)
|
||||||
cover = self.drag_icon(m.cover(self.currentIndex().row()),
|
cover = self.drag_icon(m.cover(self.currentIndex().row()),
|
||||||
len(selected) > 1)
|
len(selected) > 1)
|
||||||
|
@ -67,7 +67,7 @@ class TagsView(QTreeView): # {{{
|
|||||||
author_sort_edit = pyqtSignal(object, object)
|
author_sort_edit = pyqtSignal(object, object)
|
||||||
tag_item_renamed = pyqtSignal()
|
tag_item_renamed = pyqtSignal()
|
||||||
search_item_renamed = pyqtSignal()
|
search_item_renamed = pyqtSignal()
|
||||||
drag_drop_finished = pyqtSignal(object)
|
drag_drop_finished = pyqtSignal(object, object)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QTreeView.__init__(self, parent=None)
|
QTreeView.__init__(self, parent=None)
|
||||||
@ -252,6 +252,30 @@ class TagsView(QTreeView): # {{{
|
|||||||
self.context_menu.popup(self.mapToGlobal(point))
|
self.context_menu.popup(self.mapToGlobal(point))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def dragMoveEvent(self, event):
|
||||||
|
self.setDropIndicatorShown(False)
|
||||||
|
index = self.indexAt(event.pos())
|
||||||
|
if not index.isValid():
|
||||||
|
self.setDropIndicatorShown(False)
|
||||||
|
return
|
||||||
|
item = index.internalPointer()
|
||||||
|
flags = self._model.flags(index)
|
||||||
|
if item.type == TagTreeItem.TAG and flags & Qt.ItemIsDropEnabled:
|
||||||
|
self.setDropIndicatorShown(True)
|
||||||
|
else:
|
||||||
|
item = index.internalPointer()
|
||||||
|
if item.type == TagTreeItem.CATEGORY:
|
||||||
|
fm_dest = self.db.metadata_for_field(item.category_key)
|
||||||
|
if fm_dest['kind'] == 'user':
|
||||||
|
md = event.mimeData()
|
||||||
|
fm_src = self.db.metadata_for_field(md.column_name)
|
||||||
|
if md.column_name in ['authors', 'publisher', 'series'] or \
|
||||||
|
(fm_src['is_custom'] and
|
||||||
|
fm_src['datatype'] in ['series', 'text'] and
|
||||||
|
not fm_src['is_multiple']):
|
||||||
|
self.setDropIndicatorShown(True)
|
||||||
|
QTreeView.dragMoveEvent(self, event)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
if self.model():
|
if self.model():
|
||||||
self.model().clear_state()
|
self.model().clear_state()
|
||||||
@ -448,8 +472,59 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
ids = list(map(int, str(md.data(mime)).split()))
|
ids = list(map(int, str(md.data(mime)).split()))
|
||||||
self.handle_drop(node, ids)
|
self.handle_drop(node, ids)
|
||||||
return True
|
return True
|
||||||
|
elif node.type == TagTreeItem.CATEGORY:
|
||||||
|
fm_dest = self.db.metadata_for_field(node.category_key)
|
||||||
|
if fm_dest['kind'] == 'user':
|
||||||
|
fm_src = self.db.metadata_for_field(md.column_name)
|
||||||
|
if md.column_name in ['authors', 'publisher', 'series'] or \
|
||||||
|
(fm_src['is_custom'] and
|
||||||
|
fm_src['datatype'] in ['series', 'text'] and
|
||||||
|
not fm_src['is_multiple']):
|
||||||
|
mime = 'application/calibre+from_library'
|
||||||
|
ids = list(map(int, str(md.data(mime)).split()))
|
||||||
|
self.handle_user_category_drop(node, ids, md.column_name)
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def handle_user_category_drop(self, on_node, ids, column):
|
||||||
|
categories = self.db.prefs.get('user_categories', {})
|
||||||
|
category = categories.get(on_node.category_key[:-1], None)
|
||||||
|
if category is None:
|
||||||
|
return
|
||||||
|
fm_src = self.db.metadata_for_field(column)
|
||||||
|
for id in ids:
|
||||||
|
vmap = {}
|
||||||
|
label = fm_src['label']
|
||||||
|
if not fm_src['is_custom']:
|
||||||
|
if label == 'authors':
|
||||||
|
items = self.db.get_authors_with_ids()
|
||||||
|
items = [(i[0], i[1].replace('|', ',')) for i in items]
|
||||||
|
value = self.db.authors(id, index_is_id=True)
|
||||||
|
value = [v.replace('|', ',') for v in value.split(',')]
|
||||||
|
elif label == 'publisher':
|
||||||
|
items = self.db.get_publishers_with_ids()
|
||||||
|
value = self.db.publisher(id, index_is_id=True)
|
||||||
|
elif label == 'series':
|
||||||
|
items = self.db.get_series_with_ids()
|
||||||
|
value = self.db.series(id, index_is_id=True)
|
||||||
|
else:
|
||||||
|
items = self.db.get_custom_items_with_ids(label=label)
|
||||||
|
value = self.db.get_custom(id, label=label, index_is_id=True)
|
||||||
|
if value is None:
|
||||||
|
return
|
||||||
|
if not isinstance(value, list):
|
||||||
|
value = [value]
|
||||||
|
for v in items:
|
||||||
|
vmap[v[1]] = v[0]
|
||||||
|
for val in value:
|
||||||
|
for (v, c, id) in category:
|
||||||
|
if v == val and c == column:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
category.append([val, column, vmap[val]])
|
||||||
|
categories[on_node.category_key[:-1]] = category
|
||||||
|
self.db.prefs.set('user_categories', categories)
|
||||||
|
self.drag_drop_finished.emit(None, True)
|
||||||
|
|
||||||
def handle_drop(self, on_node, ids):
|
def handle_drop(self, on_node, ids):
|
||||||
#print 'Dropped ids:', ids, on_node.tag
|
#print 'Dropped ids:', ids, on_node.tag
|
||||||
@ -499,7 +574,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
self.db.set_metadata(id, mi, set_title=False,
|
self.db.set_metadata(id, mi, set_title=False,
|
||||||
set_authors=set_authors, commit=False)
|
set_authors=set_authors, commit=False)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
self.drag_drop_finished.emit(ids)
|
self.drag_drop_finished.emit(ids, False)
|
||||||
|
|
||||||
def set_search_restriction(self, s):
|
def set_search_restriction(self, s):
|
||||||
self.search_restriction = s
|
self.search_restriction = s
|
||||||
@ -641,6 +716,8 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
(fm['is_custom'] and \
|
(fm['is_custom'] and \
|
||||||
fm['datatype'] in ['text', 'rating', 'series']):
|
fm['datatype'] in ['text', 'rating', 'series']):
|
||||||
ans |= Qt.ItemIsDropEnabled
|
ans |= Qt.ItemIsDropEnabled
|
||||||
|
else:
|
||||||
|
ans |= Qt.ItemIsDropEnabled
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
def supportedDropActions(self):
|
def supportedDropActions(self):
|
||||||
@ -857,8 +934,11 @@ class TagBrowserMixin(object): # {{{
|
|||||||
self.library_view.model().refresh()
|
self.library_view.model().refresh()
|
||||||
self.tags_view.recount()
|
self.tags_view.recount()
|
||||||
|
|
||||||
def drag_drop_finished(self, ids):
|
def drag_drop_finished(self, ids, is_category):
|
||||||
self.library_view.model().refresh_ids(ids)
|
if is_category:
|
||||||
|
self.tags_view.recount()
|
||||||
|
else:
|
||||||
|
self.library_view.model().refresh_ids(ids)
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user