diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS I18n CoreAddons Service ConfigWidgets JobWidgets KIO Crash Completion WidgetsAddons Wallet - Notifications IdleTime WindowSystem) + Notifications IdleTime WindowSystem SyntaxHighlighting) find_package(Qt5X11Extras ${QT_MIN_VERSION} CONFIG) set_package_properties(Qt5X11Extras PROPERTIES TYPE RECOMMENDED PURPOSE "Recommended for better integration on X11.") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,7 +37,6 @@ ptracer.cpp debuggermanager.cpp applicationdetailsexamples.cpp - gdbhighlighter.cpp statusnotifier.cpp ) @@ -104,6 +103,8 @@ KF5::Notifications # for status notifier KF5::IdleTime # hide status notifier only if user saw it + KF5::SyntaxHighlighting # Backtrace Highlighting + drkonqi_backtrace_parser qbugzilla ) diff --git a/src/backtracewidget.h b/src/backtracewidget.h --- a/src/backtracewidget.h +++ b/src/backtracewidget.h @@ -25,7 +25,9 @@ #include "debugpackageinstaller.h" #include "ui_backtracewidget.h" -class QSyntaxHighlighter; +namespace KSyntaxHighlighting { + class SyntaxHighlighter; +} class BacktraceRatingWidget; class BacktraceGenerator; @@ -54,7 +56,7 @@ BacktraceGenerator * m_btGenerator = nullptr; Ui::Form ui; BacktraceRatingWidget * m_backtraceRatingWidget = nullptr; - QSyntaxHighlighter *m_highlighter = nullptr; + KSyntaxHighlighting::SyntaxHighlighter *m_highlighter = nullptr; DebugPackageInstaller * m_debugPackageInstaller = nullptr; void setAsLoading(); diff --git a/src/backtracewidget.cpp b/src/backtracewidget.cpp --- a/src/backtracewidget.cpp +++ b/src/backtracewidget.cpp @@ -21,9 +21,14 @@ #include #include +#include #include #include +#include +#include +#include +#include #include #include "drkonqi.h" @@ -33,7 +38,6 @@ #include "parser/backtraceparser.h" #include "drkonqi_globals.h" #include "debuggermanager.h" -#include "gdbhighlighter.h" static const char extraDetailsLabelMargin[] = " margin: 5px; "; @@ -221,8 +225,14 @@ // highlight if possible if (m_btGenerator->debugger().codeName() == QLatin1String("gdb")) { - m_highlighter = new GdbHighlighter(ui.m_backtraceEdit->document(), - m_btGenerator->parser()->parsedBacktraceLines()); + KSyntaxHighlighting::Repository repository; + m_highlighter = new KSyntaxHighlighting::SyntaxHighlighter(ui.m_backtraceEdit->document()); + m_highlighter->setTheme((palette().color(QPalette::Base).lightness() < 128) + ? repository.defaultTheme(KSyntaxHighlighting::Repository::DarkTheme) + : repository.defaultTheme(KSyntaxHighlighting::Repository::LightTheme)); + + const auto def = repository.definitionForName(QStringLiteral("GDB Backtrace")); + m_highlighter->setDefinition(def); } BacktraceParser * btParser = m_btGenerator->parser(); @@ -322,11 +332,6 @@ void BacktraceWidget::backtraceNewLine(const QString & line) { - // We absolutely must not have a highlighter attached. The highlighter has - // a static list of lines to highlight from. When we are loading lines - // this static list does not match reality breaking text length expectations - // and resulting in segfaults. - Q_ASSERT(!m_highlighter); //While loading the backtrace (unparsed) a new line was sent from the debugger, append it ui.m_backtraceEdit->append(line.trimmed()); } diff --git a/src/gdbhighlighter.h b/src/gdbhighlighter.h deleted file mode 100644 --- a/src/gdbhighlighter.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2010 Milian Wolff - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#ifndef GDBHIGHLIGHTER_H -#define GDBHIGHLIGHTER_H - -#include - -#include "parser/backtraceline.h" - -class GdbHighlighter : public QSyntaxHighlighter -{ -public: - GdbHighlighter(QTextDocument* parent, const QList & gdbLines); - -protected: - void highlightBlock(const QString& text) override; - -private: - QMap lines; - QTextCharFormat crashFormat; - QTextCharFormat nullptrFormat; - QTextCharFormat assertFormat; - QTextCharFormat threadFormat; - QTextCharFormat urlFormat; - QTextCharFormat funcFormat; - QTextCharFormat otheridFormat; - QTextCharFormat crapFormat; -}; - -#endif // GDBHIGHLIGHTER_H diff --git a/src/gdbhighlighter.cpp b/src/gdbhighlighter.cpp deleted file mode 100644 --- a/src/gdbhighlighter.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - Copyright (C) 2010 Milian Wolff - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include "gdbhighlighter.h" - -#include -#include - -#include - -GdbHighlighter::GdbHighlighter(QTextDocument* parent, const QList & gdbLines) - : QSyntaxHighlighter(parent) -{ - // setup line lookup - int l = 0; - foreach(const BacktraceLine& line, gdbLines) { - lines.insert(l, line); - l += line.toString().count(QLatin1Char('\n')); - } - - // setup formats - KColorScheme scheme(QPalette::Active); - - crashFormat.setForeground(scheme.foreground(KColorScheme::NegativeText)); - nullptrFormat.setForeground(scheme.foreground(KColorScheme::NegativeText)); - nullptrFormat.setFontWeight(QFont::Bold); - assertFormat = nullptrFormat; - threadFormat.setForeground(scheme.foreground(KColorScheme::NeutralText)); - urlFormat.setForeground(scheme.foreground(KColorScheme::LinkText)); - funcFormat.setForeground(scheme.foreground(KColorScheme::VisitedText)); - funcFormat.setFontWeight(QFont::Bold); - otheridFormat.setForeground(scheme.foreground(KColorScheme::PositiveText)); - crapFormat.setForeground(scheme.foreground(KColorScheme::InactiveText)); -} - -void GdbHighlighter::highlightBlock(const QString& text) -{ - int cur = 0; - int next; - int diff; - const static QRegularExpression hexptrPattern(QStringLiteral("0x[0-9a-f]+")); - int lineNr = currentBlock().firstLineNumber(); - while ( cur < text.length() ) { - next = text.indexOf(QLatin1Char('\n'), cur); - if (next == -1) { - next = text.length(); - } - if (lineNr == 0) { - // line that contains 'Application: ...' - ++lineNr; - cur = next; - continue; - } - - diff = next - cur; - - const QString lineStr = text.mid(cur, diff).append(QLatin1Char('\n')); - // -1 since we skip the first line - QMap< int, BacktraceLine >::iterator it = lines.lowerBound(lineNr - 1); - Q_ASSERT(it != lines.end()); - // lowerbound would return the next higher item, even though we want the former one - if (it.key() > lineNr - 1) { - --it; - } - const BacktraceLine& line = it.value(); - - if (line.type() == BacktraceLine::KCrash) { - setFormat(cur, diff, crashFormat); - } else if (line.type() == BacktraceLine::ThreadStart || line.type() == BacktraceLine::ThreadIndicator) { - setFormat(cur, diff, threadFormat); - } else if (line.type() == BacktraceLine::Crap) { - setFormat(cur, diff, crapFormat); - } else if (line.type() == BacktraceLine::StackFrame) { - if (!line.fileName().isEmpty()) { - int colonPos = line.fileName().lastIndexOf(QLatin1Char(':')); - setFormat(lineStr.indexOf(line.fileName()), colonPos == -1 ? line.fileName().length() : colonPos, urlFormat); - } - if (!line.libraryName().isEmpty()) { - setFormat(lineStr.indexOf(line.libraryName()), line.libraryName().length(), urlFormat); - } - if (!line.functionName().isEmpty()) { - int idx = lineStr.indexOf(line.functionName()); - if (idx != -1) { - // highlight Id::Id::Id::Func - // Id should have otheridFormat, :: no format and Func funcFormat - int i = idx; - int from = idx; - while (i < idx + line.functionName().length()) { - if (lineStr.at(i) == QLatin1Char(':')) { - setFormat(from, i - from, otheridFormat); - // skip :: - i += 2; - from = i; - continue; - } else if (lineStr.at(i) == QLatin1Char('<') || lineStr.at(i) == QLatin1Char('>')) { - setFormat(from, i - from, otheridFormat); - ++i; - from = i; - continue; - } - ++i; - } - if (line.functionName() == QLatin1String("qFatal") || line.functionName() == QLatin1String("abort") || line.functionName() == QLatin1String("__assert_fail") - || line.functionName() == QLatin1String("*__GI___assert_fail") || line.functionName() == QLatin1String("*__GI_abort")) { - setFormat(from, i - from, assertFormat); - } else { - setFormat(from, i - from, funcFormat); - } - } - } - // highlight hexadecimal ptrs - QRegularExpressionMatchIterator iter = hexptrPattern.globalMatch(lineStr); - while (iter.hasNext()) { - const QRegularExpressionMatch match = iter.next(); - if (match.captured(0) == QLatin1String("0x0")) { - setFormat(match.capturedStart(0), match.capturedLength(0), nullptrFormat); - } - } - } - - cur = next; - ++lineNr; - } -}