| 62 | |
| 63 | |
| 64 | class DragDropListView(QtWidgets.QListView): |
| 65 | def __init__(self, parent=None): |
| 66 | super().__init__(parent) |
| 67 | self.parent = parent |
| 68 | self.setAcceptDrops(True) |
| 69 | self.setDropIndicatorShown(True) |
| 70 | self.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove) |
| 71 | self.model = QStandardItemModel(self) |
| 72 | self.setModel(self.model) |
| 73 | self._default_style = self.styleSheet() |
| 74 | |
| 75 | @property |
| 76 | def items(self): |
| 77 | for i in range(self.model.rowCount()): |
| 78 | yield self.model.item(i) |
| 79 | |
| 80 | @property |
| 81 | def state(self): |
| 82 | tests = [item.checkState() == QtCore.Qt.Checked for item in self.items] |
| 83 | n_checked = sum(tests) |
| 84 | if all(tests): |
| 85 | state = QtCore.Qt.Checked |
| 86 | elif any(tests): |
| 87 | state = QtCore.Qt.PartiallyChecked |
| 88 | else: |
| 89 | state = QtCore.Qt.Unchecked |
| 90 | return state, n_checked |
| 91 | |
| 92 | def add_item(self, path): |
| 93 | item = QStandardItem(path) |
| 94 | item.setCheckable(True) |
| 95 | item.setCheckState(QtCore.Qt.Checked) |
| 96 | self.model.appendRow(item) |
| 97 | |
| 98 | def clear(self): |
| 99 | self.model.removeRows(0, self.model.rowCount()) |
| 100 | |
| 101 | def dragEnterEvent(self, event): |
| 102 | if event.mimeData().hasUrls(): |
| 103 | event.accept() |
| 104 | else: |
| 105 | event.ignore() |
| 106 | |
| 107 | def dropEvent(self, event): |
| 108 | for url in event.mimeData().urls(): |
| 109 | path = url.toLocalFile() |
| 110 | if os.path.isfile(path): |
| 111 | self.add_item(path) |
| 112 | elif os.path.isdir(path): |
| 113 | for root, _, files in os.walk(path): |
| 114 | for file in files: |
| 115 | if not file.startswith("."): |
| 116 | self.add_item(os.path.join(root, file)) |
| 117 | |
| 118 | |
| 119 | class ItemSelectionFrame(QtWidgets.QFrame): |