so-gui/widgets/drag_tree_widget.py
baiobelfer 2017e7a4c5 init
2025-02-01 18:16:23 +01:00

151 lines
5.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
from PySide6.QtWidgets import (
QTreeWidget, QTreeWidgetItem,
QAbstractItemView, QApplication
)
from PySide6.QtCore import QPoint, Qt, QMimeData
from PySide6.QtGui import QDrag, QMouseEvent
class DragTreeWidget(QTreeWidget):
"""
Drzewo źródłowe (drag source). Umożliwia przeciąganie wybranych węzłów
w formacie JSON do DropTreeWidget.
"""
def __init__(self, parent=None):
super().__init__(parent)
self.setSelectionMode(QAbstractItemView.ExtendedSelection)
self.setDragEnabled(True)
# Edycja np. double-click lub kliknięcie wybranego
self.setEditTriggers(QAbstractItemView.DoubleClicked | QAbstractItemView.SelectedClicked)
self._drag_start_pos = QPoint()
self._drag_in_progress = False # Flaga kontroli przeciągania
def handle_item_click(self, item, column):
"""
Po kliknięciu w węzeł kopiuje do schowka JSON zawierający
ścieżkę (rodzice) od korzenia do tego węzła ale BEZ dzieci!
"""
chain_json = self.item_to_json_parents_no_children(item)
print("[LOG] Copied item + parents (NO children) to clipboard:")
print(chain_json)
from PySide6.QtWidgets import QApplication
QApplication.clipboard().setText(chain_json)
def item_to_json_parents_no_children(self, item: QTreeWidgetItem) -> str:
"""
Buduje strukturę JSON (jako string) dla pojedynczej ścieżki
'korzeń -> ... -> item', bez dzieci. Każdy węzeł ma 'children': [].
"""
import json
# Zacznij od zaznaczonego węzła
node_dict = self.item_to_dict_no_children(item)
# Idź w górę, owijając node_dict w kolejnych rodziców
current = item.parent()
while current is not None:
parent_dict = self.item_to_dict_no_children(current)
parent_dict["children"] = [node_dict]
node_dict = parent_dict
current = current.parent()
# Zamień na ładny, sformatowany JSON
return json.dumps(node_dict, ensure_ascii=False, indent=2)
def item_to_dict_no_children(self, item: QTreeWidgetItem) -> dict:
"""
Zwraca słownik z polami (punkty, obowiązkowe, nr, opis),
ale 'children' zawsze jest pustą listą.
"""
return {
"punkty": item.text(0),
"obowiązkowe": item.text(1),
"nr": item.text(2),
"opis": item.text(3),
"children": []
}
def mousePressEvent(self, event: QMouseEvent):
item = self.itemAt(event.position().toPoint())
if item:
# 1) Alt + LPM: kopiowanie do schowka (łańcuch bez dzieci)
if (event.button() == Qt.LeftButton) and (event.modifiers() & Qt.ShiftModifier):
chain_json = self.item_to_json_parents_no_children(item)
from PySide6.QtWidgets import QApplication
QApplication.clipboard().setText(chain_json)
return # Nie zaznaczaj już tego węzła
# 2) Shift + LPM: kopiowanie *tylko* opisu (kolumna 3) klikniętego węzła
if (event.button() == Qt.LeftButton) and (event.modifiers() & Qt.AltModifier):
from PySide6.QtWidgets import QApplication
opis = item.text(3).strip() # kolumna 3
QApplication.clipboard().setText(opis)
return # Nie zaznaczaj już tego węzła
# Poniższa logika pozostaje bez zmian (drag, normalne zaznaczenie itp.)
if event.button() == Qt.LeftButton:
self._drag_start_pos = event.position().toPoint()
self._drag_in_progress = False
super().mousePressEvent(event)
def mouseMoveEvent(self, event: QMouseEvent):
if event.buttons() & Qt.LeftButton:
dist = (event.position().toPoint() - self._drag_start_pos).manhattanLength()
if dist > QApplication.startDragDistance() and not self._drag_in_progress:
self._drag_in_progress = True
self.startDrag()
super().mouseMoveEvent(event)
def startDrag(self, supportedActions=Qt.MoveAction):
if self._drag_in_progress:
selected_items = self.selectedItems()
if not selected_items:
self._drag_in_progress = False
return
# Konwertujemy zaznaczone elementy na listę JSON (uwzględniamy hierarchię)
data_list = [self.item_to_dict_with_parents(item) for item in selected_items]
formatted_json = json.dumps(data_list, ensure_ascii=False, indent=4)
drag = QDrag(self)
mime = QMimeData()
mime.setText(formatted_json)
drag.setMimeData(mime)
result = drag.exec(Qt.CopyAction)
self._drag_in_progress = False
def item_to_dict_with_parents(self, item: QTreeWidgetItem) -> dict:
"""
Buduje pełną hierarchię rodziców i dzieci od wybranego elementu aż do korzenia.
"""
current_item = item
full_hierarchy = None
while current_item is not None:
node = self.item_to_dict_subtree(current_item)
if full_hierarchy is not None:
node["children"] = [full_hierarchy]
full_hierarchy = node
current_item = current_item.parent()
return full_hierarchy
def item_to_dict_subtree(self, item: QTreeWidgetItem) -> dict:
"""Rekurencyjnie przekształca węzeł i jego dzieci w słownik."""
node_data = {
"punkty": item.text(0).strip(),
"obowiązkowe": item.text(1).strip(),
"nr": item.text(2).strip(),
"opis": item.text(3).strip(),
"children": []
}
for i in range(item.childCount()):
child = item.child(i)
node_data["children"].append(self.item_to_dict_subtree(child))
return node_data