1from PyQt5.QtCore import Qt, QEvent, pyqtSignal, pyqtSlot
2from PyQt5.QtGui import QDragEnterEvent, QContextMenuEvent, QIcon, QDropEvent
3from PyQt5.QtWidgets import QListWidget, QMenu
4
5from urh import settings
6
7
8class ListWidget(QListWidget):
9    internalMove = pyqtSignal()
10    deleteElement = pyqtSignal()
11
12    def __init__(self, parent=None):
13        super().__init__(parent)
14        self.installEventFilter(self)
15        self.active_element = 0
16        self.active_element_text = ""
17        self.context_menu_pos = None
18
19    def dropEvent(self, event: QDropEvent):
20        super().dropEvent(event)
21        if self.count() > 0:
22            item = self.itemAt(event.pos())
23            if item is not None:
24                index = self.indexFromItem(item).row()
25                self.setCurrentRow(index)
26            else:
27                self.setCurrentRow(self.count()-1)
28
29    def dragEnterEvent(self, event: QDragEnterEvent):
30        self.active_element = self.indexAt(event.pos()).row()
31        event.accept()
32        super().dragEnterEvent(event)
33
34    def eventFilter(self, sender, event):
35        if event.type() == QEvent.ChildRemoved:
36            self.internalMove.emit()
37        elif event.type() == QEvent.KeyPress and event.key() in (Qt.Key_Delete, Qt.Key_Backspace)\
38                and self.currentItem() is not None:
39            item = self.currentRow()
40            item_name = self.currentItem().text()
41            self.active_element_text = item_name
42            self.takeItem(item)
43            self.deleteElement.emit()
44        return False
45
46    def create_context_menu(self):
47        menu = QMenu()
48        item = self.indexAt(self.context_menu_pos).row()
49        if item < 0:
50            return menu
51
52        item_name = self.item(item).text()
53
54        # Menu Entries
55        rm_action = menu.addAction(self.tr("Delete"))
56        rm_action.setIcon(QIcon.fromTheme("list-remove"))
57        rm_action.triggered.connect(self.on_rm_action_triggered)
58        if settings.DECODING_DISABLED_PREFIX in item_name:
59            disable_function = menu.addAction(self.tr("Enable"))
60        else:
61            disable_function = menu.addAction(self.tr("Disable"))
62
63        disable_function.triggered.connect(self.on_disable_function_triggered)
64
65        menu.addSeparator()
66        clear_all_action = menu.addAction(self.tr("Clear All"))
67        clear_all_action.triggered.connect(self.on_clear_all_action_triggered)
68        return menu
69
70    def contextMenuEvent(self, event: QContextMenuEvent):
71        self.context_menu_pos = event.pos()
72        menu = self.create_context_menu()
73        menu.exec_(self.mapToGlobal(event.pos()))
74        self.context_menu_pos = None
75
76    @pyqtSlot()
77    def on_rm_action_triggered(self):
78        item = self.indexAt(self.context_menu_pos).row()
79        item_name = self.item(item).text()
80        self.active_element_text = item_name
81        self.takeItem(item)
82        self.deleteElement.emit()
83
84    @pyqtSlot()
85    def on_disable_function_triggered(self):
86        item = self.indexAt(self.context_menu_pos).row()
87        item_name = self.item(item).text()
88        if settings.DECODING_DISABLED_PREFIX in item_name:
89            item_name = item_name[len(settings.DECODING_DISABLED_PREFIX):]
90        else:
91            item_name = settings.DECODING_DISABLED_PREFIX + item_name
92        self.takeItem(item)
93        self.insertItem(item, item_name)
94        self.internalMove.emit()
95
96    @pyqtSlot()
97    def on_clear_all_action_triggered(self):
98        while self.count() > 0:
99            self.takeItem(0)
100        self.deleteElement.emit()
101