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