Skip to content

Commit

Permalink
Diagnostics output visual fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
IgKh committed Oct 18, 2024
1 parent 7cc3e01 commit 418dffe
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 36 deletions.
89 changes: 74 additions & 15 deletions src/katvan_compileroutput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,50 +18,109 @@
#include "katvan_compileroutput.h"
#include "katvan_diagnosticsmodel.h"

#include <QFontDatabase>
#include <QHeaderView>
#include <QResizeEvent>
#include <QStyledItemDelegate>

namespace katvan {

class DiagnosticsItemDelegate : public QStyledItemDelegate {
public:
DiagnosticsItemDelegate(QObject *parent = nullptr)
: QStyledItemDelegate(parent) {}

protected:
void initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const override
{
QStyledItemDelegate::initStyleOption(option, index);

// Not interested in individual focus rects on columns
option->state &= ~QStyle::State_HasFocus;
}
};

CompilerOutput::CompilerOutput(QWidget* parent)
: QTreeView(parent)
{
setHeaderHidden(true);
setRootIsDecorated(false);
setAlternatingRowColors(true);
header()->setStretchLastSection(true);

setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
setItemDelegate(new DiagnosticsItemDelegate(this));
setLayoutDirection(Qt::LeftToRight);
setMouseTracking(true);
header()->setStretchLastSection(false);

connect(this, &QTreeView::activated, this, &CompilerOutput::itemActivated);
connect(this, &QTreeView::clicked, this, &CompilerOutput::indexClicked);
}

void CompilerOutput::setModel(QAbstractItemModel* model)
{
Q_ASSERT(qobject_cast<DiagnosticsModel*>(model) != nullptr);

QTreeView::setModel(model);

header()->setSectionResizeMode(DiagnosticsModel::COLUMN_SEVERITY, QHeaderView::Fixed);
header()->setSectionResizeMode(DiagnosticsModel::COLUMN_MESSAGE, QHeaderView::Stretch);
header()->setSectionResizeMode(DiagnosticsModel::COLUMN_SOURCE_LOCATION, QHeaderView::Fixed);
}

void CompilerOutput::adjustColumnWidths()
{
adjustColumnWidths(viewport()->size());
}

void CompilerOutput::adjustColumnWidths(QSize viewportSize)
{
int severityWidth = 22;
int locationWidth = fontMetrics().horizontalAdvance("0000:000");
int availableWidthForFileName = viewport()->width() - severityWidth - locationWidth;
int fileNameSizeHint = sizeHintForColumn(DiagnosticsModel::COLUMN_FILE);
int messageSizeHint = sizeHintForColumn(DiagnosticsModel::COLUMN_MESSAGE);
int locationSizeHint = sizeHintForColumn(DiagnosticsModel::COLUMN_SOURCE_LOCATION);
int availableWidthForLocation = viewportSize.width() - severityWidth - messageSizeHint;

// If there is enough space for fully accomodate the file name, give it that
// much width. Otherwise, give it 25% of the total width.
int fileNameWidth = (fileNameSizeHint <= availableWidthForFileName)
? fileNameSizeHint
: qRound(viewport()->width() / 4.0);
// much width. Otherwise, give it up to 25% of the total width.
int locationWidth = (locationSizeHint <= availableWidthForLocation)
? locationSizeHint
: qMin(qRound(viewportSize.width() / 4.0), locationSizeHint);

setColumnWidth(DiagnosticsModel::COLUMN_SEVERITY, severityWidth);
setColumnWidth(DiagnosticsModel::COLUMN_FILE, fileNameWidth);
setColumnWidth(DiagnosticsModel::COLUMN_SOURCE_LOCATION, locationWidth);
}

void CompilerOutput::resizeEvent(QResizeEvent* event)
{
if (!model()) {
return;
}

QTreeView::resizeEvent(event);
adjustColumnWidths();
adjustColumnWidths(event->size());
}

void CompilerOutput::mouseMoveEvent(QMouseEvent* event)
{
QTreeView::mouseMoveEvent(event);

QModelIndex index = indexAt(event->pos());
if (index.isValid()) {
QVariant cursor = index.data(DiagnosticsModel::ROLE_MOUSE_CURSOR);
if (cursor.isValid()) {
setCursor(qvariant_cast<QCursor>(cursor));
return;
}
}
setCursor(Qt::ArrowCursor);
}

void CompilerOutput::keyPressEvent(QKeyEvent* event)
{
if (event->key() == Qt::Key_Escape) {
clearSelection();
return;
}
QTreeView::keyPressEvent(event);
}

void CompilerOutput::itemActivated(const QModelIndex& index)
void CompilerOutput::indexClicked(const QModelIndex& index)
{
if (!index.isValid()) {
return;
Expand Down
7 changes: 6 additions & 1 deletion src/katvan_compileroutput.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,22 @@ class CompilerOutput : public QTreeView
public:
CompilerOutput(QWidget* parent = nullptr);

void setModel(QAbstractItemModel* model) override;

public slots:
void adjustColumnWidths();
void adjustColumnWidths(QSize viewportSize);

signals:
void goToPosition(int blockNum, int charOffset);

protected:
void resizeEvent(QResizeEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void keyPressEvent(QKeyEvent* event) override;

private slots:
void itemActivated(const QModelIndex& index);
void indexClicked(const QModelIndex& index);
};

}
41 changes: 28 additions & 13 deletions src/katvan_diagnosticsmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
*/
#include "katvan_diagnosticsmodel.h"

#include <QCursor>
#include <QFileInfo>
#include <QFontDatabase>
#include <QIcon>

namespace katvan {
Expand All @@ -27,6 +29,7 @@ static constexpr QLatin1StringView MAIN_SOURCE = QLatin1StringView("MAIN");
DiagnosticsModel::DiagnosticsModel(QObject* parent)
: QAbstractTableModel(parent)
{
d_font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
}

void DiagnosticsModel::setInputFileName(const QString& fileName)
Expand Down Expand Up @@ -103,6 +106,19 @@ QVariant DiagnosticsModel::data(const QModelIndex& index, int role) const

const auto& diagnostic = d_diagnostics[index.row()];

if (role == Qt::FontRole) {
QFont font = d_font;
if (index.column() == COLUMN_SOURCE_LOCATION && diagnostic.file() == MAIN_SOURCE) {
font.setUnderline(true);
}
return font;
}
if (role == ROLE_MOUSE_CURSOR) {
if (index.column() == COLUMN_SOURCE_LOCATION && diagnostic.file() == MAIN_SOURCE) {
return QCursor(Qt::PointingHandCursor);
}
}

if (index.column() == COLUMN_SEVERITY) {
auto kind = diagnostic.kind();
if (role == Qt::DecorationRole) {
Expand Down Expand Up @@ -130,26 +146,25 @@ QVariant DiagnosticsModel::data(const QModelIndex& index, int role) const
}
}
}
else if (index.column() == COLUMN_FILE && (role == Qt::DisplayRole || role == Qt::ToolTipRole)) {
QString fileName = diagnostic.file();
if (fileName == MAIN_SOURCE) {
return d_shortFileName;
}
return fileName;
}
else if (index.column() == COLUMN_SOURCE_LOCATION && role == Qt::DisplayRole) {
if (diagnostic.location()) {
auto location = diagnostic.location().value();
return QString("%1:%2").arg(location.line).arg(location.column);
}
}
else if (index.column() == COLUMN_MESSAGE && (role == Qt::DisplayRole || role == Qt::ToolTipRole)) {
QString message = diagnostic.message();
for (const QString& hint : diagnostic.hints()) {
message += QChar::LineFeed + QStringLiteral("Hint: ") + hint;
}
return message;
}
else if (index.column() == COLUMN_SOURCE_LOCATION && (role == Qt::DisplayRole || role == Qt::ToolTipRole)) {
QString result = diagnostic.file();
if (result == MAIN_SOURCE) {
result = d_shortFileName;
}

if (diagnostic.location()) {
auto location = diagnostic.location().value();
result += QStringLiteral(" (%1:%2)").arg(location.line).arg(location.column);
}
return result;
}
return QVariant();
}

Expand Down
11 changes: 8 additions & 3 deletions src/katvan_diagnosticsmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "typstdriver_logger.h"

#include <QAbstractTableModel>
#include <QFont>
#include <QList>

#include <optional>
Expand All @@ -36,12 +37,15 @@ class DiagnosticsModel : public QAbstractTableModel
public:
enum {
COLUMN_SEVERITY = 0,
COLUMN_FILE,
COLUMN_SOURCE_LOCATION,
COLUMN_MESSAGE,
COLUMN_SOURCE_LOCATION,
COLUMN_COUNT
};

enum {
ROLE_MOUSE_CURSOR = Qt::UserRole + 1,
};

DiagnosticsModel(QObject* parent = nullptr);

void setInputFileName(const QString& fileName);
Expand All @@ -55,9 +59,10 @@ class DiagnosticsModel : public QAbstractTableModel

public slots:
void clear();
void addDiagnostic(const typstdriver::Diagnostic& diagnostic);
void addDiagnostic(const katvan::typstdriver::Diagnostic& diagnostic);

private:
QFont d_font;
QString d_shortFileName;
QList<typstdriver::Diagnostic> d_diagnostics;
};
Expand Down
2 changes: 1 addition & 1 deletion src/katvan_mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ MainWindow::MainWindow()

