Warning, /plasma/discover/discover/qml/DiscoverWindow.qml is written in an unsupported language. File is not indexed.
0001 import QtQuick 2.15 0002 import QtQuick.Layouts 1.15 0003 import QtQuick.Controls 2.14 0004 import QtQml.Models 2.15 0005 import org.kde.discover 2.0 0006 import org.kde.discover.app 1.0 0007 import org.kde.kquickcontrolsaddons 2.0 0008 import org.kde.kirigami 2.19 as Kirigami 0009 import "navigation.js" as Navigation 0010 0011 Kirigami.ApplicationWindow 0012 { 0013 id: window 0014 readonly property string topBrowsingComp: ("qrc:/qml/BrowsingPage.qml") 0015 readonly property string topInstalledComp: ("qrc:/qml/InstalledPage.qml") 0016 readonly property string topSearchComp: ("qrc:/qml/SearchPage.qml") 0017 readonly property string topUpdateComp: ("qrc:/qml/UpdatesPage.qml") 0018 readonly property string topSourcesComp: ("qrc:/qml/SourcesPage.qml") 0019 readonly property string topAboutComp: ("qrc:/qml/AboutPage.qml") 0020 readonly property QtObject stack: window.pageStack 0021 property string currentTopLevel 0022 0023 objectName: "DiscoverMainWindow" 0024 title: leftPage ? leftPage.title : "" 0025 0026 width: app.initialGeometry.width>=10 ? app.initialGeometry.width : Kirigami.Units.gridUnit * 52 0027 height: app.initialGeometry.height>=10 ? app.initialGeometry.height : Math.max(Kirigami.Units.gridUnit * 38, window.globalDrawer.contentHeight) 0028 0029 visible: true 0030 0031 minimumWidth: Kirigami.Units.gridUnit * 17 0032 minimumHeight: Kirigami.Units.gridUnit * 17 0033 0034 pageStack.defaultColumnWidth: Math.max(Kirigami.Units.gridUnit * 25, pageStack.width / 4) 0035 pageStack.globalToolBar.style: Kirigami.Settings.isMobile ? Kirigami.ApplicationHeaderStyle.Titles : Kirigami.ApplicationHeaderStyle.Auto 0036 pageStack.globalToolBar.showNavigationButtons: pageStack.currentIndex == 0 ? Kirigami.ApplicationHeaderStyle.None : Kirigami.ApplicationHeaderStyle.ShowBackButton 0037 pageStack.globalToolBar.canContainHandles: true // mobile handles in header 0038 0039 readonly property var leftPage: window.stack.depth>0 ? window.stack.get(0) : null 0040 0041 Component.onCompleted: { 0042 if (app.isRoot) { 0043 messagesSheet.addMessage(i18n("Running as <em>root</em> is discouraged and unnecessary.")); 0044 } 0045 } 0046 0047 readonly property string describeSources: feedbackLoader.item ? feedbackLoader.item.describeDataSources : "" 0048 Loader { 0049 id: feedbackLoader 0050 source: "Feedback.qml" 0051 } 0052 0053 TopLevelPageData { 0054 id: featuredAction 0055 iconName: "go-home" 0056 text: i18n("&Home") 0057 component: topBrowsingComp 0058 objectName: "discover" 0059 } 0060 0061 TopLevelPageData { 0062 id: searchAction 0063 visible: enabled 0064 enabled: !window.wideScreen 0065 iconName: "search" 0066 text: i18n("&Search") 0067 component: topSearchComp 0068 objectName: "search" 0069 shortcut: StandardKey.Find 0070 } 0071 TopLevelPageData { 0072 id: installedAction 0073 iconName: "view-list-details" 0074 text: i18n("&Installed") 0075 component: topInstalledComp 0076 objectName: "installed" 0077 } 0078 TopLevelPageData { 0079 id: updateAction 0080 iconName: ResourcesModel.updatesCount>0 ? ResourcesModel.hasSecurityUpdates ? "update-high" : "update-low" : "update-none" 0081 text: ResourcesModel.updatesCount<=0 ? (ResourcesModel.isFetching ? i18n("Fetching &updates…") : i18n("&Up to date") ) : i18nc("Update section name", "&Update (%1)", ResourcesModel.updatesCount) 0082 component: topUpdateComp 0083 objectName: "update" 0084 } 0085 TopLevelPageData { 0086 id: aboutAction 0087 iconName: "help-feedback" 0088 text: i18n("&About") 0089 component: topAboutComp 0090 objectName: "about" 0091 shortcut: StandardKey.HelpContents 0092 } 0093 TopLevelPageData { 0094 id: sourcesAction 0095 iconName: "configure" 0096 text: i18n("S&ettings") 0097 component: topSourcesComp 0098 objectName: "sources" 0099 shortcut: StandardKey.Preferences 0100 } 0101 0102 Kirigami.Action { 0103 id: refreshAction 0104 readonly property QtObject action: ResourcesModel.updateAction 0105 text: action.text 0106 icon.name: "view-refresh" 0107 onTriggered: action.trigger() 0108 enabled: action.enabled 0109 // Don't need to show this action in mobile view since you can pull down 0110 // on the view to refresh, and this is the common and expected behavior 0111 //on that platform 0112 visible: window.wideScreen 0113 tooltip: shortcut.nativeText 0114 0115 // Need to define an explicit Shortcut object so we can get its text 0116 // using shortcut.nativeText 0117 shortcut: Shortcut { 0118 sequences: [ StandardKey.Refresh ] 0119 onActivated: refreshAction.trigger() 0120 } 0121 } 0122 0123 Connections { 0124 target: app 0125 function onOpenApplicationInternal(app) { 0126 Navigation.clearStack() 0127 Navigation.openApplication(app) 0128 } 0129 function onListMimeInternal(mime) { 0130 currentTopLevel = topBrowsingComp; 0131 Navigation.openApplicationMime(mime) 0132 } 0133 function onListCategoryInternal(cat) { 0134 currentTopLevel = topBrowsingComp; 0135 Navigation.openCategory(cat, "") 0136 } 0137 0138 function onOpenSearch(search) { 0139 Navigation.clearStack() 0140 Navigation.openApplicationList({search: search}) 0141 } 0142 0143 function onOpenErrorPage(errorMessage, errorExplanation, buttonText, buttonIcon, buttonUrl) { 0144 Navigation.clearStack() 0145 console.warn("Error: " + errorMessage + "\n" + errorExplanation + "\n" + "Please visit " + buttonUrl) 0146 window.stack.push(errorPageComponent, { title: i18n("Error"), errorMessage: errorMessage, errorExplanation: errorExplanation, buttonText: buttonText, buttonIcon: buttonIcon, buttonUrl: buttonUrl }) 0147 } 0148 0149 function onUnableToFind(resid) { 0150 messagesSheet.addMessage(i18n("Unable to find resource: %1", resid)); 0151 Navigation.openHome() 0152 } 0153 } 0154 0155 Connections { 0156 target: ResourcesModel 0157 0158 function onPassiveMessage(message) { 0159 messagesSheet.addMessage(message); 0160 } 0161 } 0162 0163 footer: Loader { 0164 active: !window.wideScreen 0165 visible: active // ensure that no height is used when not loaded 0166 height: item ? item.implicitHeight : 0 0167 sourceComponent: Kirigami.NavigationTabBar { 0168 actions: [ 0169 featuredAction, 0170 searchAction, 0171 installedAction, 0172 updateAction 0173 ] 0174 Component.onCompleted: { 0175 // Exclusivity is already handled by the actions. This prevents BUG:448460 0176 tabGroup.exclusive = false 0177 } 0178 } 0179 } 0180 0181 Component { 0182 id: errorPageComponent 0183 Kirigami.Page { 0184 id: page 0185 property string errorMessage: "" 0186 property string errorExplanation: "" 0187 property string buttonText: "" 0188 property string buttonIcon: "" 0189 property string buttonUrl: "" 0190 readonly property bool isHome: true 0191 function searchFor(text) { 0192 if (text.length === 0) 0193 return; 0194 Navigation.openCategory(null, "") 0195 } 0196 Kirigami.PlaceholderMessage { 0197 anchors.centerIn: parent 0198 width: parent.width - (Kirigami.Units.largeSpacing * 8) 0199 visible: page.errorMessage !== "" 0200 icon.name: "emblem-warning" 0201 text: page.errorMessage 0202 explanation: page.errorExplanation 0203 helpfulAction: Kirigami.Action { 0204 icon.name: page.buttonIcon 0205 text: page.buttonText 0206 onTriggered: { 0207 Qt.openUrlExternally(page.buttonUrl) 0208 } 0209 } 0210 } 0211 } 0212 } 0213 0214 Component { 0215 id: proceedDialog 0216 Kirigami.OverlaySheet { 0217 id: sheet 0218 showCloseButton: false 0219 property QtObject transaction 0220 property alias description: desc.text 0221 property bool acted: false 0222 0223 // No need to add our own ScrollView since OverlaySheet includes 0224 // one automatically. 0225 // But we do need to put the label into a Layout of some sort so we 0226 // can limit the width of the sheet. 0227 contentItem: ColumnLayout { 0228 Label { 0229 id: desc 0230 0231 Layout.fillWidth: true 0232 Layout.maximumWidth: Kirigami.Units.gridUnit * 20 0233 0234 textFormat: Text.StyledText 0235 wrapMode: Text.WordWrap 0236 } 0237 } 0238 0239 footer: RowLayout { 0240 0241 Item { Layout.fillWidth : true } 0242 0243 Button { 0244 text: i18n("Proceed") 0245 icon.name: "dialog-ok" 0246 onClicked: { 0247 transaction.proceed() 0248 sheet.acted = true 0249 sheet.close() 0250 } 0251 Keys.onEnterPressed: clicked() 0252 Keys.onReturnPressed: clicked() 0253 } 0254 0255 Button { 0256 Layout.alignment: Qt.AlignRight 0257 text: i18n("Cancel") 0258 icon.name: "dialog-cancel" 0259 onClicked: { 0260 transaction.cancel() 0261 sheet.acted = true 0262 sheet.close() 0263 } 0264 Keys.onEscapePressed: clicked() 0265 } 0266 } 0267 0268 onSheetOpenChanged: if(!sheetOpen) { 0269 sheet.destroy(1000) 0270 if (!sheet.acted) 0271 transaction.cancel() 0272 } 0273 } 0274 } 0275 0276 Component { 0277 id: distroErrorMessageDialog 0278 Kirigami.OverlaySheet { 0279 id: sheet 0280 property alias message: desc.text 0281 0282 // No need to add our own ScrollView since OverlaySheet includes 0283 // one automatically. 0284 // But we do need to put the label into a Layout of some sort so we 0285 // can limit the width of the sheet. 0286 contentItem: ColumnLayout { 0287 Label { 0288 id: desc 0289 0290 Layout.fillWidth: true 0291 Layout.maximumWidth: Kirigami.Units.gridUnit * 20 0292 0293 textFormat: Text.StyledText 0294 wrapMode: Text.WordWrap 0295 } 0296 0297 RowLayout { 0298 Item { Layout.fillWidth : true } 0299 Button { 0300 icon.name: "tools-report-bug" 0301 text: i18n("Report this issue") 0302 onClicked: { 0303 Qt.openUrlExternally(ResourcesModel.distroBugReportUrl()) 0304 } 0305 } 0306 } 0307 } 0308 0309 onSheetOpenChanged: if(!sheetOpen) { 0310 sheet.destroy(1000) 0311 } 0312 } 0313 } 0314 0315 Kirigami.OverlaySheet { 0316 id: messagesSheet 0317 0318 property bool copyButtonEnabled: true 0319 0320 function addMessage(message: string) { 0321 messages.append({message: message}); 0322 app.restore() 0323 } 0324 0325 title: messages.count > 1 ? i18n("Error %1 of %2", messagesSheetView.currentIndex + 1, messages.count) : i18n("Error") 0326 0327 // No need to add our own ScrollView since OverlaySheet includes 0328 // one automatically. 0329 // But we do need to put the label into a Layout of some sort so we 0330 // can limit the width of the sheet. 0331 contentItem: ColumnLayout { 0332 Item { 0333 Layout.fillWidth: true 0334 Layout.maximumWidth: Kirigami.Units.gridUnit * 20 0335 } 0336 0337 StackLayout { 0338 id: messagesSheetView 0339 0340 Layout.fillWidth: true 0341 Layout.bottomMargin: Kirigami.Units.gridUnit 0342 0343 Repeater { 0344 model: ListModel { 0345 id: messages 0346 0347 onCountChanged: { 0348 messagesSheet.sheetOpen = (count > 0); 0349 0350 if (count > 0 && messagesSheetView.currentIndex === -1) { 0351 messagesSheetView.currentIndex = 0; 0352 } 0353 } 0354 } 0355 0356 delegate: Label { 0357 Layout.fillWidth: true 0358 0359 text: model.message 0360 textFormat: Text.StyledText 0361 wrapMode: Text.WordWrap 0362 } 0363 } 0364 } 0365 0366 RowLayout { 0367 Layout.fillWidth: true 0368 0369 Button { 0370 text: i18nc("@action:button", "Show Previous") 0371 icon.name: "go-previous" 0372 visible: messages.count > 1 0373 enabled: visible && messagesSheetView.currentIndex > 0 0374 0375 onClicked: { 0376 if (messagesSheetView.currentIndex > 0) { 0377 messagesSheetView.currentIndex--; 0378 } 0379 } 0380 } 0381 0382 Button { 0383 text: i18nc("@action:button", "Show Next") 0384 icon.name: "go-next" 0385 visible: messages.count > 1 0386 enabled: visible && messagesSheetView.currentIndex < messages.count - 1 0387 0388 onClicked: { 0389 if (messagesSheetView.currentIndex < messages.count) { 0390 messagesSheetView.currentIndex++; 0391 } 0392 } 0393 } 0394 0395 Item { Layout.fillWidth: true } 0396 0397 Button { 0398 Layout.alignment: Qt.AlignRight 0399 text: i18n("Copy to Clipboard") 0400 icon.name: "edit-copy" 0401 0402 onClicked: { 0403 app.copyTextToClipboard(messages.get(messagesSheetView.currentIndex).message); 0404 } 0405 } 0406 } 0407 } 0408 0409 onSheetOpenChanged: if (!sheetOpen) { 0410 messagesSheetView.currentIndex = -1; 0411 messages.clear(); 0412 } 0413 } 0414 0415 Instantiator { 0416 model: TransactionModel 0417 0418 delegate: Connections { 0419 target: model.transaction ? model.transaction : null 0420 0421 function onProceedRequest(title, description) { 0422 var dialog = proceedDialog.createObject(window, {transaction: transaction, title: title, description: description}) 0423 dialog.open() 0424 app.restore() 0425 } 0426 0427 function onPassiveMessage(message) { 0428 messagesSheet.addMessage(message); 0429 } 0430 0431 function onDistroErrorMessage(message, actions) { 0432 var dialog = distroErrorMessageDialog.createObject(window, {transaction: transaction, title: i18n("Error"), message: message}) 0433 dialog.open() 0434 app.restore() 0435 } 0436 function onWebflowStarted(url) { 0437 var component = Qt.createComponent("WebflowDialog.qml"); 0438 if (component.status == Component.Error) { 0439 Qt.openUrlExternally(url); 0440 console.error("Webflow Error", component.errorString()) 0441 } else if (component.status == Component.Ready) { 0442 const sheet = component.createObject(window, {transaction: transaction, url: url }); 0443 sheet.open() 0444 } 0445 component.destroy(); 0446 } 0447 } 0448 } 0449 0450 PowerManagementInterface { 0451 reason: TransactionModel.mainTransactionText 0452 preventSleep: TransactionModel.count > 0 0453 } 0454 0455 contextDrawer: Kirigami.ContextDrawer {} 0456 0457 globalDrawer: DiscoverDrawer { 0458 wideScreen: window.wideScreen 0459 } 0460 0461 onCurrentTopLevelChanged: { 0462 window.pageStack.clear() 0463 if (currentTopLevel) 0464 window.pageStack.push(currentTopLevel, {}, window.status!==Component.Ready) 0465 globalDrawer.forceSearchFieldFocus(); 0466 } 0467 0468 UnityLauncher { 0469 launcherId: "org.kde.discover.desktop" 0470 progressVisible: TransactionModel.count > 0 0471 progress: TransactionModel.progress 0472 } 0473 }