1/* 2 SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org> 3 4 SPDX-License-Identifier: LGPL-2.0-or-later 5*/ 6 7import QtQuick 2.7 8import QtQuick.Controls 2.5 as QQC2 9 10import org.kde.plasma.components 2.0 as PlasmaComponents 11import org.kde.plasma.core 2.0 as PlasmaCore 12import org.kde.plasma.extras 2.0 as PlasmaExtras 13import org.kde.kquickcontrolsaddons 2.0 14import org.kde.kwindowsystem 1.0 15 16import QtQuick.Window 2.1 17import QtQuick.Layouts 1.1 18 19import org.kde.plasma.private.shell 2.0 20 21Item { 22 id: main 23 24 width: Math.max(heading.paintedWidth, PlasmaCore.Units.iconSizes.enormous * 3 + PlasmaCore.Units.smallSpacing * 4 + PlasmaCore.Units.gridUnit * 2) 25 height: 800//Screen.height 26 27 opacity: draggingWidget ? 0.3 : 1 28 29 property QtObject containment 30 31 //external drop events can cause a raise event causing us to lose focus and 32 //therefore get deleted whilst we are still in a drag exec() 33 //this is a clue to the owning dialog that hideOnWindowDeactivate should be deleted 34 //See https://bugs.kde.org/show_bug.cgi?id=332733 35 property bool preventWindowHide: draggingWidget || categoriesDialog.status !== PlasmaComponents.DialogStatus.Closed 36 || getWidgetsDialog.status !== PlasmaComponents.DialogStatus.Closed 37 38 property bool outputOnly: draggingWidget 39 40 property Item categoryButton 41 42 property bool draggingWidget: false 43 44 signal closed() 45 46 onVisibleChanged: { 47 if (!visible) { 48 kwindowsystem.showingDesktop = false 49 } 50 } 51 52 Component.onCompleted: { 53 if (!root.widgetExplorer) { 54 root.widgetExplorer = widgetExplorerComponent.createObject(root) 55 } 56 root.widgetExplorer.containment = main.containment 57 } 58 59 Component.onDestruction: { 60 if (pendingUninstallTimer.running) { 61 // we're not being destroyed so at least reset the filters 62 widgetExplorer.widgetsModel.filterQuery = "" 63 widgetExplorer.widgetsModel.filterType = "" 64 widgetExplorer.widgetsModel.searchTerm = "" 65 } else { 66 root.widgetExplorer.destroy() 67 root.widgetExplorer = null 68 } 69 } 70 71 function addCurrentApplet() { 72 var pluginName = list.currentItem ? list.currentItem.pluginName : "" 73 if (pluginName) { 74 widgetExplorer.addApplet(pluginName) 75 } 76 } 77 78 KWindowSystem { 79 id: kwindowsystem 80 } 81 82 QQC2.Action { 83 shortcut: "Escape" 84 onTriggered: { 85 if (searchInput.length > 0) { 86 searchInput.text = "" 87 } else { 88 main.closed() 89 } 90 } 91 } 92 93 QQC2.Action { 94 shortcut: "Up" 95 onTriggered: list.currentIndex = (list.count + list.currentIndex - 1) % list.count 96 } 97 98 QQC2.Action { 99 shortcut: "Down" 100 onTriggered: list.currentIndex = (list.currentIndex + 1) % list.count 101 } 102 103 QQC2.Action { 104 shortcut: "Enter" 105 onTriggered: addCurrentApplet() 106 } 107 QQC2.Action { 108 shortcut: "Return" 109 onTriggered: addCurrentApplet() 110 } 111 112 Component { 113 id: widgetExplorerComponent 114 115 WidgetExplorer { 116 //view: desktop 117 onShouldClose: main.closed(); 118 } 119 } 120 121 PlasmaComponents.ModelContextMenu { 122 id: categoriesDialog 123 visualParent: categoryButton 124 // model set on first invocation 125 126 onClicked: { 127 list.contentX = 0 128 list.contentY = 0 129 categoryButton.text = (model.filterData ? model.display : i18nd("plasma_shell_org.kde.plasma.desktop", "All Widgets")) 130 widgetExplorer.widgetsModel.filterQuery = model.filterData 131 widgetExplorer.widgetsModel.filterType = model.filterType 132 } 133 } 134 135 PlasmaComponents.ModelContextMenu { 136 id: getWidgetsDialog 137 visualParent: getWidgetsButton 138 placement: PlasmaCore.Types.TopPosedLeftAlignedPopup 139 // model set on first invocation 140 onClicked: model.trigger() 141 } 142 /* 143 PlasmaCore.Dialog { 144 id: tooltipDialog 145 property Item appletDelegate 146 location: PlasmaCore.Types.RightEdge //actually we want this to be the opposite location of the explorer itself 147 148 type: PlasmaCore.Dialog.Tooltip 149 flags:Qt.Window|Qt.WindowStaysOnTopHint|Qt.X11BypassWindowManagerHint 150 151 onAppletDelegateChanged: { 152 if (!appletDelegate) { 153 toolTipHideTimer.restart() 154 toolTipShowTimer.running = false 155 } else if (tooltipDialog.visible) { 156 tooltipDialog.visualParent = appletDelegate 157 } else { 158 tooltipDialog.visualParent = appletDelegate 159 toolTipShowTimer.restart() 160 toolTipHideTimer.running = false 161 } 162 } 163 mainItem: Tooltip { id: tooltipWidget } 164 165 Behavior on y { 166 NumberAnimation { duration: PlasmaCore.Units.longDuration } 167 } 168 } 169 Timer { 170 id: toolTipShowTimer 171 interval: 500 172 repeat: false 173 onTriggered: { 174 tooltipDialog.visible = true 175 } 176 } 177 Timer { 178 id: toolTipHideTimer 179 interval: 1000 180 repeat: false 181 onTriggered: tooltipDialog.visible = false 182 } 183 */ 184 185 186 PlasmaExtras.PlasmoidHeading { 187 id: topArea 188 implicitWidth: header.implicitWidth 189 implicitHeight: header.implicitHeight 190 anchors { 191 top: parent.top 192 left: parent.left 193 right: parent.right 194 } 195 196 ColumnLayout { 197 id: header 198 anchors.fill: parent 199 200 RowLayout { 201 PlasmaExtras.Heading { 202 id: heading 203 level: 1 204 text: i18nd("plasma_shell_org.kde.plasma.desktop", "Widgets") 205 elide: Text.ElideRight 206 207 Layout.fillWidth: true 208 } 209 PlasmaComponents.ToolButton { 210 id: getWidgetsButton 211 iconSource: "get-hot-new-stuff" 212 text: i18nd("plasma_shell_org.kde.plasma.desktop", "Get New Widgets…") 213 onClicked: { 214 getWidgetsDialog.model = widgetExplorer.widgetsMenuActions 215 getWidgetsDialog.openRelative() 216 } 217 } 218 PlasmaComponents.ToolButton { 219 id: closeButton 220 iconSource: "window-close" 221 onClicked: main.closed() 222 } 223 } 224 225 RowLayout { 226 PlasmaComponents.TextField { 227 id: searchInput 228 Layout.fillWidth: true 229 clearButtonShown: true 230 placeholderText: i18nd("plasma_shell_org.kde.plasma.desktop", "Search…") 231 232 inputMethodHints: Qt.ImhNoPredictiveText 233 234 onTextChanged: { 235 list.positionViewAtBeginning() 236 list.currentIndex = -1 237 widgetExplorer.widgetsModel.searchTerm = text 238 } 239 240 Component.onCompleted: forceActiveFocus() 241 } 242 PlasmaComponents.ToolButton { 243 id: categoryButton 244 tooltip: i18nd("plasma_shell_org.kde.plasma.desktop", "Categories") 245 text: i18nd("plasma_shell_org.kde.plasma.desktop", "All Widgets") 246 iconSource: "view-filter" 247 onClicked: { 248 categoriesDialog.model = widgetExplorer.filterModel 249 categoriesDialog.open(0, categoryButton.height) 250 } 251 } 252 } 253 254 Item { 255 height: PlasmaCore.Units.smallSpacing 256 } 257 } 258 } 259 260 Timer { 261 id: setModelTimer 262 interval: 20 263 running: true 264 onTriggered: list.model = widgetExplorer.widgetsModel 265 } 266 267 PlasmaExtras.ScrollArea { 268 anchors { 269 top: topArea.bottom 270 left: parent.left 271 right: parent.right 272 bottom: parent.bottom 273 } 274 275 verticalScrollBarPolicy: Qt.ScrollBarAlwaysOn 276 277 // hide the flickering by fading in nicely 278 opacity: setModelTimer.running ? 0 : 1 279 Behavior on opacity { 280 OpacityAnimator { 281 duration: PlasmaCore.Units.longDuration 282 easing.type: Easing.InOutQuad 283 } 284 } 285 286 GridView { 287 id: list 288 289 // model set delayed by Timer above 290 291 activeFocusOnTab: true 292 keyNavigationWraps: true 293 cellWidth: Math.floor((width - PlasmaCore.Units.smallSpacing) / 3) 294 cellHeight: cellWidth + PlasmaCore.Units.gridUnit * 4 + PlasmaCore.Units.smallSpacing * 2 295 296 delegate: AppletDelegate {} 297 highlight: PlasmaComponents.Highlight {} 298 highlightMoveDuration: 0 299 //highlightResizeDuration: 0 300 301 //slide in to view from the left 302 add: Transition { 303 NumberAnimation { 304 properties: "x" 305 from: -list.width 306 duration: PlasmaCore.Units.shortDuration 307 } 308 } 309 310 //slide out of view to the right 311 remove: Transition { 312 NumberAnimation { 313 properties: "x" 314 to: list.width 315 duration: PlasmaCore.Units.shortDuration 316 } 317 } 318 319 //if we are adding other items into the view use the same animation as normal adding 320 //this makes everything slide in together 321 //if we make it move everything ends up weird 322 addDisplaced: list.add 323 324 //moved due to filtering 325 displaced: Transition { 326 NumberAnimation { 327 properties: "x,y" 328 duration: PlasmaCore.Units.shortDuration 329 } 330 } 331 332 PlasmaExtras.Heading { 333 anchors.fill: parent 334 anchors.margins: PlasmaCore.Units.largeSpacing 335 horizontalAlignment: Text.AlignHCenter 336 verticalAlignment: Text.AlignVCenter 337 wrapMode: Text.WordWrap 338 level: 2 339 text: searchInput.text.length > 0 ? i18n("No widgets matched the search terms") : i18n("No widgets available") 340 enabled: false 341 visible: list.count == 0 342 } 343 } 344 } 345} 346