-
-
Notifications
You must be signed in to change notification settings - Fork 426
/
Copy pathdirectories_model.py
162 lines (134 loc) · 5.48 KB
/
directories_model.py
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# Created By: Virgil Dupras
# Created On: 2009-04-25
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.QtCore import pyqtSignal, Qt, QRect, QUrl, QModelIndex, QItemSelection
from PyQt5.QtWidgets import (
QComboBox,
QStyledItemDelegate,
QStyle,
QStyleOptionComboBox,
QStyleOptionViewItem,
QApplication,
)
from PyQt5.QtGui import QBrush
from hscommon.trans import trget
from qt.tree_model import RefNode, TreeModel
tr = trget("ui")
HEADERS = [tr("Name"), tr("State")]
STATES = [tr("Normal"), tr("Reference"), tr("Excluded")]
class DirectoriesDelegate(QStyledItemDelegate):
def createEditor(self, parent, option, index):
editor = QComboBox(parent)
editor.addItems(STATES)
return editor
def paint(self, painter, option, index):
self.initStyleOption(option, index)
# No idea why, but this cast is required if we want to have access to the V4 valuess
option = QStyleOptionViewItem(option)
if (index.column() == 1) and (option.state & QStyle.State_Selected):
cboption = QStyleOptionComboBox()
cboption.rect = option.rect
# On OS X (with Qt4.6.0), adding State_Enabled to the flags causes the whole drawing to
# fail (draw nothing), but it's an OS X only glitch. On Windows, it works alright.
cboption.state |= QStyle.State_Enabled
QApplication.style().drawComplexControl(QStyle.CC_ComboBox, cboption, painter)
painter.setBrush(option.palette.text())
rect = QRect(option.rect)
rect.setLeft(rect.left() + 4)
painter.drawText(rect, Qt.AlignLeft, option.text)
else:
super().paint(painter, option, index)
def setEditorData(self, editor, index):
value = index.model().data(index, Qt.EditRole)
editor.setCurrentIndex(value)
editor.showPopup()
def setModelData(self, editor, model, index):
value = editor.currentIndex()
model.setData(index, value, Qt.EditRole)
def updateEditorGeometry(self, editor, option, index):
editor.setGeometry(option.rect)
class DirectoriesModel(TreeModel):
MIME_TYPE_FORMAT = "text/uri-list"
def __init__(self, model, view, **kwargs):
super().__init__(**kwargs)
self.model = model
self.model.view = self
self.view = view
self.view.setModel(self)
self.view.selectionModel().selectionChanged[(QItemSelection, QItemSelection)].connect(self.selectionChanged)
def _create_node(self, ref, row):
return RefNode(self, None, ref, row)
def _get_children(self):
return list(self.model)
def columnCount(self, parent=QModelIndex()):
return 2
def data(self, index, role):
if not index.isValid():
return None
node = index.internalPointer()
ref = node.ref
if role == Qt.DisplayRole:
if index.column() == 0:
return ref.name
else:
return STATES[ref.state]
elif role == Qt.EditRole and index.column() == 1:
return ref.state
elif role == Qt.ForegroundRole:
state = ref.state
if state == 1:
return QBrush(Qt.blue)
elif state == 2:
return QBrush(Qt.red)
return None
def dropMimeData(self, mime_data, action, row, column, parent_index):
# the data in mimeData is urlencoded **in utf-8**
if not mime_data.hasFormat(self.MIME_TYPE_FORMAT):
return False
data = bytes(mime_data.data(self.MIME_TYPE_FORMAT)).decode("ascii")
urls = data.split("\r\n")
paths = [QUrl(url).toLocalFile() for url in urls if url]
for path in paths:
self.model.add_directory(path)
self.foldersAdded.emit(paths)
self.reset()
return True
def flags(self, index):
if not index.isValid():
return Qt.ItemIsEnabled | Qt.ItemIsDropEnabled
result = Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDropEnabled
if index.column() == 1:
result |= Qt.ItemIsEditable
return result
def headerData(self, section, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole and section < len(HEADERS):
return HEADERS[section]
return None
def mimeTypes(self):
return [self.MIME_TYPE_FORMAT]
def setData(self, index, value, role):
if not index.isValid() or role != Qt.EditRole or index.column() != 1:
return False
node = index.internalPointer()
ref = node.ref
ref.state = value
return True
def supportedDropActions(self):
# Normally, the correct action should be ActionLink, but the drop doesn't work. It doesn't
# work with ActionMove either. So screw that, and accept anything.
return Qt.ActionMask
# --- Events
def selectionChanged(self, selected, deselected):
new_nodes = [modelIndex.internalPointer().ref for modelIndex in self.view.selectionModel().selectedRows()]
self.model.selected_nodes = new_nodes
# --- Signals
foldersAdded = pyqtSignal(list)
# --- model --> view
def refresh(self):
self.reset()
def refresh_states(self):
self.refreshData()