mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Make drag & drop work again in the tag browser. Fix problem w/Qt near the end of the list.
This commit is contained in:
parent
ab16d1c0a8
commit
7dfa9897d9
@ -335,7 +335,6 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
node.is_gst = is_gst
|
||||
if not is_gst:
|
||||
node.tag.is_hierarchical = '5state'
|
||||
if not is_gst:
|
||||
tree_root[p] = {}
|
||||
tree_root = tree_root[p]
|
||||
else:
|
||||
@ -519,7 +518,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
# category display order is important here. The following works
|
||||
# only if all the non-user categories are displayed before the
|
||||
# user categories
|
||||
if category_is_hierarchical:
|
||||
if category_is_hierarchical or tag.is_hierarchical:
|
||||
components = get_name_components(tag.original_name)
|
||||
else:
|
||||
components = [tag.original_name]
|
||||
@ -581,6 +580,14 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
return [(t.tag.id, t.tag.original_name, t.tag.count)
|
||||
for t in cat.child_tags() if t.tag.count > 0]
|
||||
|
||||
def is_in_user_category(self, index):
|
||||
if not index.isValid():
|
||||
return False
|
||||
p = self.get_node(index)
|
||||
while p.type != TagTreeItem.CATEGORY:
|
||||
p = p.parent
|
||||
return p.tag.category.startswith('@')
|
||||
|
||||
# Drag'n Drop {{{
|
||||
def mimeTypes(self):
|
||||
return ["application/calibre+from_library",
|
||||
@ -646,13 +653,13 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
action is Qt.CopyAction or Qt.MoveAction
|
||||
'''
|
||||
def process_source_node(user_cats, src_parent, src_parent_is_gst,
|
||||
is_uc, dest_key, node):
|
||||
is_uc, dest_key, idx):
|
||||
'''
|
||||
Copy/move an item and all its children to the destination
|
||||
'''
|
||||
copied = False
|
||||
src_name = node.tag.original_name
|
||||
src_cat = node.tag.category
|
||||
src_name = idx.tag.original_name
|
||||
src_cat = idx.tag.category
|
||||
# delete the item if the source is a user category and action is move
|
||||
if is_uc and not src_parent_is_gst and src_parent in user_cats and \
|
||||
action == Qt.MoveAction:
|
||||
@ -675,7 +682,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
if add_it:
|
||||
user_cats[dest_key].append([src_name, src_cat, 0])
|
||||
|
||||
for c in node.children:
|
||||
for c in idx.children:
|
||||
copied = process_source_node(user_cats, src_parent, src_parent_is_gst,
|
||||
is_uc, dest_key, c)
|
||||
return copied
|
||||
@ -696,11 +703,11 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
if dest_key not in user_cats:
|
||||
continue
|
||||
|
||||
node = self.index_for_path(path)
|
||||
if node:
|
||||
idx = self.index_for_path(path)
|
||||
if idx.isValid():
|
||||
process_source_node(user_cats, src_parent, src_parent_is_gst,
|
||||
is_uc, dest_key,
|
||||
self.get_node(node))
|
||||
self.get_node(idx))
|
||||
|
||||
self.db.prefs.set('user_categories', user_cats)
|
||||
self.refresh_required.emit()
|
||||
@ -1139,6 +1146,8 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
return QModelIndex()
|
||||
|
||||
ans = self.createIndex(parent_item.row(), 0, parent_item)
|
||||
if not ans.isValid():
|
||||
return QModelIndex()
|
||||
return ans
|
||||
|
||||
def rowCount(self, parent):
|
||||
|
@ -12,7 +12,8 @@ from functools import partial
|
||||
from itertools import izip
|
||||
|
||||
from PyQt4.Qt import (QStyledItemDelegate, Qt, QTreeView, pyqtSignal, QSize,
|
||||
QIcon, QApplication, QMenu, QPoint, QModelIndex, QToolTip, QCursor)
|
||||
QIcon, QApplication, QMenu, QPoint, QModelIndex, QToolTip, QCursor,
|
||||
QDrag)
|
||||
|
||||
from calibre.gui2.tag_browser.model import (TagTreeItem, TAG_SEARCH_STATES,
|
||||
TagsModel)
|
||||
@ -101,6 +102,7 @@ class TagsView(QTreeView): # {{{
|
||||
self.setDragEnabled(True)
|
||||
self.setDragDropMode(self.DragDrop)
|
||||
self.setDropIndicatorShown(True)
|
||||
self.in_drag_drop = False
|
||||
self.setAutoExpandDelay(500)
|
||||
self.pane_is_visible = False
|
||||
self.search_icon = QIcon(I('search.png'))
|
||||
@ -232,10 +234,35 @@ class TagsView(QTreeView): # {{{
|
||||
s = s if s else None
|
||||
self._model.set_search_restriction(s)
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
dex = self.indexAt(event.pos())
|
||||
if self.in_drag_drop or not dex.isValid():
|
||||
QTreeView.mouseMoveEvent(self, event)
|
||||
return
|
||||
# Must deal with odd case where the node being dragged is 'virtual',
|
||||
# created to form a hierarchy. We can't really drag this node, but in
|
||||
# addition we can't allow drag recognition to notice going over some
|
||||
# other node and grabbing that one. So we set in_drag_drop to prevent
|
||||
# this from happening, turning it off when the user lifts the button.
|
||||
self.in_drag_drop = True
|
||||
if not self._model.flags(dex) & Qt.ItemIsDragEnabled:
|
||||
QTreeView.mouseMoveEvent(self, event)
|
||||
return
|
||||
md = self._model.mimeData([dex])
|
||||
pixmap = dex.data(Qt.DecorationRole).toPyObject().pixmap(25, 25)
|
||||
drag = QDrag(self)
|
||||
drag.setPixmap(pixmap)
|
||||
drag.setMimeData(md)
|
||||
if self._model.is_in_user_category(dex):
|
||||
drag.exec_(Qt.CopyAction|Qt.MoveAction, Qt.CopyAction)
|
||||
else:
|
||||
drag.exec_(Qt.CopyAction)
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
# Swallow everything except leftButton so context menus work correctly
|
||||
if event.button() == Qt.LeftButton:
|
||||
if event.button() == Qt.LeftButton or self.in_drag_drop:
|
||||
QTreeView.mouseReleaseEvent(self, event)
|
||||
self.in_drag_drop = False
|
||||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
# swallow these to avoid toggling and editing at the same time
|
||||
@ -639,12 +666,19 @@ class TagsView(QTreeView): # {{{
|
||||
self.show_item_at_index(self._model.index_for_path(path), box=box,
|
||||
position=position)
|
||||
|
||||
def expand_parent(self, idx, depth=0):
|
||||
p = self._model.parent(idx)
|
||||
d = 0
|
||||
if p.isValid():
|
||||
d = self.expand_parent(p, depth+1)
|
||||
if d == 0:
|
||||
self.expand(idx)
|
||||
return d+1
|
||||
|
||||
def show_item_at_index(self, idx, box=False,
|
||||
position=QTreeView.PositionAtCenter):
|
||||
if idx.isValid() and idx.data(Qt.UserRole).toPyObject() is not self._model.root_item:
|
||||
self.expand(self._model.parent(idx)) # Needed otherwise Qt sometimes segfaults if the
|
||||
# node is buried in a collapsed, off
|
||||
# screen hierarchy
|
||||
self.expand_parent(idx)
|
||||
self.setCurrentIndex(idx)
|
||||
self.scrollTo(idx, position)
|
||||
if box:
|
||||
|
Loading…
x
Reference in New Issue
Block a user