BPL
BPL

Reputation: 9863

QTreeWidget drag and drop only when pressing key

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

Answers (1)

ekhumoro
ekhumoro

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

Related Questions