Reputation: 9863
So, let's consider this little snippet:
import sys
import random
import string
from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMenu, QAction, \
QTreeWidget, QTreeWidgetItem, QAbstractItemView
from PyQt5.QtGui import QCursor, QKeySequence
class PageTree(QTreeWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.alphabet = list(string.ascii_lowercase)
self.index = 0
self.header().hide()
self.view_menu = QMenu(self)
self.create_actions()
self.setDragEnabled(True)
self.setDragDropMode(QAbstractItemView.InternalMove)
self.setSelectionBehavior(QAbstractItemView.SelectRows)
def create_actions(self):
action = QtWidgets.QAction("Add new", self.view_menu)
action.triggered.connect(self.on_add_page)
action.setShortcuts(QKeySequence("a"))
self.view_menu.addAction(action)
self.addActions(self.view_menu.actions())
def add_page(self, name, parent=None):
if (parent is None and len(self.selectedItems()) == 1):
parent = self.selectedItems()[0]
item = QTreeWidgetItem(parent)
item.setText(0, name)
item.setFlags(item.flags() | Qt.ItemIsEditable)
self.addTopLevelItem(item)
if (parent):
parent.setExpanded(True)
return item
def on_add_page(self):
self.add_page("test_page_{0}".format(self.alphabet[self.index]), None)
self.index += 1
self.index %= len(self.alphabet)
def contextMenuEvent(self, ce):
super().contextMenuEvent(ce)
self.view_menu.exec(QCursor.pos())
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
tree_widget = PageTree()
tree_widget.resize(400, 600)
tree_widget.show()
sys.exit(app.exec_())
As you can see, the current code shows a simple QTreeWidget that allows you to reorder items using drag and drop builtin functionality thanks to setDragEnabled, setDragDropMode, setSelectionBehavior
function.
Here's the thing, I'd like to implement a behaviour where the drag and drop happened only when pressing a key (ie: ctrl). Otherwise I'd like the widget to behave normally and the items remaining static no matter if you're trying to drag items nor holding the mouse button while hovering items.
How could I implement this behaviour?
Upvotes: 4
Views: 613
Reputation: 120578
This is quite easy to implement by overriding startDrag
:
class PageTree(QTreeWidget):
...
def startDrag(self, actions):
if QtWidgets.qApp.keyboardModifiers() & Qt.MetaModifier:
super().startDrag(actions)
Note that I've used the Meta (Windows) key here, because the Ctrl and Shift modifiers affect various aspects of selection in combination with the mouse. (Also, on Linux, the Alt + drag combination is normally used to move windows around, so it may not be a good choice either). However, you might be able to work around this issue by choosing a different selection mode.
Upvotes: 3