connect(d_driver, &TypstDriverWrapper::previewReady, this, &MainWindow::previewReady);
connect(d_driver, &TypstDriverWrapper::compilationStatusChanged, this, &MainWindow::compilationStatusChanged);
connect(d_driver, &TypstDriverWrapper::compilationStatusChanged, d_compilerOutput, &CompilerOutput::adjustColumnWidths);
connect(d_driver, &TypstDriverWrapper::jumpToPreview, d_previewer, &Previewer::jumpToPreview);
connect(d_driver, &TypstDriverWrapper::jumpToEditor, d_editor, &Editor::goToBlock);

Expand Down Expand Up @@ -860,6 +859,7 @@ void MainWindow::compilationStatusChanged()
if (status != TypstDriverWrapper::Status::PROCESSING) {
d_compilingMovie->stop();
}
d_compilerOutput->adjustColumnWidths();

if (status == TypstDriverWrapper::Status::PROCESSING) {
d_compilationStatusButton->setText(tr("Compiling..."));
Expand Down
3 changes: 1 addition & 2 deletions typstdriver/rust/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,7 @@ impl<'a> EngineImpl<'a> {
// it) that is located in the main source.
let span = std::iter::once(diag.span)
.chain(diag.trace.iter().map(|t| t.span))
.filter(|span| span.id() == Some(*MAIN_ID))
.next()
.find(|span| span.id() == Some(*MAIN_ID))
.unwrap_or(diag.span);

let location = self.span_to_location(span);
Expand Down
2 changes: 1 addition & 1 deletion typstdriver/typstdriver_logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class TYPSTDRIVER_EXPORT Logger : public QObject
void logDiagnostic(Diagnostic diagnostic);

signals:
void diagnosticLogged(Diagnostic diagnostic);
void diagnosticLogged(katvan::typstdriver::Diagnostic diagnostic);
};

}

0 comments on commit 418dffe

Please sign in to comment.