| 1 | // Copyright (C) 2016 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
| 3 | |
| 4 | #include "sourcecodeview.h" |
| 5 | |
| 6 | #include <QtCore/QFile> |
| 7 | #include <QtCore/QFileInfo> |
| 8 | #include <QtCore/QTextStream> |
| 9 | |
| 10 | #include <QtGui/QTextCharFormat> |
| 11 | #include <QtGui/QTextBlock> |
| 12 | #include <QtGui/QTextCursor> |
| 13 | |
| 14 | QT_BEGIN_NAMESPACE |
| 15 | |
| 16 | SourceCodeView::SourceCodeView(QWidget *parent) |
| 17 | : QPlainTextEdit(parent), |
| 18 | m_isActive(true), |
| 19 | m_lineNumToLoad(0) |
| 20 | { |
| 21 | setReadOnly(true); |
| 22 | } |
| 23 | |
| 24 | void SourceCodeView::setSourceContext(const QString &fileName, const int lineNum) |
| 25 | { |
| 26 | m_fileToLoad.clear(); |
| 27 | setToolTip(fileName); |
| 28 | |
| 29 | if (fileName.isEmpty()) { |
| 30 | clear(); |
| 31 | m_currentFileName.clear(); |
| 32 | appendHtml(html: tr(s: "<i>Source code not available</i>" )); |
| 33 | return; |
| 34 | } |
| 35 | |
| 36 | if (m_isActive) { |
| 37 | showSourceCode(fileName, lineNum); |
| 38 | } else { |
| 39 | m_fileToLoad = fileName; |
| 40 | m_lineNumToLoad = lineNum; |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | void SourceCodeView::setActivated(bool activated) |
| 45 | { |
| 46 | m_isActive = activated; |
| 47 | if (activated && !m_fileToLoad.isEmpty()) { |
| 48 | showSourceCode(fileName: m_fileToLoad, lineNum: m_lineNumToLoad); |
| 49 | m_fileToLoad.clear(); |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | void SourceCodeView::showSourceCode(const QString &absFileName, const int lineNum) |
| 54 | { |
| 55 | QString fileText = fileHash.value(key: absFileName); |
| 56 | |
| 57 | if (fileText.isNull()) { // File not in hash |
| 58 | m_currentFileName.clear(); |
| 59 | |
| 60 | // Assume fileName is relative to directory |
| 61 | QFile file(absFileName); |
| 62 | |
| 63 | if (!file.exists()) { |
| 64 | clear(); |
| 65 | appendHtml(html: tr(s: "<i>File %1 not available</i>" ).arg(a: absFileName)); |
| 66 | return; |
| 67 | } |
| 68 | if (!file.open(flags: QIODevice::ReadOnly | QIODevice::Text)) { |
| 69 | clear(); |
| 70 | appendHtml(html: tr(s: "<i>File %1 not readable</i>" ).arg(a: absFileName)); |
| 71 | return; |
| 72 | } |
| 73 | fileText = QString::fromUtf8(ba: file.readAll()); |
| 74 | fileHash.insert(key: absFileName, value: fileText); |
| 75 | } |
| 76 | |
| 77 | |
| 78 | if (m_currentFileName != absFileName) { |
| 79 | setPlainText(fileText); |
| 80 | m_currentFileName = absFileName; |
| 81 | } |
| 82 | |
| 83 | QTextCursor cursor = textCursor(); |
| 84 | cursor.setPosition(pos: document()->findBlockByNumber(blockNumber: lineNum - 1).position()); |
| 85 | setTextCursor(cursor); |
| 86 | centerCursor(); |
| 87 | cursor.movePosition(op: QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); |
| 88 | cursor.movePosition(op: QTextCursor::Right, QTextCursor::KeepAnchor); |
| 89 | |
| 90 | QTextEdit::ExtraSelection selectedLine; |
| 91 | selectedLine.cursor = cursor; |
| 92 | |
| 93 | // Define custom color for line selection |
| 94 | const QColor fg = palette().color(cr: QPalette::Highlight); |
| 95 | const QColor bg = palette().color(cr: QPalette::Base); |
| 96 | QColor col; |
| 97 | const qreal ratio = 0.25; |
| 98 | col.setRedF(fg.redF() * ratio + bg.redF() * (1 - ratio)); |
| 99 | col.setGreenF(fg.greenF() * ratio + bg.greenF() * (1 - ratio)); |
| 100 | col.setBlueF(fg.blueF() * ratio + bg.blueF() * (1 - ratio)); |
| 101 | |
| 102 | selectedLine.format.setBackground(col); |
| 103 | selectedLine.format.setProperty(propertyId: QTextFormat::FullWidthSelection, value: true); |
| 104 | setExtraSelections(QList<QTextEdit::ExtraSelection>() << selectedLine); |
| 105 | } |
| 106 | |
| 107 | QT_END_NAMESPACE |
| 108 | |