ui: scope names in snippet titles
* added title for snippets * title displays name of parent scope. * when new TokenLocationFiles are created in the storage they are now returned as shared_ptr to ensure correct linking in the contained data. * Storage::getTokenLocationsForLinesInFile() now always returns pairs of start and end locations. * Adjusted code snippet view to regard the change described above.
This commit is contained in:
@@ -14,19 +14,28 @@
|
||||
color: black;
|
||||
}
|
||||
|
||||
#code_snippet {
|
||||
#code_file #code_snippet #title_label {
|
||||
background-color: rgb(220,220,220);
|
||||
font-family: "Source Code Pro";
|
||||
border-top-right-radius: 10px;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
padding: 4px 12px;
|
||||
}
|
||||
|
||||
#code_area {
|
||||
font-family: "Source Code Pro";
|
||||
font-size: 14px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
#code_snippet #line_number_area {
|
||||
#code_area #line_number_area {
|
||||
background-color: white;
|
||||
font-family: "Source Code Pro";
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#code_snippet #maximize_button {
|
||||
#code_area #maximize_button {
|
||||
border: none;
|
||||
border-image: none;
|
||||
margin: 5px;
|
||||
@@ -34,7 +43,7 @@
|
||||
max-width: 16px;
|
||||
}
|
||||
|
||||
#code_snippet #maximize_button:enabled {
|
||||
#code_area #maximize_button:enabled {
|
||||
border-image: url(data/gui/code_view/images/button_maximize.png);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ add_files(
|
||||
|
||||
qt/element/QtAutocompletionList.cpp
|
||||
qt/element/QtAutocompletionList.h
|
||||
qt/element/QtCodeArea.cpp
|
||||
qt/element/QtCodeArea.h
|
||||
qt/element/QtCodeFile.cpp
|
||||
qt/element/QtCodeFile.h
|
||||
qt/element/QtCodeFileList.cpp
|
||||
|
||||
@@ -0,0 +1,438 @@
|
||||
#include "qt/element/QtCodeArea.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPainter>
|
||||
#include <QPushButton>
|
||||
#include <QToolTip>
|
||||
|
||||
#include "utility/messaging/type/MessageActivateTokenLocation.h"
|
||||
#include "utility/messaging/type/MessageShowFile.h"
|
||||
|
||||
#include "data/location/TokenLocation.h"
|
||||
#include "data/location/TokenLocationFile.h"
|
||||
#include "qt/element/QtCodeFile.h"
|
||||
#include "qt/utility/QtHighlighter.h"
|
||||
#include "settings/ApplicationSettings.h"
|
||||
|
||||
QtCodeArea::LineNumberArea::LineNumberArea(QtCodeArea *codeArea)
|
||||
: QWidget(codeArea)
|
||||
, m_codeArea(codeArea)
|
||||
{
|
||||
setObjectName("line_number_area");
|
||||
}
|
||||
|
||||
QtCodeArea::LineNumberArea::~LineNumberArea()
|
||||
{
|
||||
}
|
||||
|
||||
QSize QtCodeArea::LineNumberArea::sizeHint() const
|
||||
{
|
||||
return QSize(m_codeArea->lineNumberAreaWidth(), 0);
|
||||
}
|
||||
|
||||
void QtCodeArea::LineNumberArea::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
m_codeArea->lineNumberAreaPaintEvent(event);
|
||||
}
|
||||
|
||||
|
||||
QtCodeArea::QtCodeArea(
|
||||
uint startLineNumber,
|
||||
const std::string& code,
|
||||
std::shared_ptr<TokenLocationFile> locationFile,
|
||||
QtCodeFile* parent
|
||||
)
|
||||
: QPlainTextEdit(parent)
|
||||
, m_parent(parent)
|
||||
, m_maximizeButton(nullptr)
|
||||
, m_startLineNumber(startLineNumber)
|
||||
, m_hoveredAnnotation(nullptr)
|
||||
, m_digits(0)
|
||||
{
|
||||
setObjectName("code_area");
|
||||
setReadOnly(true);
|
||||
setFrameStyle(QFrame::NoFrame);
|
||||
setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setLineWrapMode(QPlainTextEdit::NoWrap);
|
||||
|
||||
m_lineNumberArea = new LineNumberArea(this);
|
||||
m_highlighter = new QtHighlighter(document());
|
||||
|
||||
std::string displayCode = code;
|
||||
if (*code.rbegin() == '\n')
|
||||
{
|
||||
displayCode.pop_back();
|
||||
}
|
||||
|
||||
setPlainText(QString::fromUtf8(displayCode.c_str()));
|
||||
createAnnotations(locationFile);
|
||||
annotateText();
|
||||
|
||||
m_digits = lineNumberDigits();
|
||||
updateLineNumberAreaWidth(0);
|
||||
|
||||
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
|
||||
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
|
||||
connect(this, SIGNAL(selectionChanged()), this, SLOT(clearSelection()));
|
||||
|
||||
this->setMouseTracking(true);
|
||||
}
|
||||
|
||||
QtCodeArea::~QtCodeArea()
|
||||
{
|
||||
}
|
||||
|
||||
QSize QtCodeArea::sizeHint() const
|
||||
{
|
||||
int width = 480;
|
||||
int height = (document()->size().height() + 0.7f) * fontMetrics().lineSpacing();
|
||||
return QSize(width, height);
|
||||
}
|
||||
|
||||
void QtCodeArea::addMaximizeButton()
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout();
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(layout);
|
||||
|
||||
m_maximizeButton = new QPushButton(this);
|
||||
m_maximizeButton->setObjectName("maximize_button");
|
||||
m_maximizeButton->setEnabled(false);
|
||||
layout->addWidget(m_maximizeButton);
|
||||
layout->setAlignment(m_maximizeButton, Qt::AlignRight);
|
||||
|
||||
connect(m_maximizeButton, SIGNAL(clicked()), this, SLOT(clickedMaximizeButton()));
|
||||
}
|
||||
|
||||
void QtCodeArea::lineNumberAreaPaintEvent(QPaintEvent *event)
|
||||
{
|
||||
QPainter painter(m_lineNumberArea);
|
||||
|
||||
QTextBlock block = firstVisibleBlock();
|
||||
int blockNumber = block.blockNumber();
|
||||
int top = static_cast<int>(blockBoundingGeometry(block).translated(contentOffset()).top());
|
||||
int bottom = top + static_cast<int>(blockBoundingRect(block).height());
|
||||
|
||||
while (block.isValid() && top <= event->rect().bottom())
|
||||
{
|
||||
if (block.isVisible() && bottom >= event->rect().top())
|
||||
{
|
||||
QString number = QString::number(blockNumber + m_startLineNumber);
|
||||
painter.setPen(Qt::black);
|
||||
painter.drawText(0, top, m_lineNumberArea->width() - 13, fontMetrics().height(), Qt::AlignRight, number);
|
||||
}
|
||||
|
||||
block = block.next();
|
||||
top = bottom;
|
||||
bottom = top + static_cast<int>(blockBoundingRect(block).height());
|
||||
blockNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
int QtCodeArea::lineNumberDigits() const
|
||||
{
|
||||
int digits = 1;
|
||||
int max = qMax(1, int(m_startLineNumber) + blockCount());
|
||||
|
||||
while (max >= 10)
|
||||
{
|
||||
max /= 10;
|
||||
digits++;
|
||||
}
|
||||
return digits;
|
||||
}
|
||||
|
||||
int QtCodeArea::lineNumberAreaWidth() const
|
||||
{
|
||||
return fontMetrics().width(QLatin1Char('9')) * m_digits + 30;
|
||||
}
|
||||
|
||||
void QtCodeArea::updateLineNumberAreaWidthForDigits(int digits)
|
||||
{
|
||||
m_digits = digits;
|
||||
updateLineNumberAreaWidth(0);
|
||||
}
|
||||
|
||||
void QtCodeArea::update()
|
||||
{
|
||||
annotateText();
|
||||
}
|
||||
|
||||
void QtCodeArea::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
QPlainTextEdit::resizeEvent(e);
|
||||
|
||||
QRect cr = contentsRect();
|
||||
m_lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
|
||||
}
|
||||
|
||||
void QtCodeArea::showEvent(QShowEvent* event)
|
||||
{
|
||||
int tabWidth = ApplicationSettings::getInstance()->getCodeTabWidth();
|
||||
setTabStopWidth(tabWidth * fontMetrics().width('9'));
|
||||
|
||||
setMaximumHeight(sizeHint().height());
|
||||
}
|
||||
|
||||
void QtCodeArea::enterEvent(QEvent* event)
|
||||
{
|
||||
if (m_maximizeButton)
|
||||
{
|
||||
m_maximizeButton->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeArea::leaveEvent(QEvent* event)
|
||||
{
|
||||
if (m_maximizeButton)
|
||||
{
|
||||
m_maximizeButton->setEnabled(false);
|
||||
}
|
||||
|
||||
m_hoveredAnnotation = nullptr;
|
||||
annotateText();
|
||||
}
|
||||
|
||||
void QtCodeArea::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
QTextCursor cursor = this->cursorForPosition(event->pos());
|
||||
const Annotation* annotation = findAnnotationForPosition(cursor.position());
|
||||
|
||||
if (annotation)
|
||||
{
|
||||
MessageActivateTokenLocation(annotation->locationId).dispatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeArea::mouseDoubleClickEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton && m_maximizeButton)
|
||||
{
|
||||
clickedMaximizeButton();
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeArea::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
QTextCursor cursor = this->cursorForPosition(event->pos());
|
||||
const Annotation* annotation = findAnnotationForPosition(cursor.position());
|
||||
|
||||
if (annotation && annotation->isScope)
|
||||
{
|
||||
annotation = nullptr;
|
||||
}
|
||||
|
||||
if (annotation != m_hoveredAnnotation)
|
||||
{
|
||||
m_hoveredAnnotation = annotation;
|
||||
|
||||
const std::vector<std::string>& errorMessages = m_parent->getErrorMessages();
|
||||
|
||||
if (annotation && errorMessages.size() > annotation->tokenId)
|
||||
{
|
||||
QToolTip::showText(event->globalPos(), QString::fromStdString(m_parent->getErrorMessages()[annotation->tokenId]));
|
||||
}
|
||||
else
|
||||
{
|
||||
QToolTip::hideText();
|
||||
}
|
||||
|
||||
annotateText();
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeArea::updateLineNumberAreaWidth(int /* newBlockCount */)
|
||||
{
|
||||
setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
|
||||
}
|
||||
|
||||
void QtCodeArea::updateLineNumberArea(const QRect &rect, int dy)
|
||||
{
|
||||
if (dy)
|
||||
{
|
||||
m_lineNumberArea->scroll(0, dy);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lineNumberArea->update(0, rect.y(), m_lineNumberArea->width(), rect.height());
|
||||
}
|
||||
|
||||
if (rect.contains(viewport()->rect()))
|
||||
{
|
||||
updateLineNumberAreaWidth(0);
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeArea::clickedMaximizeButton()
|
||||
{
|
||||
MessageShowFile(m_parent->getFilePath().absoluteStr(), m_startLineNumber, m_startLineNumber + blockCount() - 1).dispatch();
|
||||
}
|
||||
|
||||
void QtCodeArea::clearSelection()
|
||||
{
|
||||
QTextCursor cursor = textCursor();
|
||||
cursor.clearSelection();
|
||||
setTextCursor(cursor);
|
||||
}
|
||||
|
||||
const QtCodeArea::Annotation* QtCodeArea::findAnnotationForPosition(int pos) const
|
||||
{
|
||||
const Annotation* annotationPtr = nullptr;
|
||||
int diff = endTextEditPosition() + 1;
|
||||
|
||||
for (const Annotation& annotation : m_annotations)
|
||||
{
|
||||
if (pos >= annotation.start && pos <= annotation.end)
|
||||
{
|
||||
int d = annotation.end - annotation.start;
|
||||
if (d < diff)
|
||||
{
|
||||
diff = d;
|
||||
annotationPtr = &annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return annotationPtr;
|
||||
}
|
||||
|
||||
void QtCodeArea::createAnnotations(std::shared_ptr<TokenLocationFile> locationFile)
|
||||
{
|
||||
locationFile->forEachStartTokenLocation(
|
||||
[&](TokenLocation* startLocation)
|
||||
{
|
||||
Annotation annotation;
|
||||
int endLineNumber = m_startLineNumber + blockCount() - 1;
|
||||
if (startLocation->getLineNumber() <= endLineNumber)
|
||||
{
|
||||
if (startLocation->getLineNumber() < m_startLineNumber)
|
||||
{
|
||||
annotation.start = startTextEditPosition();
|
||||
}
|
||||
else
|
||||
{
|
||||
annotation.start = toTextEditPosition(startLocation->getLineNumber(), startLocation->getColumnNumber() - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TokenLocation* endLocation = startLocation->getEndTokenLocation();
|
||||
if (endLocation->getLineNumber() >= m_startLineNumber)
|
||||
{
|
||||
if (endLocation->getLineNumber() > endLineNumber)
|
||||
{
|
||||
annotation.end = endTextEditPosition();
|
||||
}
|
||||
else
|
||||
{
|
||||
annotation.end = toTextEditPosition(endLocation->getLineNumber(), endLocation->getColumnNumber());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
annotation.tokenId = startLocation->getTokenId();
|
||||
annotation.locationId = startLocation->getId();
|
||||
annotation.isScope = (startLocation->getType() == TokenLocation::LOCATION_SCOPE);
|
||||
m_annotations.push_back(annotation);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void QtCodeArea::annotateText()
|
||||
{
|
||||
Colori color;
|
||||
const std::vector<Id>& ids = m_parent->getActiveTokenIds();
|
||||
const std::vector<std::string>& errorMessages = m_parent->getErrorMessages();
|
||||
QList<QTextEdit::ExtraSelection> extraSelections;
|
||||
|
||||
for (const Annotation& annotation: m_annotations)
|
||||
{
|
||||
bool isActive = std::find(ids.begin(), ids.end(), annotation.tokenId) != ids.end();
|
||||
|
||||
if (&annotation == m_hoveredAnnotation && errorMessages.size())
|
||||
{
|
||||
color = Colori(255, 0, 0, 128);
|
||||
}
|
||||
else if (&annotation == m_hoveredAnnotation)
|
||||
{
|
||||
color = ApplicationSettings::getInstance()->getCodeActiveLinkColor();
|
||||
}
|
||||
else if (errorMessages.size())
|
||||
{
|
||||
color = Colori(255, 0, 0, 255);
|
||||
}
|
||||
else if (isActive)
|
||||
{
|
||||
color = ApplicationSettings::getInstance()->getCodeActiveLinkColor();
|
||||
|
||||
if (annotation.isScope)
|
||||
{
|
||||
color.a /= 2;
|
||||
}
|
||||
}
|
||||
else if (annotation.isScope)
|
||||
{
|
||||
color = ApplicationSettings::getInstance()->getCodeScopeColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
color = ApplicationSettings::getInstance()->getCodeLinkColor();
|
||||
}
|
||||
|
||||
QTextEdit::ExtraSelection selection;
|
||||
selection.format.setBackground(QColor(color.r, color.g, color.b, color.a));
|
||||
|
||||
selection.cursor = textCursor();
|
||||
selection.cursor.clearSelection();
|
||||
selection.cursor.setPosition(annotation.start);
|
||||
selection.cursor.setPosition(annotation.end, QTextCursor::KeepAnchor);
|
||||
|
||||
extraSelections.append(selection);
|
||||
}
|
||||
|
||||
setExtraSelections(extraSelections);
|
||||
}
|
||||
|
||||
int QtCodeArea::toTextEditPosition(int lineNumber, int columnNumber) const
|
||||
{
|
||||
lineNumber -= m_startLineNumber - 1;
|
||||
int position = 0;
|
||||
|
||||
for (int i = 0; i < lineNumber - 1; i++)
|
||||
{
|
||||
position += document()->findBlockByLineNumber(i).length();
|
||||
}
|
||||
|
||||
position += columnNumber;
|
||||
return position;
|
||||
}
|
||||
|
||||
int QtCodeArea::startTextEditPosition() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QtCodeArea::endTextEditPosition() const
|
||||
{
|
||||
int position = 0;
|
||||
|
||||
for (int i = 0; i < document()->blockCount(); i++)
|
||||
{
|
||||
position += document()->findBlockByLineNumber(i).length();
|
||||
}
|
||||
|
||||
return position - 1;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
#ifndef QT_CODE_AREA_H
|
||||
#define QT_CODE_AREA_H
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
#include "utility/types.h"
|
||||
|
||||
class QPaintEvent;
|
||||
class QPushButton;
|
||||
class QResizeEvent;
|
||||
class QSize;
|
||||
class QtCodeFile;
|
||||
class QtHighlighter;
|
||||
class QWidget;
|
||||
class TokenLocation;
|
||||
class TokenLocationFile;
|
||||
|
||||
class QtCodeArea: public QPlainTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
class LineNumberArea: public QWidget
|
||||
{
|
||||
public:
|
||||
LineNumberArea(QtCodeArea *codeArea);
|
||||
virtual ~LineNumberArea();
|
||||
|
||||
QSize sizeHint() const;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event);
|
||||
|
||||
private:
|
||||
QtCodeArea *m_codeArea;
|
||||
};
|
||||
|
||||
QtCodeArea(
|
||||
uint startLineNumber,
|
||||
const std::string& code,
|
||||
std::shared_ptr<TokenLocationFile> locationFile,
|
||||
QtCodeFile* parent
|
||||
);
|
||||
virtual ~QtCodeArea();
|
||||
|
||||
QSize sizeHint() const;
|
||||
|
||||
void addMaximizeButton();
|
||||
|
||||
void lineNumberAreaPaintEvent(QPaintEvent *event);
|
||||
int lineNumberDigits() const;
|
||||
int lineNumberAreaWidth() const;
|
||||
void updateLineNumberAreaWidthForDigits(int digits);
|
||||
|
||||
void update();
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *event);
|
||||
virtual void showEvent(QShowEvent* event);
|
||||
virtual void enterEvent(QEvent* event);
|
||||
virtual void leaveEvent(QEvent* event);
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event);
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent* event);
|
||||
virtual void mouseMoveEvent(QMouseEvent* event);
|
||||
|
||||
private slots:
|
||||
void updateLineNumberAreaWidth(int newBlockCount);
|
||||
void updateLineNumberArea(const QRect &, int);
|
||||
void clickedMaximizeButton();
|
||||
void clearSelection();
|
||||
|
||||
private:
|
||||
struct Annotation
|
||||
{
|
||||
int start;
|
||||
int end;
|
||||
Id tokenId;
|
||||
Id locationId;
|
||||
bool isScope;
|
||||
};
|
||||
|
||||
const Annotation* findAnnotationForPosition(int pos) const;
|
||||
void createAnnotations(std::shared_ptr<TokenLocationFile> locationFile);
|
||||
void annotateText();
|
||||
|
||||
bool locationBelongsToSnippet(TokenLocation* location) const;
|
||||
|
||||
int toTextEditPosition(int lineNumber, int columnNumber) const;
|
||||
int startTextEditPosition() const;
|
||||
int endTextEditPosition() const;
|
||||
|
||||
QtCodeFile* m_parent;
|
||||
|
||||
QWidget* m_lineNumberArea;
|
||||
QtHighlighter* m_highlighter;
|
||||
|
||||
QPushButton* m_maximizeButton;
|
||||
|
||||
const uint m_startLineNumber;
|
||||
|
||||
std::vector<Annotation> m_annotations;
|
||||
const Annotation* m_hoveredAnnotation;
|
||||
|
||||
int m_digits;
|
||||
};
|
||||
|
||||
#endif // QT_CODE_AREA_H
|
||||
@@ -61,11 +61,12 @@ const std::vector<std::string>& QtCodeFile::getErrorMessages() const
|
||||
|
||||
void QtCodeFile::addCodeSnippet(
|
||||
uint startLineNumber,
|
||||
const std::string& title,
|
||||
const std::string& code,
|
||||
const TokenLocationFile& locationFile
|
||||
std::shared_ptr<TokenLocationFile> locationFile
|
||||
){
|
||||
std::shared_ptr<QtCodeSnippet> snippet(
|
||||
new QtCodeSnippet(startLineNumber, code, locationFile, this));
|
||||
new QtCodeSnippet(startLineNumber, title, code, locationFile, this));
|
||||
|
||||
if (m_parent->getShowMaximizeButton())
|
||||
{
|
||||
|
||||
@@ -31,8 +31,9 @@ public:
|
||||
|
||||
void addCodeSnippet(
|
||||
uint startLineNumber,
|
||||
const std::string& title,
|
||||
const std::string& code,
|
||||
const TokenLocationFile& locationFile
|
||||
std::shared_ptr<TokenLocationFile> locationFile
|
||||
);
|
||||
|
||||
void update();
|
||||
|
||||
@@ -36,10 +36,11 @@ QSize QtCodeFileList::sizeHint() const
|
||||
|
||||
void QtCodeFileList::addCodeSnippet(
|
||||
uint startLineNumber,
|
||||
const std::string& title,
|
||||
const std::string& code,
|
||||
const TokenLocationFile& locationFile
|
||||
std::shared_ptr<TokenLocationFile> locationFile
|
||||
){
|
||||
FilePath filePath = locationFile.getFilePath();
|
||||
FilePath filePath = locationFile->getFilePath();
|
||||
QtCodeFile* file = nullptr;
|
||||
|
||||
for (std::shared_ptr<QtCodeFile> filePtr : m_files)
|
||||
@@ -53,14 +54,14 @@ void QtCodeFileList::addCodeSnippet(
|
||||
|
||||
if (!file)
|
||||
{
|
||||
std::shared_ptr<QtCodeFile> filePtr = std::make_shared<QtCodeFile>(locationFile.getFilePath(), this);
|
||||
std::shared_ptr<QtCodeFile> filePtr = std::make_shared<QtCodeFile>(locationFile->getFilePath(), this);
|
||||
m_files.push_back(filePtr);
|
||||
|
||||
file = filePtr.get();
|
||||
m_frame->layout()->addWidget(file);
|
||||
}
|
||||
|
||||
file->addCodeSnippet(startLineNumber, code, locationFile);
|
||||
file->addCodeSnippet(startLineNumber, title, code, locationFile);
|
||||
}
|
||||
|
||||
void QtCodeFileList::clearCodeSnippets()
|
||||
|
||||
@@ -24,8 +24,9 @@ public:
|
||||
|
||||
void addCodeSnippet(
|
||||
uint startLineNumber,
|
||||
const std::string& title,
|
||||
const std::string& code,
|
||||
const TokenLocationFile& locationFile
|
||||
std::shared_ptr<TokenLocationFile> locationFile
|
||||
);
|
||||
|
||||
void clearCodeSnippets();
|
||||
|
||||
@@ -1,466 +1,59 @@
|
||||
#include "qt/element/QtCodeSnippet.h"
|
||||
|
||||
#include <QFont>
|
||||
#include <QHBoxLayout>
|
||||
#include <QPainter>
|
||||
#include <QPushButton>
|
||||
#include <QToolTip>
|
||||
|
||||
#include "utility/messaging/type/MessageActivateTokenLocation.h"
|
||||
#include "utility/messaging/type/MessageShowFile.h"
|
||||
|
||||
#include "data/location/TokenLocation.h"
|
||||
#include "data/location/TokenLocationFile.h"
|
||||
#include "qt/element/QtCodeFile.h"
|
||||
#include "qt/utility/QtHighlighter.h"
|
||||
#include "settings/ApplicationSettings.h"
|
||||
|
||||
QtCodeSnippet::LineNumberArea::LineNumberArea(QtCodeSnippet *codeSnippet)
|
||||
: QWidget(codeSnippet)
|
||||
, m_codeSnippet(codeSnippet)
|
||||
{
|
||||
setObjectName("line_number_area");
|
||||
}
|
||||
|
||||
QtCodeSnippet::LineNumberArea::~LineNumberArea()
|
||||
{
|
||||
}
|
||||
|
||||
QSize QtCodeSnippet::LineNumberArea::sizeHint() const
|
||||
{
|
||||
return QSize(m_codeSnippet->lineNumberAreaWidth(), 0);
|
||||
}
|
||||
|
||||
void QtCodeSnippet::LineNumberArea::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
m_codeSnippet->lineNumberAreaPaintEvent(event);
|
||||
}
|
||||
|
||||
|
||||
QtCodeSnippet::QtCodeSnippet(
|
||||
uint startLineNumber,
|
||||
const std::string& title,
|
||||
const std::string& code,
|
||||
const TokenLocationFile& locationFile,
|
||||
std::shared_ptr<TokenLocationFile> locationFile,
|
||||
QtCodeFile* parent
|
||||
)
|
||||
: QPlainTextEdit(parent)
|
||||
: QWidget(parent)
|
||||
, m_parent(parent)
|
||||
, m_maximizeButton(nullptr)
|
||||
, m_startLineNumber(startLineNumber)
|
||||
, m_hoveredAnnotation(nullptr)
|
||||
, m_digits(0)
|
||||
, m_codeArea(std::make_shared<QtCodeArea>(startLineNumber, code, locationFile, parent))
|
||||
{
|
||||
setObjectName("code_snippet");
|
||||
setReadOnly(true);
|
||||
setFrameStyle(QFrame::NoFrame);
|
||||
setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setLineWrapMode(QPlainTextEdit::NoWrap);
|
||||
|
||||
m_lineNumberArea = new LineNumberArea(this);
|
||||
m_highlighter = new QtHighlighter(document());
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(layout);
|
||||
|
||||
std::string displayCode = code;
|
||||
if (*code.rbegin() == '\n')
|
||||
{
|
||||
displayCode.pop_back();
|
||||
}
|
||||
m_title = new QPushButton(title.c_str(), this);
|
||||
m_title->setObjectName("title_label");
|
||||
m_title->minimumSizeHint(); // force font loading
|
||||
m_title->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
|
||||
m_title->setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
|
||||
layout->addWidget(m_title);
|
||||
|
||||
setPlainText(QString::fromUtf8(displayCode.c_str()));
|
||||
createAnnotations(locationFile);
|
||||
annotateText();
|
||||
|
||||
m_digits = lineNumberDigits();
|
||||
updateLineNumberAreaWidth(0);
|
||||
|
||||
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
|
||||
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
|
||||
connect(this, SIGNAL(selectionChanged()), this, SLOT(clearSelection()));
|
||||
|
||||
this->setMouseTracking(true);
|
||||
layout->addWidget(m_codeArea.get());
|
||||
}
|
||||
|
||||
QtCodeSnippet::~QtCodeSnippet()
|
||||
{
|
||||
}
|
||||
|
||||
QSize QtCodeSnippet::sizeHint() const
|
||||
{
|
||||
int width = 480;
|
||||
int height = (document()->size().height() + 0.7f) * fontMetrics().lineSpacing();
|
||||
return QSize(width, height);
|
||||
}
|
||||
|
||||
void QtCodeSnippet::addMaximizeButton()
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout();
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(layout);
|
||||
|
||||
m_maximizeButton = new QPushButton(this);
|
||||
m_maximizeButton->setObjectName("maximize_button");
|
||||
m_maximizeButton->setEnabled(false);
|
||||
layout->addWidget(m_maximizeButton);
|
||||
layout->setAlignment(m_maximizeButton, Qt::AlignRight);
|
||||
|
||||
connect(m_maximizeButton, SIGNAL(clicked()), this, SLOT(clickedMaximizeButton()));
|
||||
}
|
||||
|
||||
void QtCodeSnippet::lineNumberAreaPaintEvent(QPaintEvent *event)
|
||||
{
|
||||
QPainter painter(m_lineNumberArea);
|
||||
|
||||
QTextBlock block = firstVisibleBlock();
|
||||
int blockNumber = block.blockNumber();
|
||||
int top = static_cast<int>(blockBoundingGeometry(block).translated(contentOffset()).top());
|
||||
int bottom = top + static_cast<int>(blockBoundingRect(block).height());
|
||||
|
||||
while (block.isValid() && top <= event->rect().bottom())
|
||||
{
|
||||
if (block.isVisible() && bottom >= event->rect().top())
|
||||
{
|
||||
QString number = QString::number(blockNumber + m_startLineNumber);
|
||||
painter.setPen(Qt::black);
|
||||
painter.drawText(0, top, m_lineNumberArea->width() - 13, fontMetrics().height(), Qt::AlignRight, number);
|
||||
}
|
||||
|
||||
block = block.next();
|
||||
top = bottom;
|
||||
bottom = top + static_cast<int>(blockBoundingRect(block).height());
|
||||
blockNumber++;
|
||||
}
|
||||
m_codeArea->addMaximizeButton();
|
||||
}
|
||||
|
||||
int QtCodeSnippet::lineNumberDigits() const
|
||||
{
|
||||
int digits = 1;
|
||||
int max = qMax(1, int(m_startLineNumber) + blockCount());
|
||||
|
||||
while (max >= 10)
|
||||
{
|
||||
max /= 10;
|
||||
digits++;
|
||||
}
|
||||
return digits;
|
||||
}
|
||||
|
||||
int QtCodeSnippet::lineNumberAreaWidth() const
|
||||
{
|
||||
return fontMetrics().width(QLatin1Char('9')) * m_digits + 30;
|
||||
return m_codeArea->lineNumberDigits();
|
||||
}
|
||||
|
||||
void QtCodeSnippet::updateLineNumberAreaWidthForDigits(int digits)
|
||||
{
|
||||
m_digits = digits;
|
||||
updateLineNumberAreaWidth(0);
|
||||
m_codeArea->updateLineNumberAreaWidthForDigits(digits);
|
||||
}
|
||||
|
||||
void QtCodeSnippet::update()
|
||||
{
|
||||
annotateText();
|
||||
}
|
||||
|
||||
void QtCodeSnippet::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
QPlainTextEdit::resizeEvent(e);
|
||||
|
||||
QRect cr = contentsRect();
|
||||
m_lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
|
||||
}
|
||||
|
||||
void QtCodeSnippet::showEvent(QShowEvent* event)
|
||||
{
|
||||
int tabWidth = ApplicationSettings::getInstance()->getCodeTabWidth();
|
||||
setTabStopWidth(tabWidth * fontMetrics().width('9'));
|
||||
|
||||
setMaximumHeight(sizeHint().height());
|
||||
}
|
||||
|
||||
void QtCodeSnippet::enterEvent(QEvent* event)
|
||||
{
|
||||
if (m_maximizeButton)
|
||||
{
|
||||
m_maximizeButton->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeSnippet::leaveEvent(QEvent* event)
|
||||
{
|
||||
if (m_maximizeButton)
|
||||
{
|
||||
m_maximizeButton->setEnabled(false);
|
||||
}
|
||||
|
||||
m_hoveredAnnotation = nullptr;
|
||||
annotateText();
|
||||
}
|
||||
|
||||
void QtCodeSnippet::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
QTextCursor cursor = this->cursorForPosition(event->pos());
|
||||
const Annotation* annotation = findAnnotationForPosition(cursor.position());
|
||||
|
||||
if (annotation)
|
||||
{
|
||||
MessageActivateTokenLocation(annotation->locationId).dispatch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeSnippet::mouseDoubleClickEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton && m_maximizeButton)
|
||||
{
|
||||
clickedMaximizeButton();
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeSnippet::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
QTextCursor cursor = this->cursorForPosition(event->pos());
|
||||
const Annotation* annotation = findAnnotationForPosition(cursor.position());
|
||||
|
||||
if (annotation && annotation->isScope)
|
||||
{
|
||||
annotation = nullptr;
|
||||
}
|
||||
|
||||
if (annotation != m_hoveredAnnotation)
|
||||
{
|
||||
m_hoveredAnnotation = annotation;
|
||||
|
||||
const std::vector<std::string>& errorMessages = m_parent->getErrorMessages();
|
||||
|
||||
if (annotation && errorMessages.size() > annotation->tokenId)
|
||||
{
|
||||
QToolTip::showText(event->globalPos(), QString::fromStdString(m_parent->getErrorMessages()[annotation->tokenId]));
|
||||
}
|
||||
else
|
||||
{
|
||||
QToolTip::hideText();
|
||||
}
|
||||
|
||||
annotateText();
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeSnippet::updateLineNumberAreaWidth(int /* newBlockCount */)
|
||||
{
|
||||
setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
|
||||
}
|
||||
|
||||
void QtCodeSnippet::updateLineNumberArea(const QRect &rect, int dy)
|
||||
{
|
||||
if (dy)
|
||||
{
|
||||
m_lineNumberArea->scroll(0, dy);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lineNumberArea->update(0, rect.y(), m_lineNumberArea->width(), rect.height());
|
||||
}
|
||||
|
||||
if (rect.contains(viewport()->rect()))
|
||||
{
|
||||
updateLineNumberAreaWidth(0);
|
||||
}
|
||||
}
|
||||
|
||||
void QtCodeSnippet::clickedMaximizeButton()
|
||||
{
|
||||
MessageShowFile(m_parent->getFilePath().absoluteStr(), m_startLineNumber, m_startLineNumber + blockCount() - 1).dispatch();
|
||||
}
|
||||
|
||||
void QtCodeSnippet::clearSelection()
|
||||
{
|
||||
QTextCursor cursor = textCursor();
|
||||
cursor.clearSelection();
|
||||
setTextCursor(cursor);
|
||||
}
|
||||
|
||||
const QtCodeSnippet::Annotation* QtCodeSnippet::findAnnotationForPosition(int pos) const
|
||||
{
|
||||
const Annotation* annotationPtr = nullptr;
|
||||
int diff = endTextEditPosition() + 1;
|
||||
|
||||
for (const Annotation& annotation : m_annotations)
|
||||
{
|
||||
if (pos >= annotation.start && pos <= annotation.end)
|
||||
{
|
||||
int d = annotation.end - annotation.start;
|
||||
if (d < diff)
|
||||
{
|
||||
diff = d;
|
||||
annotationPtr = &annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return annotationPtr;
|
||||
}
|
||||
|
||||
void QtCodeSnippet::createAnnotations(const TokenLocationFile& locationFile)
|
||||
{
|
||||
locationFile.forEachTokenLocation(
|
||||
[&](TokenLocation* location)
|
||||
{
|
||||
if (!locationBelongsToSnippet(location))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Annotation annotation;
|
||||
if (location->isStartTokenLocation() && location->getLineNumber() >= m_startLineNumber)
|
||||
{
|
||||
annotation.start = toTextEditPosition(location->getLineNumber(), location->getColumnNumber() - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
annotation.start = startTextEditPosition();
|
||||
}
|
||||
|
||||
TokenLocation* endLocation = location->getEndTokenLocation();
|
||||
if (endLocation)
|
||||
{
|
||||
annotation.end = toTextEditPosition(endLocation->getLineNumber(), endLocation->getColumnNumber());
|
||||
}
|
||||
else
|
||||
{
|
||||
annotation.end = endTextEditPosition();
|
||||
}
|
||||
|
||||
annotation.tokenId = location->getTokenId();
|
||||
annotation.locationId = location->getId();
|
||||
annotation.isScope = location->getType() == TokenLocation::LOCATION_SCOPE;
|
||||
|
||||
m_annotations.push_back(annotation);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void QtCodeSnippet::annotateText()
|
||||
{
|
||||
Colori color;
|
||||
const std::vector<Id>& ids = m_parent->getActiveTokenIds();
|
||||
const std::vector<std::string>& errorMessages = m_parent->getErrorMessages();
|
||||
QList<QTextEdit::ExtraSelection> extraSelections;
|
||||
|
||||
for (const Annotation& annotation: m_annotations)
|
||||
{
|
||||
bool isActive = std::find(ids.begin(), ids.end(), annotation.tokenId) != ids.end();
|
||||
|
||||
if (&annotation == m_hoveredAnnotation && errorMessages.size())
|
||||
{
|
||||
color = Colori(255, 0, 0, 128);
|
||||
}
|
||||
else if (&annotation == m_hoveredAnnotation)
|
||||
{
|
||||
color = ApplicationSettings::getInstance()->getCodeActiveLinkColor();
|
||||
}
|
||||
else if (errorMessages.size())
|
||||
{
|
||||
color = Colori(255, 0, 0, 255);
|
||||
}
|
||||
else if (isActive)
|
||||
{
|
||||
color = ApplicationSettings::getInstance()->getCodeActiveLinkColor();
|
||||
|
||||
if (annotation.isScope)
|
||||
{
|
||||
color.a /= 2;
|
||||
}
|
||||
}
|
||||
else if (annotation.isScope)
|
||||
{
|
||||
color = ApplicationSettings::getInstance()->getCodeScopeColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
color = ApplicationSettings::getInstance()->getCodeLinkColor();
|
||||
}
|
||||
|
||||
QTextEdit::ExtraSelection selection;
|
||||
selection.format.setBackground(QColor(color.r, color.g, color.b, color.a));
|
||||
|
||||
selection.cursor = textCursor();
|
||||
selection.cursor.clearSelection();
|
||||
selection.cursor.setPosition(annotation.start);
|
||||
selection.cursor.setPosition(annotation.end, QTextCursor::KeepAnchor);
|
||||
|
||||
extraSelections.append(selection);
|
||||
}
|
||||
|
||||
setExtraSelections(extraSelections);
|
||||
}
|
||||
|
||||
bool QtCodeSnippet::locationBelongsToSnippet(TokenLocation* location) const
|
||||
{
|
||||
uint lineNumber = location->getLineNumber();
|
||||
|
||||
if (location->isEndTokenLocation())
|
||||
{
|
||||
if (location->getStartTokenLocation() ||
|
||||
lineNumber < m_startLineNumber || lineNumber >= m_startLineNumber + blockCount())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (lineNumber >= m_startLineNumber + blockCount())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lineNumber >= m_startLineNumber)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
TokenLocation* endLocation = location->getEndTokenLocation();
|
||||
|
||||
if (endLocation && endLocation->getLineNumber() < m_startLineNumber)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int QtCodeSnippet::toTextEditPosition(int lineNumber, int columnNumber) const
|
||||
{
|
||||
lineNumber -= m_startLineNumber - 1;
|
||||
int position = 0;
|
||||
|
||||
for (int i = 0; i < lineNumber - 1; i++)
|
||||
{
|
||||
position += document()->findBlockByLineNumber(i).length();
|
||||
}
|
||||
|
||||
position += columnNumber;
|
||||
return position;
|
||||
}
|
||||
|
||||
int QtCodeSnippet::startTextEditPosition() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QtCodeSnippet::endTextEditPosition() const
|
||||
{
|
||||
int position = 0;
|
||||
|
||||
for (int i = 0; i < document()->blockCount(); i++)
|
||||
{
|
||||
position += document()->findBlockByLineNumber(i).length();
|
||||
}
|
||||
|
||||
return position - 1;
|
||||
m_codeArea->update();
|
||||
}
|
||||
|
||||
@@ -2,108 +2,41 @@
|
||||
#define QT_CODE_SNIPPET_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <QPlainTextEdit>
|
||||
#include <memory>
|
||||
|
||||
#include "utility/types.h"
|
||||
#include "qt/element/QtCodeArea.h"
|
||||
|
||||
class QPaintEvent;
|
||||
class QPushButton;
|
||||
class QResizeEvent;
|
||||
class QSize;
|
||||
class QtCodeFile;
|
||||
class QtHighlighter;
|
||||
class QWidget;
|
||||
class TokenLocation;
|
||||
class TokenLocationFile;
|
||||
|
||||
class QtCodeSnippet: public QPlainTextEdit
|
||||
class QtCodeSnippet: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
class LineNumberArea: public QWidget
|
||||
{
|
||||
public:
|
||||
LineNumberArea(QtCodeSnippet *codeSnippet);
|
||||
virtual ~LineNumberArea();
|
||||
|
||||
QSize sizeHint() const;
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event);
|
||||
|
||||
private:
|
||||
QtCodeSnippet *m_codeSnippet;
|
||||
};
|
||||
|
||||
QtCodeSnippet(
|
||||
uint startLineNumber,
|
||||
const std::string& title,
|
||||
const std::string& code,
|
||||
const TokenLocationFile& locationFile,
|
||||
std::shared_ptr<TokenLocationFile> locationFile,
|
||||
QtCodeFile* parent
|
||||
);
|
||||
virtual ~QtCodeSnippet();
|
||||
|
||||
QSize sizeHint() const;
|
||||
|
||||
void addMaximizeButton();
|
||||
|
||||
void lineNumberAreaPaintEvent(QPaintEvent *event);
|
||||
int lineNumberDigits() const;
|
||||
int lineNumberAreaWidth() const;
|
||||
void updateLineNumberAreaWidthForDigits(int digits);
|
||||
|
||||
void updateLineNumberAreaWidthForDigits(int digits);
|
||||
void update();
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *event);
|
||||
virtual void showEvent(QShowEvent* event);
|
||||
virtual void enterEvent(QEvent* event);
|
||||
virtual void leaveEvent(QEvent* event);
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event);
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent* event);
|
||||
virtual void mouseMoveEvent(QMouseEvent* event);
|
||||
|
||||
private slots:
|
||||
void updateLineNumberAreaWidth(int newBlockCount);
|
||||
void updateLineNumberArea(const QRect &, int);
|
||||
void clickedMaximizeButton();
|
||||
void clearSelection();
|
||||
|
||||
private:
|
||||
struct Annotation
|
||||
{
|
||||
int start;
|
||||
int end;
|
||||
Id tokenId;
|
||||
Id locationId;
|
||||
bool isScope;
|
||||
};
|
||||
|
||||
const Annotation* findAnnotationForPosition(int pos) const;
|
||||
void createAnnotations(const TokenLocationFile& locationFile);
|
||||
void annotateText();
|
||||
|
||||
bool locationBelongsToSnippet(TokenLocation* location) const;
|
||||
|
||||
int toTextEditPosition(int lineNumber, int columnNumber) const;
|
||||
int startTextEditPosition() const;
|
||||
int endTextEditPosition() const;
|
||||
|
||||
QtCodeFile* m_parent;
|
||||
|
||||
QWidget* m_lineNumberArea;
|
||||
QtHighlighter* m_highlighter;
|
||||
|
||||
QPushButton* m_maximizeButton;
|
||||
|
||||
const uint m_startLineNumber;
|
||||
|
||||
std::vector<Annotation> m_annotations;
|
||||
const Annotation* m_hoveredAnnotation;
|
||||
|
||||
int m_digits;
|
||||
QtCodeFile* m_parent; // need this?
|
||||
QPushButton* m_title;
|
||||
std::shared_ptr<QtCodeArea> m_codeArea;
|
||||
};
|
||||
|
||||
#endif // QT_CODE_SNIPPET_H
|
||||
|
||||
@@ -90,7 +90,7 @@ void QtCodeView::doShowCodeSnippets(const std::vector<CodeSnippetParams>& snippe
|
||||
|
||||
for (const CodeSnippetParams& params : snippets)
|
||||
{
|
||||
m_widget->addCodeSnippet(params.startLineNumber, params.code, params.locationFile);
|
||||
m_widget->addCodeSnippet(params.startLineNumber, params.title, params.code, params.locationFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,9 +102,9 @@ void QtCodeView::doShowCodeFile(const CodeSnippetParams& params)
|
||||
ptr->setShowMaximizeButton(false);
|
||||
ptr->setActiveTokenIds(m_activeTokenIds);
|
||||
ptr->setErrorMessages(m_errorMessages);
|
||||
ptr->addCodeSnippet(1, params.code, params.locationFile);
|
||||
ptr->addCodeSnippet(1, params.title, params.code, params.locationFile);
|
||||
|
||||
ptr->setWindowTitle(params.locationFile.getFilePath().fileName().c_str());
|
||||
ptr->setWindowTitle(params.locationFile->getFilePath().fileName().c_str());
|
||||
ptr->show();
|
||||
|
||||
float percent = float(params.startLineNumber + params.endLineNumber) / float(params.lineCount) / 2;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include "component/controller/CodeController.h"
|
||||
|
||||
#include <memory>
|
||||
#include "data/access/StorageAccess.h"
|
||||
#include "data/location/TokenLocation.h"
|
||||
#include "data/location/TokenLocationCollection.h"
|
||||
#include "data/location/TokenLocationFile.h"
|
||||
#include "data/location/TokenLocationLine.h"
|
||||
#include "settings/ApplicationSettings.h"
|
||||
#include "utility/text/TextAccess.h"
|
||||
|
||||
@@ -54,7 +56,7 @@ void CodeController::handleMessage(MessageFinishedParsing* message)
|
||||
std::vector<CodeView::CodeSnippetParams> snippets;
|
||||
|
||||
errorCollection.forEachTokenLocationFile(
|
||||
[&](TokenLocationFile* file) -> void
|
||||
[&](std::shared_ptr<TokenLocationFile> file) -> void
|
||||
{
|
||||
std::vector<CodeView::CodeSnippetParams> fileSnippets = getSnippetsForFile(file);
|
||||
snippets.insert(snippets.end(), fileSnippets.begin(), fileSnippets.end());
|
||||
@@ -101,7 +103,7 @@ std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForActiveTok
|
||||
std::vector<CodeView::CodeSnippetParams> snippets;
|
||||
|
||||
collection.forEachTokenLocationFile(
|
||||
[&](TokenLocationFile* file) -> void
|
||||
[&](std::shared_ptr<TokenLocationFile> file) -> void
|
||||
{
|
||||
std::vector<CodeView::CodeSnippetParams> fileSnippets = getSnippetsForFile(file);
|
||||
|
||||
@@ -116,7 +118,7 @@ std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForActiveTok
|
||||
bool isDeclarationFile = false;
|
||||
for (const CodeView::CodeSnippetParams& snippet : fileSnippets)
|
||||
{
|
||||
snippet.locationFile.forEachTokenLocation(
|
||||
snippet.locationFile->forEachTokenLocation(
|
||||
[&](TokenLocation* location)
|
||||
{
|
||||
if (location->getTokenId() == declarationId)
|
||||
@@ -142,7 +144,7 @@ std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForActiveTok
|
||||
return snippets;
|
||||
}
|
||||
|
||||
std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForFile(const TokenLocationFile* file) const
|
||||
std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForFile(std::shared_ptr<TokenLocationFile> file) const
|
||||
{
|
||||
std::shared_ptr<TextAccess> textAccess = TextAccess::createFromFile(file->getFilePath().str());
|
||||
|
||||
@@ -174,10 +176,24 @@ std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForFile(cons
|
||||
for (const SnippetMerger::Range& range: ranges)
|
||||
{
|
||||
CodeView::CodeSnippetParams params;
|
||||
params.locationFile = *file;
|
||||
params.locationFile = file;
|
||||
params.startLineNumber = std::max<int>(1, range.start.row - (range.start.strong ? 0 : snippetExpandRange));
|
||||
params.endLineNumber = std::min<int>(textAccess->getLineCount(), range.end.row + (range.end.strong ? 0 : snippetExpandRange));
|
||||
|
||||
|
||||
std::shared_ptr<TokenLocationFile> tempFile = m_storageAccess->getTokenLocationsForLinesInFile(file->getFilePath().str(), params.startLineNumber, params.endLineNumber);
|
||||
TokenLocationLine* firstUsedLine = nullptr;
|
||||
for (rsize_t i = params.startLineNumber; i <= params.endLineNumber, firstUsedLine == nullptr; i++)
|
||||
{
|
||||
firstUsedLine = tempFile->findTokenLocationLineByNumber(i);
|
||||
}
|
||||
m_storageAccess->getTokenLocationOfParentScope(firstUsedLine->getTokenLocations().begin()->second.get())->forEachStartTokenLocation(
|
||||
[&](TokenLocation* location)
|
||||
{
|
||||
params.title = m_storageAccess->getNameForNodeWithId(location->getTokenId());
|
||||
}
|
||||
);
|
||||
|
||||
for (const std::string& line: textAccess->getLines(params.startLineNumber, params.endLineNumber))
|
||||
{
|
||||
params.code += line;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "component/controller/helper/SnippetMerger.h"
|
||||
#include "component/controller/Controller.h"
|
||||
#include "component/view/CodeView.h"
|
||||
#include "utility/messaging/MessageListener.h"
|
||||
@@ -14,10 +15,6 @@
|
||||
#include "utility/messaging/type/MessageShowFile.h"
|
||||
#include "utility/types.h"
|
||||
|
||||
|
||||
|
||||
#include "component/controller/helper/SnippetMerger.h"
|
||||
|
||||
class StorageAccess;
|
||||
class TokenLocationFile;
|
||||
|
||||
@@ -46,7 +43,7 @@ private:
|
||||
|
||||
std::vector<CodeView::CodeSnippetParams> getSnippetsForActiveTokenIds(
|
||||
const std::vector<Id>& ids, Id declarationId) const;
|
||||
std::vector<CodeView::CodeSnippetParams> getSnippetsForFile(const TokenLocationFile* file) const;
|
||||
std::vector<CodeView::CodeSnippetParams> getSnippetsForFile(std::shared_ptr<TokenLocationFile> file) const;
|
||||
std::shared_ptr<SnippetMerger> buildMergerHierarchy(
|
||||
TokenLocation* location, SnippetMerger& fileScopedMerger, std::map<int, std::shared_ptr<SnippetMerger>>& mergers) const;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ CodeView::CodeSnippetParams::CodeSnippetParams()
|
||||
: startLineNumber(0)
|
||||
, endLineNumber(0)
|
||||
, lineCount(0)
|
||||
, locationFile("")
|
||||
, locationFile(std::make_shared<TokenLocationFile>(""))
|
||||
, isActive(false)
|
||||
, isDeclaration(false)
|
||||
{
|
||||
@@ -40,8 +40,8 @@ bool CodeView::CodeSnippetParams::sort(const CodeSnippetParams& a, const CodeSni
|
||||
return false;
|
||||
}
|
||||
|
||||
const FilePath& aFilePath = a.locationFile.getFilePath();
|
||||
const FilePath& bFilePath = b.locationFile.getFilePath();
|
||||
const FilePath& aFilePath = a.locationFile->getFilePath();
|
||||
const FilePath& bFilePath = b.locationFile->getFilePath();
|
||||
|
||||
// different files
|
||||
if (aFilePath != bFilePath)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef CODE_VIEW_H
|
||||
#define CODE_VIEW_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "component/view/View.h"
|
||||
#include "data/location/TokenLocationFile.h"
|
||||
#include "utility/types.h"
|
||||
@@ -21,9 +23,10 @@ public:
|
||||
uint endLineNumber;
|
||||
uint lineCount;
|
||||
|
||||
std::string title;
|
||||
std::string code;
|
||||
|
||||
TokenLocationFile locationFile;
|
||||
std::shared_ptr<TokenLocationFile> locationFile;
|
||||
|
||||
bool isActive;
|
||||
bool isDeclaration;
|
||||
|
||||
@@ -976,9 +976,9 @@ TokenLocationCollection Storage::getTokenLocationsForTokenIds(const std::vector<
|
||||
return ret;
|
||||
}
|
||||
|
||||
TokenLocationFile Storage::getTokenLocationsForFile(const std::string& filePath) const
|
||||
std::shared_ptr<TokenLocationFile> Storage::getTokenLocationsForFile(const std::string& filePath) const
|
||||
{
|
||||
TokenLocationFile ret(filePath);
|
||||
std::shared_ptr<TokenLocationFile> ret = std::make_shared<TokenLocationFile>(filePath);
|
||||
|
||||
TokenLocationFile* locationFile = m_locationCollection.findTokenLocationFileByPath(filePath);
|
||||
if (!locationFile)
|
||||
@@ -989,18 +989,18 @@ TokenLocationFile Storage::getTokenLocationsForFile(const std::string& filePath)
|
||||
locationFile->forEachTokenLocation(
|
||||
[&](TokenLocation* tokenLocation) -> void
|
||||
{
|
||||
ret.addTokenLocationAsPlainCopy(tokenLocation);
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation);
|
||||
}
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
TokenLocationFile Storage::getTokenLocationsForLinesInFile(
|
||||
std::shared_ptr<TokenLocationFile> Storage::getTokenLocationsForLinesInFile(
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||
) const
|
||||
{
|
||||
TokenLocationFile ret(filePath);
|
||||
std::shared_ptr<TokenLocationFile> ret = std::make_shared<TokenLocationFile>(filePath);
|
||||
|
||||
TokenLocationFile* locationFile = m_locationCollection.findTokenLocationFileByPath(filePath);
|
||||
if (!locationFile)
|
||||
@@ -1009,7 +1009,7 @@ TokenLocationFile Storage::getTokenLocationsForLinesInFile(
|
||||
}
|
||||
|
||||
uint endLineNumber = locationFile->getTokenLocationLines().rbegin()->first;
|
||||
|
||||
std::set<int> addedLocationIds;
|
||||
for (uint i = firstLineNumber; i <= endLineNumber; i++)
|
||||
{
|
||||
TokenLocationLine* locationLine = locationFile->findTokenLocationLineByNumber(i);
|
||||
@@ -1023,7 +1023,13 @@ TokenLocationFile Storage::getTokenLocationsForLinesInFile(
|
||||
locationLine->forEachTokenLocation(
|
||||
[&](TokenLocation* tokenLocation) -> void
|
||||
{
|
||||
ret.addTokenLocationAsPlainCopy(tokenLocation);
|
||||
const Id tokenId = tokenLocation->getId();
|
||||
if (addedLocationIds.find(tokenId) == addedLocationIds.end())
|
||||
{
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation->getStartTokenLocation());
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation->getEndTokenLocation());
|
||||
addedLocationIds.insert(tokenId);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1036,7 +1042,8 @@ TokenLocationFile Storage::getTokenLocationsForLinesInFile(
|
||||
if (tokenLocation->isEndTokenLocation() &&
|
||||
tokenLocation->getStartTokenLocation()->getLineNumber() < firstLineNumber)
|
||||
{
|
||||
ret.addTokenLocationAsPlainCopy(tokenLocation->getStartTokenLocation());
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation->getStartTokenLocation());
|
||||
ret->addTokenLocationAsPlainCopy(tokenLocation->getEndTokenLocation());
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -1062,7 +1069,6 @@ std::shared_ptr<TokenLocationFile> Storage::getTokenLocationOfParentScope(const
|
||||
[&](TokenLocation* tokenLocation) -> void
|
||||
{
|
||||
if (tokenLocation->getType() == TokenLocation::LOCATION_SCOPE &&
|
||||
tokenLocation->isStartTokenLocation() &&
|
||||
(*tokenLocation) < *(child->getStartTokenLocation()) &&
|
||||
(*tokenLocation->getEndTokenLocation()) > *(child->getEndTokenLocation()))
|
||||
{
|
||||
|
||||
@@ -119,8 +119,8 @@ public:
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const;
|
||||
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
virtual TokenLocationFile getTokenLocationsForFile(const std::string& filePath) const;
|
||||
virtual TokenLocationFile getTokenLocationsForLinesInFile(
|
||||
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForFile(const std::string& filePath) const;
|
||||
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForLinesInFile(
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||
) const;
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ public:
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const = 0;
|
||||
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const = 0;
|
||||
virtual TokenLocationFile getTokenLocationsForFile(const std::string& filePath) const = 0;
|
||||
virtual TokenLocationFile getTokenLocationsForLinesInFile(
|
||||
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForFile(const std::string& filePath) const = 0;
|
||||
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForLinesInFile(
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber) const = 0;
|
||||
|
||||
virtual TokenLocationCollection getErrorTokenLocations(std::vector<std::string>* errorMessages) const = 0;
|
||||
|
||||
@@ -122,17 +122,17 @@ TokenLocationCollection StorageAccessProxy::getTokenLocationsForTokenIds(const s
|
||||
return TokenLocationCollection();
|
||||
}
|
||||
|
||||
TokenLocationFile StorageAccessProxy::getTokenLocationsForFile(const std::string& filePath) const
|
||||
std::shared_ptr<TokenLocationFile> StorageAccessProxy::getTokenLocationsForFile(const std::string& filePath) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getTokenLocationsForFile(filePath);
|
||||
}
|
||||
|
||||
return TokenLocationFile("");
|
||||
return std::make_shared<TokenLocationFile>("");
|
||||
}
|
||||
|
||||
TokenLocationFile StorageAccessProxy::getTokenLocationsForLinesInFile(
|
||||
std::shared_ptr<TokenLocationFile> StorageAccessProxy::getTokenLocationsForLinesInFile(
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||
) const
|
||||
{
|
||||
@@ -141,7 +141,7 @@ TokenLocationFile StorageAccessProxy::getTokenLocationsForLinesInFile(
|
||||
return m_subject->getTokenLocationsForLinesInFile(filePath, firstLineNumber, lastLineNumber);
|
||||
}
|
||||
|
||||
return TokenLocationFile("");
|
||||
return std::make_shared<TokenLocationFile>("");
|
||||
}
|
||||
|
||||
TokenLocationCollection StorageAccessProxy::getErrorTokenLocations(std::vector<std::string>* errorMessages) const
|
||||
|
||||
@@ -27,8 +27,8 @@ public:
|
||||
virtual std::vector<Id> getTokenIdsForQuery(std::string query) const;
|
||||
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
virtual TokenLocationFile getTokenLocationsForFile(const std::string& filePath) const;
|
||||
virtual TokenLocationFile getTokenLocationsForLinesInFile(
|
||||
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForFile(const std::string& filePath) const;
|
||||
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForLinesInFile(
|
||||
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
|
||||
) const;
|
||||
|
||||
|
||||
@@ -105,11 +105,11 @@ TokenLocationFile* TokenLocationCollection::findTokenLocationFileByPath(const Fi
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TokenLocationCollection::forEachTokenLocationFile(std::function<void(TokenLocationFile*)> func) const
|
||||
void TokenLocationCollection::forEachTokenLocationFile(std::function<void(std::shared_ptr<TokenLocationFile>)> func) const
|
||||
{
|
||||
for (const TokenLocationFilePairType& file : m_files)
|
||||
{
|
||||
func(file.second.get());
|
||||
func(file.second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,9 +188,9 @@ TokenLocationFile* TokenLocationCollection::createTokenLocationFile(const FilePa
|
||||
std::ostream& operator<<(std::ostream& ostream, const TokenLocationCollection& base)
|
||||
{
|
||||
ostream << "Locations:\n";
|
||||
base.forEachTokenLocationFile([&ostream](TokenLocationFile* f)
|
||||
base.forEachTokenLocationFile([&ostream](std::shared_ptr<TokenLocationFile> f)
|
||||
{
|
||||
ostream << *f;
|
||||
ostream << *(f.get());
|
||||
});
|
||||
return ostream;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
TokenLocation* findTokenLocationById(Id id) const;
|
||||
TokenLocationFile* findTokenLocationFileByPath(const FilePath& filePath) const;
|
||||
|
||||
void forEachTokenLocationFile(std::function<void(TokenLocationFile*)> func) const;
|
||||
void forEachTokenLocationFile(std::function<void(std::shared_ptr<TokenLocationFile>)> func) const;
|
||||
void forEachTokenLocationLine(std::function<void(TokenLocationLine*)> func) const;
|
||||
void forEachTokenLocation(std::function<void(TokenLocation*)> func) const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user