Commit c1a7f507 authored by Gris Lours's avatar Gris Lours
Browse files

Merge branch 'feature_linter' into 'master'

Feature linter

See merge request !2
parents 7d65ac78 543e1d54
......@@ -15,6 +15,9 @@ set( ${PROJECT_NAME}_SOURCES
main.cpp
mainwindow.cpp
mainwindow.ui
syntax_highlighter.cpp
block_data.cpp
main.qrc
)
......
#include "block_data.hpp"
BlockData::BlockData( std::string msg )
: msg{ std::move( msg ) }
{
// null
}
BlockData::~BlockData() = default;
#ifndef BLOCK_DATA_HPP
#define BLOCK_DATA_HPP
#include <QTextBlockUserData>
class BlockData
: public QTextBlockUserData
{
public:
std::string msg = {};
public:
explicit BlockData( std::string msg );
~BlockData() override;
};
#endif
#include "block_data.hpp"
#include "mainwindow.hpp"
#include "ui_mainwindow.h"
#include <QSettings>
#include <QStandardPaths>
#include <QToolTip>
#include <QUuid>
#include <filesystem>
#include <fstream>
#include <regex>
namespace fs = std::filesystem;
......@@ -16,6 +19,8 @@ MainWindow::MainWindow( QWidget *parent )
, process_{ parent }
, plain_text_{ nullptr }
, commands_{}
, line_and_errors_{}
, syntax_highlighter_ptr_{}
{
// prepare qt things
ui_ptr_->setupUi( this );
......@@ -23,6 +28,10 @@ MainWindow::MainWindow( QWidget *parent )
connect( &process_, &QProcess::readyReadStandardError, this, &MainWindow::update_std_err );
connect( &process_, SIGNAL(finished(int)), this, SLOT(finished(int)));
// event filter for tooltip
ui_ptr_->textEdit_code->installEventFilter( this );
syntax_highlighter_ptr_ = std::make_unique<SyntaxHighlighter>( ui_ptr_->textEdit_code->document() );
// restore settings
restore_settings();
......@@ -55,12 +64,7 @@ MainWindow::MainWindow( QWidget *parent )
void MainWindow::run()
{
// preparation
ui_ptr_->tabWidget->setCurrentIndex( 0 );
QApplication::setOverrideCursor( Qt::WaitCursor );
setEnabled( false );
ui_ptr_->plainTextEdit_compilation->clear();
ui_ptr_->plainTextEdit_io->clear();
plain_text_.reset( ui_ptr_->plainTextEdit_compilation );
disable();
// copy code
auto fos = std::ofstream{};
......@@ -118,7 +122,7 @@ void MainWindow::finished( int exit_code )
MainWindow::~MainWindow() = default;
void MainWindow::closeEvent( QCloseEvent *event )
void MainWindow::closeEvent( QCloseEvent *event_ptr )
{
// delete directory
fs::remove_all( directory_ );
......@@ -130,7 +134,7 @@ void MainWindow::closeEvent( QCloseEvent *event )
settings.setValue( "windowState", saveState() );
settings.setValue( "code", ui_ptr_->textEdit_code->toPlainText() );
settings.endGroup();
QMainWindow::closeEvent( event );
QMainWindow::closeEvent( event_ptr );
}
void MainWindow::prepare_directory()
......@@ -158,6 +162,51 @@ void MainWindow::restore_settings()
settings.endGroup();
}
bool MainWindow::eventFilter( QObject *obj_ptr, QEvent *event_ptr )
{
if( obj_ptr == ui_ptr_->textEdit_code and event_ptr->type() == QEvent::ToolTip ) {
auto *help_event_ptr = static_cast<QHelpEvent *>( event_ptr );
auto cursor = ui_ptr_->textEdit_code->cursorForPosition( help_event_ptr->pos() );
cursor.select( QTextCursor::LineUnderCursor );
// get msg
auto *block_data = static_cast<BlockData*>( cursor.block().userData() );
if( block_data == nullptr ) {
QToolTip::hideText();
} else {
QToolTip::showText( help_event_ptr->globalPos(), QString::fromStdString( block_data->msg ) );
}
return true;
}
return false;
}
void MainWindow::update_blocks()
{
auto &document = *ui_ptr_->textEdit_code->document();
for( auto i = 0; i < document.blockCount(); ++i ) {
auto it = line_and_errors_.find( i + 1 );
auto block = document.findBlockByNumber( i );
if( it != line_and_errors_.end() ) {
// transform std::vector<std::string> into one string
auto result = std::string{ "" };
auto first = true;
for( const auto &str : it->second ) {
if( not first ) result += "\n";
result += str;
first = false;
}
// store message into the corresponding block
auto block_data_ptr = std::make_unique<BlockData>( result );
block.setUserData( block_data_ptr.release() );
} else {
block.setUserData( nullptr );
}
}
}
void MainWindow::execute_next_command()
{
const Command &command = commands_.at( current_command_index_ );
......@@ -171,18 +220,42 @@ void MainWindow::execute_next_command()
}
}
void MainWindow::disable()
{
QApplication::setOverrideCursor( Qt::WaitCursor );
setEnabled( false );
ui_ptr_->tabWidget->setCurrentIndex( 0 );
ui_ptr_->plainTextEdit_compilation->clear();
ui_ptr_->plainTextEdit_io->clear();
plain_text_.reset( ui_ptr_->plainTextEdit_compilation );
line_and_errors_.clear();
update_blocks();
syntax_highlighter_ptr_->rehighlight();
}
void MainWindow::enable()
{
QApplication::restoreOverrideCursor();
setEnabled( true );
update_blocks();
syntax_highlighter_ptr_->rehighlight();
}
void MainWindow::append_text( std::string_view text, const QColor &color )
void MainWindow::append_text( const std::string &text, const QColor &color )
{
// insert text
auto cursor = plain_text_->textCursor();
cursor.movePosition( QTextCursor::End );
auto format = QTextCharFormat{};
format.setForeground( QBrush{ color } );
cursor.insertText( text.data(), format );
plain_text_->moveCursor( QTextCursor::End );
// analyse and save errors or warnings
static const std::regex error_regex{ R"(\.\.\/main\.cpp\:(\d+)\:\d+: error\: (.*))" };
auto begin_it = std::sregex_iterator( text.begin(), text.end(), error_regex );
for( auto it = begin_it; it != std::sregex_iterator{}; ++it ) {
auto match = *it;
line_and_errors_[std::stoi( match.str( 1 ) )].push_back( match.str( 2 ) );
}
}
#ifndef MAINWINDOW_HPP
#define MAINWINDOW_HPP
#include "syntax_highlighter.hpp"
#include <QMainWindow>
#include <QProcess>
#include <experimental/memory>
......@@ -34,14 +35,17 @@ public slots:
void update_std_out();
protected:
void closeEvent( QCloseEvent *event ) override;
void closeEvent( QCloseEvent *event_ptr ) override;
bool eventFilter( QObject *obj_ptr, QEvent *event_ptr ) override;
private:
void append_text( std::string_view text, const QColor &color );
void append_text( const std::string &text, const QColor &color );
void disable();
void enable();
void execute_next_command();
void prepare_directory();
void restore_settings();
void update_blocks();
private:
std::unique_ptr<Ui::MainWindow> ui_ptr_;
......@@ -51,6 +55,8 @@ private:
std::experimental::observer_ptr<QPlainTextEdit> plain_text_;
std::vector<Command> commands_;
unsigned current_command_index_ = 0;
std::map<int, std::vector<std::string>> line_and_errors_;
std::unique_ptr<SyntaxHighlighter> syntax_highlighter_ptr_;
};
#endif // MAINWINDOW_HPP
......@@ -36,6 +36,9 @@
<pointsize>12</pointsize>
</font>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="tabStopWidth">
<number>20</number>
</property>
......
#include "block_data.hpp"
#include "syntax_highlighter.hpp"
#include <QTextDocument>
#include <memory>
SyntaxHighlighter::SyntaxHighlighter( QTextDocument *parent )
: QSyntaxHighlighter( parent )
, error_format_{}
{
error_format_.setUnderlineStyle( QTextCharFormat::WaveUnderline );
error_format_.setUnderlineColor( Qt::red );
}
void SyntaxHighlighter::highlightBlock( const QString &text )
{
auto *data_block = static_cast<BlockData*>( currentBlock().userData() );
if( data_block != nullptr ) {
setFormat( 0, text.length(), error_format_ );
}
}
#ifndef SYNTAX_HIGHLIGHTER_HPP
#define SYNTAX_HIGHLIGHTER_HPP
#include <QSyntaxHighlighter>
class SyntaxHighlighter
: public QSyntaxHighlighter
{
Q_OBJECT
public:
explicit SyntaxHighlighter( QTextDocument *parent = nullptr );
protected:
void highlightBlock( const QString &text ) override;
private:
QTextCharFormat error_format_;
};
#endif
......@@ -14,61 +14,61 @@
<translation></translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.ui" line="65"/>
<location filename="../src/prototypator/mainwindow.ui" line="68"/>
<source>&amp;Run</source>
<translation></translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.ui" line="68"/>
<location filename="../src/prototypator/mainwindow.ui" line="71"/>
<source>Ctrl+R</source>
<translation></translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.ui" line="79"/>
<location filename="../src/prototypator/mainwindow.ui" line="82"/>
<source>Result:</source>
<translation></translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.ui" line="90"/>
<location filename="../src/prototypator/mainwindow.ui" line="93"/>
<source>Compilation</source>
<translation></translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.ui" line="144"/>
<location filename="../src/prototypator/mainwindow.ui" line="147"/>
<source>Input/output</source>
<translation></translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.cpp" line="37"/>
<location filename="../src/prototypator/mainwindow.cpp" line="46"/>
<source>testing presence of cmake...
</source>
<translation></translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.cpp" line="41"/>
<location filename="../src/prototypator/mainwindow.cpp" line="50"/>
<source>running &apos;cmake&apos;...
</source>
<translation></translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.cpp" line="45"/>
<location filename="../src/prototypator/mainwindow.cpp" line="54"/>
<source>running &apos;make&apos;...
</source>
<translation></translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.cpp" line="49"/>
<location filename="../src/prototypator/mainwindow.cpp" line="58"/>
<source>running application...
</source>
<translation></translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.cpp" line="106"/>
<location filename="../src/prototypator/mainwindow.cpp" line="110"/>
<source> exited with code </source>
<translation></translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.cpp" line="168"/>
<location filename="../src/prototypator/mainwindow.cpp" line="217"/>
<source>failed to start &apos;</source>
<translation></translation>
</message>
......
......@@ -14,65 +14,65 @@
<translation>Code c++ :</translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.ui" line="65"/>
<location filename="../src/prototypator/mainwindow.ui" line="68"/>
<source>&amp;Run</source>
<translation>&amp;Démarrer</translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.ui" line="68"/>
<location filename="../src/prototypator/mainwindow.ui" line="71"/>
<source>Ctrl+R</source>
<translation>Ctrl+D</translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.ui" line="79"/>
<location filename="../src/prototypator/mainwindow.ui" line="82"/>
<source>Result:</source>
<translation>Résultat :</translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.ui" line="90"/>
<location filename="../src/prototypator/mainwindow.ui" line="93"/>
<source>Compilation</source>
<translation>Compilation</translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.ui" line="144"/>
<location filename="../src/prototypator/mainwindow.ui" line="147"/>
<source>Input/output</source>
<translation>Entrée/sortie</translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.cpp" line="37"/>
<location filename="../src/prototypator/mainwindow.cpp" line="46"/>
<source>testing presence of cmake...
</source>
<translation>test de la présence de cmake...
</translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.cpp" line="41"/>
<location filename="../src/prototypator/mainwindow.cpp" line="50"/>
<source>running &apos;cmake&apos;...
</source>
<translation>démarrage de &apos;cmake&apos;...
</translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.cpp" line="45"/>
<location filename="../src/prototypator/mainwindow.cpp" line="54"/>
<source>running &apos;make&apos;...
</source>
<translation>démarrage de &apos;make&apos;...
</translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.cpp" line="49"/>
<location filename="../src/prototypator/mainwindow.cpp" line="58"/>
<source>running application...
</source>
<translation>démarrage de l&apos;application...
</translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.cpp" line="106"/>
<location filename="../src/prototypator/mainwindow.cpp" line="110"/>
<source> exited with code </source>
<translation> s&apos;est terminé avec le code </translation>
</message>
<message>
<location filename="../src/prototypator/mainwindow.cpp" line="168"/>
<location filename="../src/prototypator/mainwindow.cpp" line="217"/>
<source>failed to start &apos;</source>
<translation>impossible de démarrer &apos;</translation>
</message>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment