show location of error in gutter and as selection

Close #3
This commit is contained in:
eelke 2018-04-09 21:44:00 +02:00
parent 47ee1857cd
commit 45b7d4fcbc
4 changed files with 105 additions and 14 deletions

View file

@ -17,6 +17,7 @@ CodeEditor::CodeEditor(QWidget *parent)
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateGutterAreaWidth(int))); connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateGutterAreaWidth(int)));
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateGutterArea(QRect,int))); connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateGutterArea(QRect,int)));
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine())); connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
connect(this, SIGNAL(textChanged()), this, SLOT(onTextChanged()));
updateGutterAreaWidth(0); updateGutterAreaWidth(0);
highlightCurrentLine(); highlightCurrentLine();
@ -31,7 +32,7 @@ int CodeEditor::gutterAreaWidth()
++digits; ++digits;
} }
int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits; int space = 3 + fontMetrics().width(QLatin1Char('9')) * (digits + 2);
return space; return space;
} }
@ -62,20 +63,55 @@ void CodeEditor::resizeEvent(QResizeEvent *e)
void CodeEditor::highlightCurrentLine() void CodeEditor::highlightCurrentLine()
{ {
QList<QTextEdit::ExtraSelection> extraSelections;
if (!isReadOnly()) {
QTextEdit::ExtraSelection selection; QTextEdit::ExtraSelection selection;
QColor lineColor = QColor(Qt::yellow).lighter(160); QColor lineColor = QColor(Qt::yellow).lighter(160);
selection.format.setBackground(lineColor); selection.format.setBackground(lineColor);
selection.format.setProperty(QTextFormat::FullWidthSelection, true); selection.format.setProperty(QTextFormat::FullWidthSelection, true);
selection.cursor = textCursor(); selection.cursor = textCursor();
selection.cursor.clearSelection(); selection.cursor.clearSelection();
extraSelections.append(selection); currentLine = selection;
updateExtraSelections();
} }
void CodeEditor::onTextChanged()
{
clearErrorMarkers();
}
void CodeEditor::addErrorMarker(int position, int length)
{
QTextEdit::ExtraSelection selection;
QColor lineColor = QColor(Qt::red).lighter(160);
selection.format.setBackground(lineColor);
selection.format.setFontItalic(true);
selection.cursor = textCursor();
selection.cursor.setPosition(position);
int lineno = selection.cursor.blockNumber();
errorLines.insert(lineno);
selection.cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, length);
errorMarkers.append(selection);
update();
updateExtraSelections();
}
void CodeEditor::clearErrorMarkers()
{
errorMarkers.clear();
errorLines.clear();
update();
updateExtraSelections();
}
void CodeEditor::updateExtraSelections()
{
QList<QTextEdit::ExtraSelection> extraSelections;
extraSelections.append(currentLine);
for (auto e : errorMarkers)
extraSelections.append(e);
setExtraSelections(extraSelections); setExtraSelections(extraSelections);
} }
@ -102,6 +138,12 @@ void CodeEditor::gutterAreaPaintEvent(QPaintEvent *event)
painter.setPen(Qt::black); painter.setPen(Qt::black);
painter.drawText(0, top, gutterArea->width(), fontMetrics().height(), painter.drawText(0, top, gutterArea->width(), fontMetrics().height(),
Qt::AlignRight, number); Qt::AlignRight, number);
if (errorLines.count(blockNumber) > 0) {
int s = fontMetrics().height() - 8;
painter.setBrush(QBrush(Qt::red));
painter.drawEllipse(4, top + 4, s, s);
}
} }
block = block.next(); block = block.next();

View file

@ -2,6 +2,7 @@
#define CODEEDITOR_H #define CODEEDITOR_H
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <set>
class CodeEditor : public QPlainTextEdit class CodeEditor : public QPlainTextEdit
{ {
@ -12,6 +13,8 @@ public:
void gutterAreaPaintEvent(QPaintEvent *event); void gutterAreaPaintEvent(QPaintEvent *event);
int gutterAreaWidth(); int gutterAreaWidth();
void addErrorMarker(int position, int length);
void clearErrorMarkers();
protected: protected:
void resizeEvent(QResizeEvent *event) override; void resizeEvent(QResizeEvent *event) override;
@ -23,9 +26,17 @@ private slots:
void updateGutterAreaWidth(int newBlockCount); void updateGutterAreaWidth(int newBlockCount);
void highlightCurrentLine(); void highlightCurrentLine();
void updateGutterArea(const QRect &, int); void updateGutterArea(const QRect &, int);
void onTextChanged();
private: private:
QWidget *gutterArea; QWidget *gutterArea;
QTextEdit::ExtraSelection currentLine;
QList<QTextEdit::ExtraSelection> errorMarkers;
std::set<int> errorLines;
void updateExtraSelections();
}; };
#endif // CODEEDITOR_H #endif // CODEEDITOR_H

View file

@ -512,7 +512,9 @@ void QueryTab::query_ready(Expected<std::shared_ptr<Pgsql::Result>> exp_res, qin
// statusBar()->showMessage(tr("No tuples returned, possibly an error...")); // statusBar()->showMessage(tr("No tuples returned, possibly an error..."));
// } // }
ui->tabWidget->setCurrentWidget(ui->messageTab); ui->tabWidget->setCurrentWidget(ui->messageTab);
receiveNotice(dbres->diagDetails()); auto details = dbres->diagDetails();
markError(details);
receiveNotice(details);
} }
} }
} }
@ -526,6 +528,37 @@ void QueryTab::query_ready(Expected<std::shared_ptr<Pgsql::Result>> exp_res, qin
} }
} }
void QueryTab::markError(const Pgsql::ErrorDetails &details)
{
if (details.statementPosition > 0) {
QTextCursor cursor = ui->queryEdit->textCursor();
cursor.setPosition(details.statementPosition-1);
ui->queryEdit->setTextCursor(cursor);
int length = 0;
if (details.state == "42703") {
int pos = details.messagePrimary.find('"');
if (pos != std::string::npos) {
int pos2 = details.messagePrimary.find('"', pos+1);
if (pos2 != std::string::npos) {
length = pos2 - pos;
}
}
}
else if (details.state == "42P01") {
int pos = details.messagePrimary.find('"');
if (pos != std::string::npos) {
int pos2 = details.messagePrimary.find('"', pos+1);
if (pos2 != std::string::npos) {
length = pos2 - pos;
}
}
}
ui->queryEdit->addErrorMarker(details.statementPosition-1, length);
}
}
void QueryTab::clearResult() void QueryTab::clearResult()
{ {
for (auto e : resultList) for (auto e : resultList)

View file

@ -15,6 +15,10 @@ namespace Ui {
class QueryTab; class QueryTab;
} }
namespace Pgsql {
class ErrorDetails ;
}
class QTableView; class QTableView;
class QTabWidget; class QTabWidget;
@ -95,6 +99,7 @@ private:
QTabWidget *getTabWidget(); QTabWidget *getTabWidget();
void setTabCaption(const QString &caption, const QString &tooltip); void setTabCaption(const QString &caption, const QString &tooltip);
void clearResult(); void clearResult();
void markError(const Pgsql::ErrorDetails &details);
private slots: private slots: