Warning, /plasma/plasma-desktop/applets/kickoff/package/contents/ui/main.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-FileCopyrightText: 2011 Martin Gräßlin <mgraesslin@kde.org> 0003 SPDX-FileCopyrightText: 2012 Gregor Taetzner <gregor@freenet.de> 0004 SPDX-FileCopyrightText: 2012 Marco Martin <mart@kde.org> 0005 SPDX-FileCopyrightText: 2013 David Edmundson <davidedmundson@kde.org> 0006 SPDX-FileCopyrightText: 2015 Eike Hein <hein@kde.org> 0007 SPDX-FileCopyrightText: 2021 Mikel Johnson <mikel5764@gmail.com> 0008 SPDX-FileCopyrightText: 2021 Noah Davis <noahadvs@gmail.com> 0009 0010 SPDX-License-Identifier: GPL-2.0-or-later 0011 */ 0012 import QtQuick 2.15 0013 import QtQuick.Layouts 1.15 0014 import QtQuick.Window 2.15 0015 import QtQml 2.15 0016 import org.kde.plasma.plasmoid 2.0 0017 import org.kde.plasma.core as PlasmaCore 0018 import org.kde.ksvg 1.0 as KSvg 0019 import org.kde.plasma.components 3.0 as PC3 0020 import org.kde.plasma.private.kicker 0.1 as Kicker 0021 import org.kde.kirigami 2.20 as Kirigami 0022 0023 import "code/tools.js" as Tools 0024 0025 PlasmoidItem { 0026 id: kickoff 0027 0028 // The properties are defined here instead of the singleton because each 0029 // instance of Kickoff requires different instances of these properties 0030 0031 readonly property bool inPanel: [ 0032 PlasmaCore.Types.TopEdge, 0033 PlasmaCore.Types.RightEdge, 0034 PlasmaCore.Types.BottomEdge, 0035 PlasmaCore.Types.LeftEdge, 0036 ].includes(Plasmoid.location) 0037 readonly property bool vertical: Plasmoid.formFactor === PlasmaCore.Types.Vertical 0038 0039 // Used to prevent the width from changing frequently when the scrollbar appears or disappears 0040 readonly property bool mayHaveGridWithScrollBar: Plasmoid.configuration.applicationsDisplay === 0 0041 || (Plasmoid.configuration.favoritesDisplay === 0 && kickoff.rootModel.favoritesModel.count > minimumGridRowCount * minimumGridRowCount) 0042 0043 //BEGIN Models 0044 readonly property Kicker.RootModel rootModel: Kicker.RootModel { 0045 autoPopulate: false 0046 0047 // TODO: appletInterface property now can be ported to "applet" and have the real Applet* assigned directly 0048 appletInterface: kickoff 0049 0050 flat: true // have categories, but no subcategories 0051 sorted: Plasmoid.configuration.alphaSort 0052 showSeparators: true 0053 showTopLevelItems: true 0054 0055 showAllApps: true 0056 showAllAppsCategorized: false 0057 showRecentApps: false 0058 showRecentDocs: false 0059 showPowerSession: false 0060 showFavoritesPlaceholder: true 0061 0062 Component.onCompleted: { 0063 favoritesModel.initForClient("org.kde.plasma.kickoff.favorites.instance-" + Plasmoid.id) 0064 0065 if (!Plasmoid.configuration.favoritesPortedToKAstats) { 0066 if (favoritesModel.count < 1) { 0067 favoritesModel.portOldFavorites(Plasmoid.configuration.favorites); 0068 } 0069 Plasmoid.configuration.favoritesPortedToKAstats = true; 0070 } 0071 } 0072 } 0073 0074 readonly property Kicker.RunnerModel runnerModel: Kicker.RunnerModel { 0075 query: kickoff.searchField ? kickoff.searchField.text : "" 0076 onRequestUpdateQuery: query => { 0077 if (kickoff.searchField) { 0078 kickoff.searchField.text = query; 0079 } 0080 } 0081 appletInterface: kickoff 0082 mergeResults: true 0083 favoritesModel: rootModel.favoritesModel 0084 } 0085 0086 readonly property Kicker.ComputerModel computerModel: Kicker.ComputerModel { 0087 appletInterface: kickoff 0088 favoritesModel: rootModel.favoritesModel 0089 systemApplications: Plasmoid.configuration.systemApplications 0090 Component.onCompleted: { 0091 //systemApplications = Plasmoid.configuration.systemApplications; 0092 } 0093 } 0094 0095 readonly property Kicker.RecentUsageModel recentUsageModel: Kicker.RecentUsageModel { 0096 favoritesModel: rootModel.favoritesModel 0097 } 0098 0099 readonly property Kicker.RecentUsageModel frequentUsageModel: Kicker.RecentUsageModel { 0100 favoritesModel: rootModel.favoritesModel 0101 ordering: 1 // Popular / Frequently Used 0102 } 0103 //END 0104 0105 //BEGIN UI elements 0106 // Set in FullRepresentation.qml 0107 property Item header: null 0108 0109 // Set in Header.qml 0110 property PC3.TextField searchField: null 0111 0112 // Set in FullRepresentation.qml, ApplicationPage.qml, PlacesPage.qml 0113 property Item sideBar: null // is null when searching 0114 property Item contentArea: null // is searchView when searching 0115 0116 // Set in NormalPage.qml 0117 property Item footer: null 0118 0119 // True when central pane (and header) LayoutMirroring diverges from global 0120 // LayoutMirroring, in order to achieve the desired sidebar position 0121 readonly property bool paneSwap: Plasmoid.configuration.paneSwap 0122 readonly property bool sideBarOnRight: (Qt.application.layoutDirection == Qt.RightToLeft) != paneSwap 0123 // References to items according to their focus chain order 0124 readonly property Item firstHeaderItem: header ? (paneSwap ? header.pinButton : header.avatar) : null 0125 readonly property Item lastHeaderItem: header ? (paneSwap ? header.avatar : header.pinButton) : null 0126 readonly property Item firstCentralPane: paneSwap ? contentArea : sideBar 0127 readonly property Item lastCentralPane: paneSwap ? sideBar : contentArea 0128 //END 0129 0130 //BEGIN Metrics 0131 readonly property KSvg.FrameSvgItem backgroundMetrics: KSvg.FrameSvgItem { 0132 // Inset defaults to a negative value when not set by margin hints 0133 readonly property real leftPadding: margins.left - Math.max(inset.left, 0) 0134 readonly property real rightPadding: margins.right - Math.max(inset.right, 0) 0135 readonly property real topPadding: margins.top - Math.max(inset.top, 0) 0136 readonly property real bottomPadding: margins.bottom - Math.max(inset.bottom, 0) 0137 readonly property real spacing: leftPadding 0138 visible: false 0139 imagePath: Plasmoid.formFactor === PlasmaCore.Types.Planar ? "widgets/background" : "dialogs/background" 0140 } 0141 0142 // This is here rather than in the singleton with the other metrics items 0143 // because the list delegate's height depends on a configuration setting 0144 // and the singleton can't access those 0145 readonly property real listDelegateHeight: listDelegate.height 0146 KickoffListDelegate { 0147 id: listDelegate 0148 visible: false 0149 enabled: false 0150 model: null 0151 index: -1 0152 text: "asdf" 0153 url: "" 0154 decoration: "start-here-kde" 0155 description: "asdf" 0156 action: null 0157 indicator: null 0158 } 0159 0160 // Used to show smaller Kickoff on small screens 0161 readonly property int minimumGridRowCount: Math.min(Screen.desktopAvailableWidth, Screen.desktopAvailableHeight) * Screen.devicePixelRatio < KickoffSingleton.gridCellSize * 4 + (fullRepresentationItem ? fullRepresentationItem.normalPage.preferredSideBarWidth : KickoffSingleton.gridCellSize * 2) ? 2 : 4 0162 //END 0163 0164 Plasmoid.icon: Plasmoid.configuration.icon 0165 0166 switchWidth: fullRepresentationItem ? fullRepresentationItem.Layout.minimumWidth : -1 0167 switchHeight: fullRepresentationItem ? fullRepresentationItem.Layout.minimumHeight : -1 0168 0169 preferredRepresentation: compactRepresentation 0170 0171 fullRepresentation: FullRepresentation { focus: true } 0172 0173 // Only exists because the default CompactRepresentation doesn't: 0174 // - open on drag 0175 // - allow defining a custom drop handler 0176 // - expose the ability to show text below or beside the icon 0177 // TODO remove once it gains those features 0178 compactRepresentation: MouseArea { 0179 id: compactRoot 0180 0181 // Taken from DigitalClock to ensure uniform sizing when next to each other 0182 readonly property bool tooSmall: Plasmoid.formFactor === PlasmaCore.Types.Horizontal && Math.round(2 * (compactRoot.height / 5)) <= Kirigami.Theme.smallFont.pixelSize 0183 0184 readonly property bool shouldHaveIcon: Plasmoid.formFactor === PlasmaCore.Types.Vertical || Plasmoid.icon !== "" 0185 readonly property bool shouldHaveLabel: Plasmoid.formFactor !== PlasmaCore.Types.Vertical && Plasmoid.configuration.menuLabel !== "" 0186 0187 readonly property int iconSize: 48 0188 0189 readonly property var sizing: { 0190 const displayedIcon = buttonIcon.valid ? buttonIcon : buttonIconFallback; 0191 0192 let impWidth = 0; 0193 if (shouldHaveIcon) { 0194 impWidth += displayedIcon.width; 0195 } 0196 if (shouldHaveLabel) { 0197 impWidth += labelTextField.contentWidth + labelTextField.Layout.leftMargin + labelTextField.Layout.rightMargin; 0198 } 0199 const impHeight = displayedIcon.height > 0 ? displayedIcon.height : iconSize 0200 0201 // at least square, but can be wider/taller 0202 if (kickoff.inPanel) { 0203 if (kickoff.vertical) { 0204 return { 0205 preferredWidth: iconSize, 0206 preferredHeight: impHeight 0207 }; 0208 } else { // horizontal 0209 return { 0210 preferredWidth: impWidth, 0211 preferredHeight: iconSize 0212 }; 0213 } 0214 } else { 0215 return { 0216 preferredWidth: impWidth, 0217 preferredHeight: Kirigami.Units.iconSizes.small, 0218 }; 0219 } 0220 } 0221 0222 implicitWidth: iconSize 0223 implicitHeight: iconSize 0224 0225 Layout.preferredWidth: sizing.preferredWidth 0226 Layout.preferredHeight: sizing.preferredHeight 0227 Layout.minimumWidth: Layout.preferredWidth 0228 Layout.minimumHeight: Layout.preferredHeight 0229 0230 hoverEnabled: true 0231 0232 property bool wasExpanded 0233 0234 Accessible.name: Plasmoid.title 0235 0236 onPressed: wasExpanded = kickoff.expanded 0237 onClicked: kickoff.expanded = !wasExpanded 0238 0239 DropArea { 0240 id: compactDragArea 0241 anchors.fill: parent 0242 } 0243 0244 Timer { 0245 id: expandOnDragTimer 0246 // this is an interaction and not an animation, so we want it as a constant 0247 interval: 250 0248 running: compactDragArea.containsDrag 0249 onTriggered: kickoff.expanded = true 0250 } 0251 0252 RowLayout { 0253 id: iconLabelRow 0254 anchors.fill: parent 0255 spacing: 0 0256 0257 Kirigami.Icon { 0258 id: buttonIcon 0259 0260 Layout.fillWidth: kickoff.vertical 0261 Layout.fillHeight: !kickoff.vertical 0262 Layout.preferredWidth: kickoff.vertical ? -1 : height / (implicitHeight / implicitWidth) 0263 Layout.preferredHeight: !kickoff.vertical ? -1 : width * (implicitHeight / implicitWidth) 0264 Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter 0265 source: Tools.iconOrDefault(Plasmoid.formFactor, Plasmoid.icon) 0266 active: compactRoot.containsMouse || compactDragArea.containsDrag 0267 roundToIconSize: implicitHeight === implicitWidth 0268 visible: valid 0269 } 0270 0271 Kirigami.Icon { 0272 id: buttonIconFallback 0273 // fallback is assumed to be square 0274 Layout.fillWidth: kickoff.vertical 0275 Layout.fillHeight: !kickoff.vertical 0276 Layout.preferredWidth: kickoff.vertical ? -1 : height 0277 Layout.preferredHeight: !kickoff.vertical ? -1 : width 0278 Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter 0279 0280 source: buttonIcon.valid ? null : Tools.defaultIconName 0281 active: compactRoot.containsMouse || compactDragArea.containsDrag 0282 visible: !buttonIcon.valid && Plasmoid.icon !== "" 0283 } 0284 0285 PC3.Label { 0286 id: labelTextField 0287 0288 Layout.fillHeight: true 0289 Layout.leftMargin: Kirigami.Units.smallSpacing 0290 Layout.rightMargin: Kirigami.Units.smallSpacing 0291 0292 text: Plasmoid.configuration.menuLabel 0293 textFormat: Text.PlainText 0294 horizontalAlignment: Text.AlignLeft 0295 verticalAlignment: Text.AlignVCenter 0296 wrapMode: Text.NoWrap 0297 fontSizeMode: Text.VerticalFit 0298 font.pixelSize: compactRoot.tooSmall ? Kirigami.Theme.defaultFont.pixelSize : Kirigami.Units.iconSizes.roundedIconSize(Kirigami.Units.gridUnit * 2) 0299 minimumPointSize: Kirigami.Theme.smallFont.pointSize 0300 visible: compactRoot.shouldHaveLabel 0301 } 0302 } 0303 } 0304 0305 Kicker.ProcessRunner { 0306 id: processRunner; 0307 } 0308 0309 Plasmoid.contextualActions: [ 0310 PlasmaCore.Action { 0311 text: i18n("Edit Applications…") 0312 icon.name: "kmenuedit" 0313 visible: Plasmoid.immutability !== PlasmaCore.Types.SystemImmutable 0314 onTriggered: processRunner.runMenuEditor() 0315 } 0316 ] 0317 0318 Component.onCompleted: { 0319 if (Plasmoid.hasOwnProperty("activationTogglesExpanded")) { 0320 Plasmoid.activationTogglesExpanded = true 0321 } 0322 } 0323 } // root