Warning, /plasma/drkonqi/src/qml/DeveloperPage.qml is written in an unsupported language. File is not indexed.

0001 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0002 // SPDX-FileCopyrightText: 2021-2022 Harald Sitter <sitter@kde.org>
0003 
0004 import QtQuick 2.15
0005 import QtQuick.Layouts 1.15
0006 import QtQuick.Controls 2.15 as QQC2
0007 import org.kde.kirigami 2.19 as Kirigami
0008 import org.kde.syntaxhighlighting 1.0
0009 
0010 import org.kde.drkonqi 1.0
0011 
0012 Kirigami.ScrollablePage {
0013     id: page
0014 
0015     property string trace: ""
0016     property bool basic: false
0017     property alias usefulness: ratingItem.usefulness
0018     property alias footerActionsLeft: footerBarLeft.actions
0019     property alias footerActionsRight: footerBarRight.actions
0020 
0021     padding: 0
0022     bottomPadding: 0
0023 
0024     title: i18nc("@title:window", "Developer Information")
0025     onStateChanged: {
0026         console.log("state")
0027         console.log(state)
0028     }
0029 
0030     mainAction: Kirigami.Action {
0031         id: installButton
0032         visible: false
0033         text: i18nc("@action:button", "Install Debug Symbols")
0034         onTriggered: {
0035             if (debugPackageInstaller.canInstallDebugPackages) { // prefer the installer when available over dynamic resolution
0036                 debugPackageInstaller.installDebugPackages()
0037             } else if (BacktraceGenerator.supportsSymbolResolution) {
0038                 traceArea.text = ""
0039                 BacktraceGenerator.symbolResolution = true
0040                 BacktraceGenerator.start()
0041             } else {
0042                 console.warn("Unexpected install button state :O")
0043             }
0044         }
0045         iconName: "install"
0046         tooltip: i18nc("@info:tooltip", "Use this button to install the missing debug symbols packages.")
0047     }
0048 
0049     contextualActions: [
0050         Kirigami.Action {
0051             id: reloadAction
0052             enabled: BacktraceGenerator.state !== BacktraceGenerator.Loading
0053             iconName: "view-refresh"
0054             text: i18nc("@action:button", "Reload")
0055             tooltip: xi18nc("@info:tooltip",
0056 `Use this button to reload the crash information (backtrace). This is useful when you have
0057 installed the proper debug symbol packages and you want to obtain a better backtrace.`)
0058             onTriggered: {
0059                 traceArea.text = ""
0060                 BacktraceGenerator.start()
0061             }
0062         },
0063 
0064         Kirigami.Action {
0065             iconName: "edit-copy"
0066             text: i18nc("@action:button", "Copy")
0067             tooltip: i18nc("@info:tooltip", "Use this button to copy the crash information (backtrace) to the clipboard.")
0068             onTriggered: DrKonqi.copyToClipboard(traceArea.text)
0069         },
0070 
0071         Kirigami.Action {
0072             iconName: "document-save"
0073             text: i18nc("@action:button", "Save")
0074             tooltip: xi18nc("@info:tooltip",
0075 `Use this button to save the crash information (backtrace) to a file. This is useful if you want to take a look at it or to report the bug later.`)
0076             onTriggered: DrKonqi.saveReport(traceArea.text)
0077         }
0078     ]
0079 
0080     header: QQC2.ToolBar {
0081         RatingItem {
0082             id: ratingItem
0083             anchors.fill: parent
0084             failed: BacktraceGenerator.state === BacktraceGenerator.Failed || BacktraceGenerator.state === BacktraceGenerator.FailedToStart
0085             loading: BacktraceGenerator.state === BacktraceGenerator.Loading
0086         }
0087     }
0088 
0089     ColumnLayout {
0090         DebugPackageInstaller { // not in global scope because it messes up scrollbars
0091             id: debugPackageInstaller
0092             onPackagesInstalled: reloadAction.trigger()
0093             onError: appWindow.showPassiveNotification(i18nc("@title:window", "Error during the installation of debug symbols"), "long")
0094         }
0095 
0096         RowLayout {
0097             visible: page.basic
0098             Layout.fillHeight: true
0099             Kirigami.Icon {
0100                 source: "help-hint"
0101                 width: Kirigami.Units.iconSizes.enormous
0102                 height: width
0103             }
0104             QQC2.Label {
0105                 Layout.fillHeight: true
0106                 Layout.fillWidth: true
0107                 wrapMode: Text.Wrap
0108                 text: xi18nc("@info",
0109 `<subtitle>What is a "backtrace" ?</subtitle><para>A backtrace basically describes what was
0110 happening inside the application when it crashed, so the developers may track
0111 down where the mess started. They may look meaningless to you, but they might
0112 actually contain a wealth of useful information.<nl />Backtraces are commonly
0113 used during interactive and post-mortem debugging.</para>`)
0114             }
0115         }
0116         QQC2.TextArea {
0117             id: traceArea
0118             Layout.fillWidth: true
0119             Layout.fillHeight: true
0120             visible: text !== "" && !page.basic
0121 
0122             // text: output.text
0123             font.family: "monospace"
0124             wrapMode: Text.Wrap
0125             textFormat: TextEdit.PlainText
0126             readOnly: true
0127             selectByMouse: Kirigami.Settings.isMobile ? false : true
0128 
0129             SyntaxHighlighter {
0130                 textEdit:  BacktraceGenerator.debuggerIsGDB() ? traceArea : undefined
0131                 definition: "GDB Backtrace"
0132             }
0133 
0134             Connections {
0135                 id: generatorConnections
0136                 target: BacktraceGenerator
0137                 function onNewLine(line) { traceArea.text += line }
0138                 function onStateChanged() {
0139                     console.log(BacktraceGenerator.state)
0140                     console.log(BacktraceGenerator.Loaded)
0141 
0142                     const state = BacktraceGenerator.state
0143                     page.state = state
0144 
0145                     installButton.visible = false
0146 
0147                     const parser = BacktraceGenerator.parser();
0148                     usefulness = parser.backtraceUsefulness()
0149                     // ratingItem.usefulness = usefulness
0150                     if (state == BacktraceGenerator.Loaded) {
0151                         traceArea.text = BacktraceGenerator.backtrace()
0152                         trace = traceArea.text // FIXME ensure this doesn't result in a binding
0153 
0154                         if (usefulness != BacktraceParser.ReallyUseful) {
0155                             if (debugPackageInstaller.canInstallDebugPackages || BacktraceGenerator.supportsSymbolResolution) {
0156                                 detailsLabel.text = xi18nc("@info/rich",
0157 `You can click the <interface>Install Debug Symbols</interface> button in order to automatically install the missing debugging information packages. If this method
0158 does not work: please read <link url='%1'>How to create useful crash reports</link> to learn how to get a useful
0159 backtrace; install the needed packages (<link url='%2'> list of files</link>) and click the <interface>Reload</interface> button.`,
0160                                                             Globals.techbaseHowtoDoc, '#missingDebugPackages')
0161                                 installButton.visible = true
0162                                 debugPackageInstaller.setMissingLibraries(parser.librariesWithMissingDebugSymbols())
0163                             } else {
0164                                 detailsLabel.text = xi18nc("@info/rich",
0165 `Please read <link url='%1'>How to create useful crash reports</link> to learn how to get a useful backtrace; install the needed packages (<link url='%2'>
0166 list of files</link>) and click the <interface>Reload</interface> button.`,
0167                                                             Globals.techbaseHowtoDoc, '#missingDebugPackages')
0168                             }
0169                         }
0170                     } else if (state == BacktraceGenerator.Failed) {
0171                         traceArea.text = i18nc("@info:status", "The crash information could not be generated.")
0172                         detailsLabel.text = xi18nc("@info/rich", `You could try to regenerate the backtrace by clicking the <interface>Reload</interface> button.`)
0173                     } else if (state == BacktraceGenerator.FailedToStart) {
0174                         // FIXME dupe from failed
0175                         traceArea.text = i18nc("@info:status", "The crash information could not be generated.")
0176                         detailsLabel.text = xi18nc("@info/rich",
0177 `<emphasis strong='true'>You need to first install the debugger application (%1) then click the <interface>Reload</interface> button.</emphasis>`,
0178                                                    BacktraceGenerator.debuggerName())
0179                     }
0180                 }
0181             }
0182         }
0183     }
0184 
0185     footer: ColumnLayout {
0186         QQC2.Control { // Get standard padding so it doesn't stick to the edges, Label has none by default cause it isn't a Control
0187             Layout.fillWidth: true
0188             background: null
0189 
0190             Kirigami.PromptDialog {
0191                 id: filesDialog
0192                 title: i18nc("@title", "Not Sufficiently Useful")
0193                 function reload() {
0194                     const parser = BacktraceGenerator.parser()
0195                     let missingDbgForFiles = parser.librariesWithMissingDebugSymbols()
0196                     missingDbgForFiles.unshift(CrashedApplication.exectuableAbsoluteFilePath)
0197                     // TODO should maybe prepend DrKonqi::crashedApplication()->executable().absoluteFilePath()
0198                     // NB: cannot use xi18nc here because that'd close the html tag but we need to append an unordered list of paths
0199                     let message = "<html>" + i18n("The packages containing debug information for the following application and libraries are missing:") + "<br /><ul>";
0200                     for (const i in missingDbgForFiles) {
0201                         message += "<li>" + missingDbgForFiles[i] + "</li>";
0202                     }
0203                     message += "</ul></html>"
0204                     subtitle = message
0205                 }
0206 
0207                 showCloseButton: true
0208             }
0209 
0210             contentItem: QQC2.Label {
0211                 id: detailsLabel
0212                 wrapMode: Text.Wrap
0213                 onLinkActivated: {
0214                     if (link[0] == "#") { // in-page reference
0215                         filesDialog.reload()
0216                         filesDialog.open()
0217                     } else {
0218                         Qt.openUrlExternally(link)
0219                     }
0220                 }
0221                 textFormat: Text.RichText
0222             }
0223         }
0224         RowLayout {
0225             // Two bars because of https://bugs.kde.org/show_bug.cgi?id=451026
0226             // Awkard though, maybe we should just live with everything being right aligned
0227             FooterActionBar {
0228                 padding: 0
0229                 id: footerBarLeft
0230                 alignment: Qt.AlignLeft
0231                 visible: actions.length > 0
0232             }
0233             FooterActionBar {
0234                 padding: 0
0235                 id: footerBarRight
0236                 visible: actions.length > 0
0237             }
0238         }
0239     }
0240 
0241     Component.onCompleted: {
0242         if (BacktraceGenerator.state === BacktraceGenerator.NotLoaded) {
0243             reloadAction.trigger()
0244         } else {
0245             // ensure our current state is the state of the backend. this is important in case the developer page
0246             // was used before the report workflow (i.e. the data was generated but from a different view)
0247             generatorConnections.onStateChanged()
0248         }
0249     }
0250 }