Warning, /plasma/plasma-desktop/containments/desktop/package/contents/ui/FolderItemDelegate.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2014-2015 Eike Hein <hein@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 import QtQuick 2.15 0008 import QtQuick.Window 2.15 0009 import Qt5Compat.GraphicalEffects 0010 0011 import org.kde.plasma.plasmoid 2.0 0012 import org.kde.plasma.core as PlasmaCore 0013 import org.kde.plasma.extras as PlasmaExtras 0014 0015 import org.kde.kirigami 2.20 as Kirigami 0016 import org.kde.ksvg 1.0 as KSvg 0017 import org.kde.kquickcontrolsaddons 2.0 0018 0019 Item { 0020 id: main 0021 0022 property int index: model.index 0023 property string name: model.blank ? "" : model.display 0024 property string nameWrapped: model.blank ? "" : model.displayWrapped 0025 property bool blank: model.blank 0026 property bool isDir: loader.item ? loader.item.isDir : false 0027 property QtObject popupDialog: loader.item ? loader.item.popupDialog : null 0028 property Item iconArea: loader.item ? loader.item.iconArea : null 0029 property Item label: loader.item ? loader.item.label : null 0030 property Item labelArea: loader.item ? loader.item.labelArea : null 0031 property Item actionsOverlay: loader.item ? loader.item.actionsOverlay : null 0032 property Item hoverArea: loader.item ? loader.item.hoverArea : null 0033 property Item frame: loader.item ? loader.item.frame : null 0034 property Item toolTip: loader.item ? loader.item.toolTip : null 0035 Accessible.name: name 0036 Accessible.role: Accessible.Canvas 0037 0038 // This MouseArea exists to intercept press and hold; preventing edit mode 0039 // from being triggered when pressing and holding on an icon (if there is one). 0040 MouseArea { 0041 anchors.fill: parent 0042 visible: !main.blank 0043 } 0044 0045 function openPopup() { 0046 if (isDir) { 0047 loader.item.openPopup(); 0048 } 0049 } 0050 0051 function closePopup() { 0052 if (popupDialog) { 0053 popupDialog.requestDestroy(); 0054 loader.item.popupDialog = null; 0055 } 0056 } 0057 0058 Loader { 0059 id: loader 0060 0061 // On the desktop we pad our cellSize to avoid a gap at the right/bottom of the screen. 0062 // The padding per item is quite small and causes the delegate to be positioned on fractional pixels 0063 // leading to blurry rendering. The Loader is offset to account for this. 0064 x: -main.x % 1 0065 y: -main.y % 1 0066 width: parent.width 0067 height: parent.height 0068 0069 visible: status === Loader.Ready 0070 0071 active: !model.blank 0072 0073 sourceComponent: delegateImplementation 0074 0075 asynchronous: true 0076 } 0077 0078 Component { 0079 id: delegateImplementation 0080 0081 Item { 0082 id: impl 0083 0084 anchors.fill: parent 0085 0086 property bool blank: model.blank 0087 property bool selected: model.blank ? false : model.selected 0088 property bool isDir: model.blank ? false : model.isDir 0089 property bool hovered: (main.GridView.view.hoveredItem === main) 0090 property QtObject popupDialog: null 0091 property Item iconArea: icon 0092 property Item label: label 0093 property Item labelArea: label 0094 property Item actionsOverlay: actions 0095 property Item hoverArea: toolTip 0096 property Item frame: frameLoader 0097 property Item toolTip: toolTip 0098 property Item selectionButton: null 0099 property Item popupButton: null 0100 0101 readonly property bool iconAndLabelsShouldlookSelected: impl.hovered 0102 0103 // When a drop happens, a new item is created, and is set to selected 0104 // grabToImagebefore it gets the final width, making grabToImage fail because it's still 0x0 0105 onSelectedChanged: Qt.callLater(updateDragImage) 0106 function updateDragImage() { 0107 if (selected && !blank) { 0108 frameLoader.grabToImage(result => { 0109 dir.addItemDragImage(positioner.map(index), main.x + frameLoader.x, main.y + frameLoader.y, frameLoader.width, frameLoader.height, result.image); 0110 }); 0111 } 0112 } 0113 0114 Connections { 0115 target: model 0116 0117 function onSelectedChanged() { 0118 if (dir.usedByContainment && model.selected) { 0119 gridView.currentIndex = model.index; 0120 } 0121 } 0122 } 0123 0124 onHoveredChanged: { 0125 if (hovered) { 0126 // In list view, it behaves more like a menu, and menus always activate their items on a single click 0127 if (Plasmoid.configuration.selectionMarkers && (Qt.styleHints.singleClickActivation || root.useListViewMode)) { 0128 selectionButton = selectionButtonComponent.createObject(actions); 0129 } 0130 0131 if (model.isDir) { 0132 if (!main.GridView.view.isRootView || root.containsDrag) { 0133 hoverActivateTimer.restart(); 0134 } 0135 0136 if (Plasmoid.configuration.popups && !root.useListViewMode) { 0137 popupButton = popupButtonComponent.createObject(actions); 0138 } 0139 } 0140 } else if (!hovered) { 0141 if (popupDialog != null) { 0142 closePopup(); 0143 } 0144 0145 if (selectionButton) { 0146 selectionButton.destroy(); 0147 selectionButton = null; 0148 } 0149 0150 if (popupButton) { 0151 popupButton.destroy(); 0152 popupButton = null; 0153 } 0154 } 0155 } 0156 0157 function openPopup() { 0158 if (folderViewDialogComponent.status === Component.Ready) { 0159 impl.popupDialog = folderViewDialogComponent.createObject(impl); 0160 impl.popupDialog.visualParent = icon; 0161 impl.popupDialog.url = model.linkDestinationUrl; 0162 impl.popupDialog.visible = true; 0163 } 0164 } 0165 0166 PlasmaCore.ToolTipArea { 0167 id: toolTip 0168 0169 active: (Plasmoid.configuration.toolTips || label.truncated) 0170 && popupDialog === null 0171 && !model.blank 0172 interactive: false 0173 location: root.useListViewMode ? (Plasmoid.location === PlasmaCore.Types.LeftEdge ? PlasmaCore.Types.LeftEdge : PlasmaCore.Types.RightEdge) : Plasmoid.location 0174 0175 onContainsMouseChanged: { 0176 if (containsMouse && !model.blank) { 0177 if (toolTip.active) { 0178 toolTip.icon = model.decoration; 0179 toolTip.mainText = model.display; 0180 0181 if (model.size !== undefined) { 0182 toolTip.subText = model.type + "\n" + model.size; 0183 } else { 0184 toolTip.subText = model.type; 0185 } 0186 } 0187 0188 main.GridView.view.hoveredItem = main; 0189 } 0190 } 0191 0192 states: [ 0193 State { // icon view 0194 when: !root.useListViewMode 0195 0196 AnchorChanges { 0197 target: toolTip 0198 anchors.horizontalCenter: parent.horizontalCenter 0199 } 0200 0201 PropertyChanges { 0202 target: toolTip 0203 y: frameLoader.y + icon.y 0204 width: Math.max(icon.paintedWidth, label.paintedWidth) 0205 height: (label.y + label.paintedHeight) - y 0206 } 0207 }, 0208 State { // list view 0209 when: root.useListViewMode 0210 0211 AnchorChanges { 0212 target: toolTip 0213 anchors.horizontalCenter: undefined 0214 } 0215 0216 PropertyChanges { 0217 target: toolTip 0218 x: frameLoader.x 0219 y: frameLoader.y 0220 width: frameLoader.width 0221 height: frameLoader.height 0222 } 0223 } 0224 ] 0225 } 0226 0227 Loader { 0228 id: frameLoader 0229 0230 x: root.useListViewMode ? 0 : Kirigami.Units.smallSpacing 0231 y: root.useListViewMode ? 0 : Kirigami.Units.smallSpacing 0232 0233 property Item iconShadow: null 0234 property string prefix: "" 0235 0236 sourceComponent: frameComponent 0237 active: impl.iconAndLabelsShouldlookSelected || model.selected 0238 asynchronous: true 0239 0240 width: { 0241 if (root.useListViewMode) { 0242 if (main.GridView.view.overflowing) { 0243 return parent.width - Kirigami.Units.smallSpacing; 0244 } else { 0245 return parent.width; 0246 } 0247 } 0248 0249 return parent.width - (Kirigami.Units.smallSpacing * 2); 0250 } 0251 0252 height: root.useListViewMode 0253 ? parent.height 0254 // the smallSpacings are for padding 0255 : icon.height + (Kirigami.Units.gridUnit * label.lineCount) + (Kirigami.Units.smallSpacing * 3) 0256 0257 Kirigami.Icon { 0258 id: icon 0259 0260 z: 2 0261 0262 states: [ 0263 State { // icon view 0264 when: !root.useListViewMode 0265 0266 AnchorChanges { 0267 target: icon 0268 anchors.top: parent.top 0269 anchors.horizontalCenter: parent.horizontalCenter 0270 } 0271 }, 0272 State { // list view 0273 when: root.useListViewMode 0274 0275 AnchorChanges { 0276 target: icon 0277 anchors.left: parent.left 0278 anchors.verticalCenter: parent.verticalCenter 0279 } 0280 } 0281 ] 0282 0283 anchors { 0284 topMargin: Kirigami.Units.smallSpacing 0285 leftMargin: Kirigami.Units.smallSpacing 0286 } 0287 0288 width: root.useListViewMode ? main.GridView.view.iconSize : (parent.width - 2 * Kirigami.Units.smallSpacing) 0289 height: main.GridView.view.iconSize 0290 0291 opacity: { 0292 if (root.useListViewMode && selectionButton) { 0293 return 0.3; 0294 } 0295 0296 if (model.isHidden) { 0297 return 0.6; 0298 } 0299 0300 return 1.0; 0301 } 0302 0303 animated: false 0304 0305 source: model.decoration 0306 } 0307 0308 PlasmaExtras.ShadowedLabel { 0309 id: label 0310 0311 z: 2 // So it's always above the highlight effect 0312 0313 states: [ 0314 State { // icon view 0315 when: !root.useListViewMode 0316 0317 AnchorChanges { 0318 target: label 0319 anchors.top: icon.bottom 0320 anchors.horizontalCenter: parent.horizontalCenter 0321 } 0322 PropertyChanges { 0323 target: label 0324 anchors.topMargin: Kirigami.Units.smallSpacing 0325 width: parent.width - Kirigami.Units.smallSpacing 0326 maximumLineCount: Plasmoid.configuration.textLines 0327 horizontalAlignment: Text.AlignHCenter 0328 } 0329 }, 0330 State { // list view 0331 when: root.useListViewMode 0332 0333 AnchorChanges { 0334 target: label 0335 anchors.left: icon.right 0336 anchors.verticalCenter: parent.verticalCenter 0337 } 0338 PropertyChanges { 0339 target: label 0340 anchors.leftMargin: Kirigami.Units.smallSpacing * 2 0341 anchors.rightMargin: Kirigami.Units.smallSpacing * 2 0342 width: parent.width - icon.width - (Kirigami.Units.smallSpacing * 4) 0343 maximumLineCount: 1 0344 horizontalAlignment: Text.AlignLeft 0345 } 0346 } 0347 ] 0348 0349 color: { 0350 if (!root.useListViewMode) { 0351 // In this situation there's a shadow or a background rect, both of which are always black 0352 return "white"; 0353 } 0354 0355 if (model.selected) { 0356 return Kirigami.Theme.highlightedTextColor; 0357 } 0358 0359 return Kirigami.Theme.textColor; 0360 0361 } 0362 renderShadow: (!editor || editor.targetItem !== main) && !root.useListViewMode 0363 opacity: model.isHidden ? 0.6 : 1 0364 0365 text: main.nameWrapped 0366 font.italic: model.isLink 0367 wrapMode: (maximumLineCount === 1) ? Text.NoWrap : Text.Wrap 0368 horizontalAlignment: Text.AlignHCenter 0369 } 0370 0371 Component { 0372 id: frameComponent 0373 0374 PlasmaExtras.Highlight { 0375 // Workaround for a bug where the frameComponent does not 0376 // get unloaded when items are dragged to a different 0377 // place on the desktop. 0378 visible: this === frameLoader.item 0379 hovered: impl.iconAndLabelsShouldlookSelected 0380 pressed: model.selected 0381 active: Window.active 0382 } 0383 } 0384 0385 Component { 0386 id: selectionButtonComponent 0387 0388 FolderItemActionButton { 0389 element: model.selected ? "remove" : "add" 0390 0391 onClicked: { 0392 dir.toggleSelected(positioner.map(index)); 0393 main.GridView.view.currentIndex = index; 0394 } 0395 } 0396 } 0397 0398 Component { 0399 id: popupButtonComponent 0400 0401 FolderItemActionButton { 0402 visible: main.GridView.view.isRootView && (popupDialog == null) 0403 0404 element: "open" 0405 0406 onClicked: { 0407 dir.setSelected(positioner.map(index)); 0408 main.GridView.view.currentIndex = index; 0409 openPopup(); 0410 } 0411 } 0412 } 0413 0414 Component { 0415 id: iconShadowComponent 0416 0417 DropShadow { 0418 anchors.fill: icon 0419 0420 z: 1 0421 0422 verticalOffset: 1 0423 0424 radius: 5.0 0425 samples: radius * 2 + 1 0426 spread: 0.05 0427 0428 color: "black" 0429 0430 opacity: model.isHidden ? 0.3 : 0.6 0431 0432 source: icon 0433 } 0434 } 0435 } 0436 0437 Column { 0438 id: actions 0439 0440 visible: { 0441 if (main.GridView.view.isRootView && root.containsDrag) { 0442 return false; 0443 } 0444 0445 if (!main.GridView.view.isRootView && main.GridView.view.dialog && main.GridView.view.dialog.containsDrag) { 0446 return false; 0447 } 0448 0449 if (popupDialog) { 0450 return false; 0451 } 0452 0453 return true; 0454 } 0455 0456 anchors { 0457 left: frameLoader.left 0458 top: frameLoader.top 0459 leftMargin: root.useListViewMode ? (icon.x + (icon.width / 2)) - (width / 2) : 0 0460 topMargin: root.useListViewMode ? (icon.y + (icon.height / 2)) - (height / 2) : 0 0461 } 0462 0463 width: implicitWidth 0464 height: implicitHeight 0465 } 0466 0467 Component.onCompleted: { 0468 if (Plasmoid.isContainment && main.GridView.view.isRootView && root.GraphicsInfo.api === GraphicsInfo.OpenGL) { 0469 frameLoader.iconShadow = iconShadowComponent.createObject(frameLoader); 0470 } 0471 } 0472 } 0473 } 0474 }