aboutsummaryrefslogtreecommitdiffstats
path: root/examples/widgets/draganddrop/draggabletext/draggabletext.py
blob: 6ffdbd70eb0a5880b0af0bc15a09e4476e09c81a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# Copyright (C) 2013 Riverbank Computing Limited.
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

"""PySide6 port of the widgets/draganddrop/draggabletext example from Qt v5.x,
   originating from PyQt"""

from PySide6.QtCore import QFile, QIODevice, QMimeData, QPoint, Qt, QTextStream
from PySide6.QtGui import QDrag, QPalette, QPixmap
from PySide6.QtWidgets import QApplication, QFrame, QLabel, QWidget

import draggabletext_rc  # noqa: F401


class DragLabel(QLabel):
    def __init__(self, text, parent):
        super().__init__(text, parent)

        self.setAutoFillBackground(True)
        self.setFrameShape(QFrame.Panel)
        self.setFrameShadow(QFrame.Raised)

    def mousePressEvent(self, event):
        hot_spot = event.position().toPoint()

        mime_data = QMimeData()
        mime_data.setText(self.text())
        hx = hot_spot.x()
        hy = hot_spot.y()
        mime_data.setData('application/x-hotspot', f'{hx} {hy}'.encode('utf-8'))

        pixmap = QPixmap(self.size())
        self.render(pixmap)

        drag = QDrag(self)
        drag.setMimeData(mime_data)
        drag.setPixmap(pixmap)
        drag.setHotSpot(hot_spot)

        drop_action = drag.exec(Qt.CopyAction | Qt.MoveAction, Qt.CopyAction)

        if drop_action == Qt.MoveAction:
            self.close()
            self.update()


class DragWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        dictionary_file = QFile(':/dictionary/words.txt')
        dictionary_file.open(QIODevice.ReadOnly)

        x = 5
        y = 5

        for word in QTextStream(dictionary_file).readAll().split():
            word_label = DragLabel(word, self)
            word_label.move(x, y)
            word_label.show()
            x += word_label.width() + 2
            if x >= 195:
                x = 5
                y += word_label.height() + 2

        new_palette = self.palette()
        new_palette.setColor(QPalette.Window, Qt.white)
        self.setPalette(new_palette)

        self.setAcceptDrops(True)
        self.setMinimumSize(400, max(200, y))
        self.setWindowTitle("Draggable Text")

    def dragEnterEvent(self, event):
        if event.mimeData().hasText():
            if event.source() in self.children():
                event.setDropAction(Qt.MoveAction)
                event.accept()
            else:
                event.acceptProposedAction()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasText():
            mime = event.mimeData()
            pieces = mime.text().split()
            position = event.position().toPoint()
            hot_spot = QPoint()

            hot_spot_pos = mime.data('application/x-hotspot').split(' ')
            if len(hot_spot_pos) == 2:
                hot_spot.setX(hot_spot_pos[0].toInt()[0])
                hot_spot.setY(hot_spot_pos[1].toInt()[0])

            for piece in pieces:
                new_label = DragLabel(piece, self)
                new_label.move(position - hot_spot)
                new_label.show()

                position += QPoint(new_label.width(), 0)

            if event.source() in self.children():
                event.setDropAction(Qt.MoveAction)
                event.accept()
            else:
                event.acceptProposedAction()
        else:
            event.ignore()


if __name__ == '__main__':

    import sys

    app = QApplication(sys.argv)
    window = DragWidget()
    window.show()
    sys.exit(app.exec())