Changeset View
Changeset View
Standalone View
Standalone View
applets/clipboard/contents/ui/ClipboardItemDelegate.qml
Show All 21 Lines | |||||
22 | import QtGraphicalEffects 1.0 | 22 | import QtGraphicalEffects 1.0 | ||
23 | 23 | | |||
24 | import org.kde.plasma.components 2.0 as PlasmaComponents | 24 | import org.kde.plasma.components 2.0 as PlasmaComponents | ||
25 | import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons | 25 | import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons | ||
26 | 26 | | |||
27 | PlasmaComponents.ListItem { | 27 | PlasmaComponents.ListItem { | ||
28 | id: menuItem | 28 | id: menuItem | ||
29 | 29 | | |||
30 | property alias supportsBarcodes: barcodeToolButton.visible | 30 | property bool supportsBarcodes | ||
31 | property int maximumNumberOfPreviews: Math.floor(width / (units.gridUnit * 4 + units.smallSpacing)) | 31 | property int maximumNumberOfPreviews: Math.floor(width / (units.gridUnit * 4 + units.smallSpacing)) | ||
32 | readonly property real gradientThreshold: (label.width - toolButtonsLayout.width) / label.width | 32 | readonly property real gradientThreshold: (label.width - toolButtonsLoader.width) / label.width | ||
33 | 33 | | |||
34 | signal itemSelected(string uuid) | 34 | signal itemSelected(string uuid) | ||
35 | signal remove(string uuid) | 35 | signal remove(string uuid) | ||
36 | signal edit(string uuid) | 36 | signal edit(string uuid) | ||
37 | signal barcode(string uuid) | 37 | signal barcode(string uuid) | ||
38 | signal action(string uuid) | 38 | signal action(string uuid) | ||
39 | 39 | | |||
40 | height: Math.max(label.height, toolButtonsLayout.implicitHeight) + 2 * units.smallSpacing | 40 | // the 1.6 comes from ToolButton's default height | ||
41 | height: Math.max(label.height, Math.round(units.gridUnit * 1.6)) + 2 * units.smallSpacing | ||||
41 | 42 | | |||
42 | enabled: true | 43 | enabled: true | ||
43 | 44 | | |||
44 | onClicked: { | 45 | onClicked: { | ||
45 | menuItem.itemSelected(UuidRole); | 46 | menuItem.itemSelected(UuidRole); | ||
46 | plasmoid.expanded = false; | 47 | plasmoid.expanded = false; | ||
47 | } | 48 | } | ||
48 | onContainsMouseChanged: { | 49 | onContainsMouseChanged: { | ||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Line(s) | 92 | Item { | |||
93 | height: childrenRect.height | 94 | height: childrenRect.height | ||
94 | visible: !menuItem.ListView.isCurrentItem | 95 | visible: !menuItem.ListView.isCurrentItem | ||
95 | anchors { | 96 | anchors { | ||
96 | left: parent.left | 97 | left: parent.left | ||
97 | leftMargin: units.gridUnit / 2 - listMargins.left | 98 | leftMargin: units.gridUnit / 2 - listMargins.left | ||
98 | right: parent.right | 99 | right: parent.right | ||
99 | verticalCenter: parent.verticalCenter | 100 | verticalCenter: parent.verticalCenter | ||
100 | } | 101 | } | ||
101 | PlasmaComponents.Label { | | |||
102 | width: parent.width | | |||
103 | height: undefined // unset PlasmaComponents.Label default height | | |||
104 | maximumLineCount: 3 | | |||
105 | verticalAlignment: Text.AlignVCenter | | |||
106 | | ||||
107 | text: { | | |||
108 | var highlightFontTag = "<font color='" + theme.highlightColor + "'>%1</font>" | | |||
109 | | ||||
110 | var text = DisplayRole | | |||
111 | | ||||
112 | // first escape any HTML characters to prevent privacy issues | | |||
113 | text = text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") | | |||
114 | | ||||
115 | // color code leading or trailing whitespace | | |||
116 | // the first regex is basically "trim" | | |||
117 | text = text.replace(/^\s+|\s+$/gm, function(match) { | | |||
118 | // then inside the trimmed characters ("match") we replace each one individually | | |||
119 | match = match.replace(/ /g, "␣") // space | | |||
120 | .replace(/\t/g, "↹") // tab | | |||
121 | .replace(/\n/g, "↵") // return | | |||
122 | return highlightFontTag.arg(match) | | |||
123 | }) | | |||
124 | | ||||
125 | // finally turn line breaks into HTML br tags | | |||
126 | text = text.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, "<br>") | | |||
127 | | ||||
128 | return text | | |||
129 | } | | |||
130 | visible: TypeRole == 0 // TypeRole: 0: Text, 1: Image, 2: Url | | |||
131 | elide: Text.ElideRight | | |||
132 | wrapMode: Text.WrapAtWordBoundaryOrAnywhere | | |||
133 | textFormat: Text.StyledText | | |||
134 | } | | |||
135 | KQuickControlsAddons.QPixmapItem { | | |||
136 | id: previewPixmap | | |||
137 | width: parent.width | | |||
138 | height: Math.round(width * (nativeHeight/nativeWidth) + units.smallSpacing * 2) | | |||
139 | pixmap: DecorationRole | | |||
140 | visible: TypeRole == 1 | | |||
141 | fillMode: KQuickControlsAddons.QPixmapItem.PreserveAspectFit | | |||
142 | } | | |||
143 | Item { | | |||
144 | id: previewItem | | |||
145 | visible: TypeRole == 2 | | |||
146 | // visible updates recursively, our label becomes invisible when hovering, hence no visible check here | | |||
147 | height: TypeRole == 2 ? (units.gridUnit * 4 + units.smallSpacing * 2) : 0 | | |||
148 | width: parent.width | | |||
149 | | ||||
150 | ListView { | | |||
151 | id: previewList | | |||
152 | model: TypeRole == 2 ? DisplayRole.split(" ", maximumNumberOfPreviews) : 0 | | |||
153 | property int itemWidth: units.gridUnit * 4 | | |||
154 | property int itemHeight: units.gridUnit * 4 | | |||
155 | interactive: false | | |||
156 | | ||||
157 | spacing: units.smallSpacing | | |||
158 | orientation: Qt.Horizontal | | |||
159 | width: (itemWidth + spacing) * model.length | | |||
160 | anchors { | | |||
161 | top: parent.top | | |||
162 | left: parent.left | | |||
163 | bottom: parent.bottom | | |||
164 | } | | |||
165 | | ||||
166 | delegate: Item { | | |||
167 | width: previewList.itemWidth | | |||
168 | height: previewList.itemHeight | | |||
169 | y: Math.round((parent.height - previewList.itemHeight) / 2) | | |||
170 | clip: true | | |||
171 | | ||||
172 | KQuickControlsAddons.QPixmapItem { | | |||
173 | id: previewPixmap | | |||
174 | | ||||
175 | anchors.centerIn: parent | | |||
176 | | ||||
177 | Component.onCompleted: { | | |||
178 | function result(job) { | | |||
179 | if (!job.error) { | | |||
180 | pixmap = job.result.preview; | | |||
181 | previewPixmap.width = job.result.previewWidth | | |||
182 | previewPixmap.height = job.result.previewHeight | | |||
183 | } | | |||
184 | } | | |||
185 | var service = clipboardSource.serviceForSource(UuidRole) | | |||
186 | var operation = service.operationDescription("preview"); | | |||
187 | operation.url = modelData; | | |||
188 | // We request a bigger size and then clip out a square in the middle | | |||
189 | // so we get uniform delegate sizes without distortion | | |||
190 | operation.previewWidth = previewList.itemWidth * 2; | | |||
191 | operation.previewHeight = previewList.itemHeight * 2; | | |||
192 | var serviceJob = service.startOperationCall(operation); | | |||
193 | serviceJob.finished.connect(result); | | |||
194 | } | | |||
195 | } | | |||
196 | Rectangle { | | |||
197 | id: overlay | | |||
198 | color: theme.textColor | | |||
199 | opacity: 0.6 | | |||
200 | height: units.gridUnit | | |||
201 | anchors { | | |||
202 | left: parent.left | | |||
203 | right: parent.right | | |||
204 | bottom: parent.bottom | | |||
205 | } | | |||
206 | } | | |||
207 | PlasmaComponents.Label { | | |||
208 | font.pointSize: theme.smallestFont.pointSize | | |||
209 | color: theme.backgroundColor | | |||
210 | maximumLineCount: 1 | | |||
211 | anchors { | | |||
212 | verticalCenter: overlay.verticalCenter | | |||
213 | left: overlay.left | | |||
214 | right: overlay.right | | |||
215 | leftMargin: units.smallSpacing | | |||
216 | rightMargin: units.smallSpacing | | |||
217 | } | | |||
218 | elide: Text.ElideRight | | |||
219 | horizontalAlignment: Text.AlignHCenter | | |||
220 | text: { | | |||
221 | var u = modelData.split("/"); | | |||
222 | return decodeURIComponent(u[u.length - 1]); | | |||
223 | } | | |||
224 | } | | |||
225 | } | | |||
226 | } | | |||
227 | PlasmaComponents.Label { | | |||
228 | property int additionalItems: DisplayRole.split(" ").length - maximumNumberOfPreviews | | |||
229 | visible: additionalItems > 0 | | |||
230 | opacity: 0.6 | | |||
231 | text: i18nc("Indicator that there are more urls in the clipboard than previews shown", "+%1", additionalItems) | | |||
232 | anchors { | | |||
233 | left: previewList.right | | |||
234 | right: parent.right | | |||
235 | bottom: parent.bottom | | |||
236 | margins: units.smallSpacing | | |||
237 | 102 | | |||
238 | } | 103 | Loader { | ||
239 | verticalAlignment: Text.AlignBottom | 104 | width: parent.width | ||
240 | horizontalAlignment: Text.AlignCenter | 105 | source: ["Text", "Image", "Url"][TypeRole] + "ItemDelegate.qml" | ||
241 | font.pointSize: theme.smallestFont.pointSize | | |||
242 | } | | |||
243 | } | 106 | } | ||
244 | } | 107 | } | ||
245 | 108 | | |||
246 | Row { | 109 | Loader { | ||
247 | id: toolButtonsLayout | 110 | id: toolButtonsLoader | ||
248 | anchors { | 111 | anchors { | ||
249 | right: label.right | 112 | right: label.right | ||
250 | verticalCenter: parent.verticalCenter | 113 | verticalCenter: parent.verticalCenter | ||
251 | } | 114 | } | ||
252 | visible: menuItem.ListView.isCurrentItem | 115 | source: "DelegateToolButtons.qml" | ||
253 | 116 | active: menuItem.ListView.isCurrentItem | |||
254 | PlasmaComponents.ToolButton { | 117 | onActiveChanged: { | ||
255 | // TODO: only show for items supporting actions? | 118 | if (active) { | ||
256 | iconSource: "system-run" | 119 | // break binding, once it was loaded, never unload | ||
257 | tooltip: i18n("Invoke action") | 120 | active = true; | ||
258 | onClicked: menuItem.action(UuidRole) | | |||
259 | } | | |||
260 | PlasmaComponents.ToolButton { | | |||
261 | id: barcodeToolButton | | |||
262 | iconSource: "view-barcode" | | |||
263 | tooltip: i18n("Show barcode") | | |||
264 | onClicked: menuItem.barcode(UuidRole) | | |||
265 | } | | |||
266 | PlasmaComponents.ToolButton { | | |||
267 | iconSource: "document-edit" | | |||
268 | enabled: !clipboardSource.editing | | |||
269 | visible: TypeRole === 0 | | |||
270 | tooltip: i18n("Edit contents") | | |||
271 | onClicked: menuItem.edit(UuidRole) | | |||
272 | } | | |||
273 | PlasmaComponents.ToolButton { | | |||
274 | iconSource: "edit-delete" | | |||
275 | tooltip: i18n("Remove from history") | | |||
276 | onClicked: menuItem.remove(UuidRole) | | |||
277 | } | 121 | } | ||
278 | } | 122 | } | ||
123 | | ||||
124 | onStatusChanged: console.log("TUHL", index, status) | ||||
125 | } | ||||
279 | } | 126 | } |