Skip to content

Commit

Permalink
Merge pull request #182 from PauloCarvalhoRJ/Issues20180311
Browse files Browse the repository at this point in the history
Issues20180311
  • Loading branch information
PauloCarvalhoRJ authored Mar 31, 2018
2 parents ccd25d3 + 928c8c0 commit 08fe64b
Show file tree
Hide file tree
Showing 32 changed files with 952 additions and 45 deletions.
10 changes: 7 additions & 3 deletions GammaRay.pro
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,9 @@ SOURCES += main.cpp\
calculator/calcscripting.cpp \
calculator/icalcpropertycollection.cpp \
calculator/calculatordialog.cpp \
calculator/icalcproperty.cpp
calculator/icalcproperty.cpp \
calculator/calclinenumberarea.cpp \
calculator/calccodeeditor.cpp

HEADERS += mainwindow.h \
domain/project.h \
Expand Down Expand Up @@ -397,7 +399,9 @@ HEADERS += mainwindow.h \
calculator/calcscripting.h \
calculator/icalcpropertycollection.h \
calculator/calculatordialog.h \
calculator/icalcproperty.h
calculator/icalcproperty.h \
calculator/calclinenumberarea.h \
calculator/calccodeeditor.h


FORMS += mainwindow.ui \
Expand Down Expand Up @@ -573,7 +577,7 @@ win32 {
# The application version
# Don't forget to update the Util::importSettingsFromPreviousVersion() method to
# enable the import of registry/user settings of previous versions.
VERSION = 4.0
VERSION = 4.3

# Define a preprocessor macro so we can get the application version in application code.
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
Expand Down
102 changes: 102 additions & 0 deletions calculator/calccodeeditor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#include "calccodeeditor.h"
#include "calclinenumberarea.h"
#include <QPainter>
#include <QTextBlock>

CalcCodeEditor::CalcCodeEditor(QWidget *parent) : QPlainTextEdit(parent)
{
lineNumberArea = new CalcLineNumberArea(this);

connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));

updateLineNumberAreaWidth(0);
highlightCurrentLine();
}

int CalcCodeEditor::lineNumberAreaWidth()
{
int digits = 1;
int max = qMax(1, blockCount());
while (max >= 10) {
max /= 10;
++digits;
}

int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;

return space;
}

void CalcCodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
{
setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
}

void CalcCodeEditor::updateLineNumberArea(const QRect &rect, int dy)
{
if (dy)
lineNumberArea->scroll(0, dy);
else
lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());

if (rect.contains(viewport()->rect()))
updateLineNumberAreaWidth(0);
}

void CalcCodeEditor::resizeEvent(QResizeEvent *e)
{
QPlainTextEdit::resizeEvent(e);

QRect cr = contentsRect();
lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
}

void CalcCodeEditor::highlightCurrentLine()
{
QList<QTextEdit::ExtraSelection> extraSelections;

if (!isReadOnly()) {
QTextEdit::ExtraSelection selection;

QColor lineColor = QColor(Qt::yellow).lighter(160);

selection.format.setBackground(lineColor);
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
selection.cursor = textCursor();
selection.cursor.clearSelection();
extraSelections.append(selection);
}

setExtraSelections(extraSelections);
}

void CalcCodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
{
QPainter painter(lineNumberArea);
painter.fillRect(event->rect(), Qt::lightGray);
QTextBlock block = firstVisibleBlock();
/* The lineNumberAreaPaintEvent() is called from LineNumberArea whenever it receives a paint event.
* We start off by painting the widget's background. */
int blockNumber = block.blockNumber();
int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
int bottom = top + (int) blockBoundingRect(block).height();
/*We will now loop through all visible lines and paint the line numbers in the extra area for each line.
* Notice that in a plain text edit each line will consist of one QTextBlock; though, if line wrapping
* is enabled, a line may span several rows in the text edit's viewport.
* We get the top and bottom y-coordinate of the first text block, and adjust these values by the height
* of the current text block in each iteration in the loop. */
while (block.isValid() && top <= event->rect().bottom()) {
if (block.isVisible() && bottom >= event->rect().top()) {
QString number = QString::number(blockNumber + 1);
painter.setPen(Qt::black);
painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
Qt::AlignRight, number);
}
block = block.next();
top = bottom;
bottom = top + (int) blockBoundingRect(block).height();
++blockNumber;
}
}
29 changes: 29 additions & 0 deletions calculator/calccodeeditor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef CALCCODEEDITOR_H
#define CALCCODEEDITOR_H

#include <QPlainTextEdit>

/** This class extends QPlainTextEdit to include script line numbers. */
class CalcCodeEditor : public QPlainTextEdit
{
Q_OBJECT

public:
CalcCodeEditor(QWidget *parent = 0);

void lineNumberAreaPaintEvent(QPaintEvent *event);
int lineNumberAreaWidth();

protected:
void resizeEvent(QResizeEvent *event) override;

private slots:
void updateLineNumberAreaWidth(int newBlockCount);
void highlightCurrentLine();
void updateLineNumberArea(const QRect &, int);

private:
QWidget *lineNumberArea;
};

#endif // CALCCODEEDITOR_H
18 changes: 18 additions & 0 deletions calculator/calclinenumberarea.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "calclinenumberarea.h"
#include "calccodeeditor.h"

CalcLineNumberArea::CalcLineNumberArea(CalcCodeEditor *editor) :
QWidget(editor)
{
codeEditor = editor;
}

QSize CalcLineNumberArea::sizeHint() const
{
return QSize(codeEditor->lineNumberAreaWidth(), 0);
}

void CalcLineNumberArea::paintEvent(QPaintEvent *event)
{
codeEditor->lineNumberAreaPaintEvent(event);
}
26 changes: 26 additions & 0 deletions calculator/calclinenumberarea.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef CALCLINENUMBERAREA_H
#define CALCLINENUMBERAREA_H

#include <QWidget>

class CalcCodeEditor;

/** This class is a widget that draws the script line numbers in the editor. */
class CalcLineNumberArea : public QWidget
{

Q_OBJECT

public:
explicit CalcLineNumberArea (CalcCodeEditor *editor);

QSize sizeHint() const override;

protected:
void paintEvent(QPaintEvent *event) override;

private:
CalcCodeEditor *codeEditor;
};

#endif // CALCLINENUMBERAREA_H
50 changes: 44 additions & 6 deletions calculator/calcscripting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct neigh : public exprtk::igeneric_function<T>
string_t tmpVarName(parameters[0]);
std::string varName;
varName.reserve(100); //this speeds up things a bit
for( int i = 0; i < tmpVarName.size(); ++i )
for( unsigned int i = 0; i < tmpVarName.size(); ++i )
varName.push_back( tmpVarName[i] );

//get the numerical parameters
Expand All @@ -45,15 +45,18 @@ struct neigh : public exprtk::igeneric_function<T>
//This is to speed up the resolution of property index a bit
int propIndex;
if( varNameFromPreviousCall != varName ){
propIndex = propCol->getCalcPropertyIndex( varName );
propIndex = propCol->getCalcPropertyIndexByScriptCompatibleName( varName );
propIndexFromPreviousCall = propIndex;
varNameFromPreviousCall = varName;
}else{
propIndex = propIndexFromPreviousCall;
}

//finally actually retrieve the neighbor value
return propCol->getNeighborValue( s_currentIteraction, propIndex, dI, dJ, dK );
if( propIndex < 0 )
return std::numeric_limits<double>::quiet_NaN();

//finally actually retrieve the neighbor value
return propCol->getNeighborValue( s_currentIteraction, propIndex, dI, dJ, dK );
}
};

Expand Down Expand Up @@ -83,6 +86,22 @@ CalcScripting::~CalcScripting()
delete m_registers;
}

/** LOCAL FUNCTION: Converts an absolute char postion into line number an column number in the expression text. */
void getLineAndColumnFromPosition( const QString& expression, int position, int& line, int& col ){
line = 1;
col = 1;
for( int i = 0; i < expression.size(); ++i ){
if( i == position )
return;
QChar c = expression.at(i);
if( c == '\n'){
++line;
col = 1;
}
++col;
}
}

bool CalcScripting::doCalc( const QString & script )
{
if( m_isBlocked ){
Expand All @@ -94,6 +113,7 @@ bool CalcScripting::doCalc( const QString & script )
typedef exprtk::symbol_table<double> symbol_table_t;
typedef exprtk::expression<double> expression_t;
typedef exprtk::parser<double> parser_t;
typedef exprtk::parser_error::type error_t;

//The registers to hold the spatial and topological coordinates.
double _X_, _Y_, _Z_;
Expand Down Expand Up @@ -128,15 +148,33 @@ bool CalcScripting::doCalc( const QString & script )
//Bind constant symbols (e.g. pi).
symbol_table.add_constants();

//Bind vector functions like avg(), sort(), etc...
exprtk::rtl::vecops::package<double> vecops_package;
symbol_table.add_package ( vecops_package );

//Register the variable bind table.
expression_t expression;
expression.register_symbol_table(symbol_table);

//Parse the script against the variable bind table.
parser_t parser;
if( ! parser.compile(expression_string, expression) ){
m_lastError = QString( parser.error().c_str() );
return false;
m_lastError = QString( parser.error().c_str() ) + "<br><br>\n\nError details:<br>\n";
//retrive compilation error details
for (std::size_t i = 0; i < parser.error_count(); ++i){
error_t error = parser.get_error(i);
QString tmp;
int lin, col;
getLineAndColumnFromPosition( script, error.token.position, lin, col);
tmp.sprintf("%2d) %14s @ line=%3d, col=%3d: %s; <BR>\n",
(int)i+1,
exprtk::parser_error::to_str(error.mode).c_str(),
lin,
col,
error.diagnostic.c_str());
m_lastError += tmp + '\n';
}
return false;
}

//Evaluate the script against all data records.
Expand Down
9 changes: 8 additions & 1 deletion calculator/calculatordialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@
</layout>
</item>
<item>
<widget class="QPlainTextEdit" name="txtScript">
<widget class="CalcCodeEditor" name="txtScript">
<property name="font">
<font>
<family>Courier New</family>
Expand Down Expand Up @@ -212,6 +212,13 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>CalcCodeEditor</class>
<extends>QPlainTextEdit</extends>
<header>calculator/calccodeeditor.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="calcresources.qrc"/>
</resources>
Expand Down
4 changes: 3 additions & 1 deletion calculator/icalcproperty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ QString ICalcProperty::getScriptCompatibleName()
compatibleName = compatibleName.replace( ' ', '_' );
compatibleName = compatibleName.replace( '(', '_' );
compatibleName = compatibleName.replace( ')', '_' );
return compatibleName;
compatibleName = compatibleName.replace( '-', '_' );
compatibleName = compatibleName.replace( '+', '_' );
return compatibleName;
}
12 changes: 12 additions & 0 deletions calculator/icalcpropertycollection.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
#include "icalcpropertycollection.h"
#include "icalcproperty.h"

ICalcPropertyCollection::ICalcPropertyCollection()
{
}

int ICalcPropertyCollection::getCalcPropertyIndexByScriptCompatibleName(const std::string& name)
{
int n = getCalcPropertyCount();
for( int i = 0; i < n; ++i){
ICalcProperty* prop = getCalcProperty( i );
if( prop->getScriptCompatibleName() == QString( name.c_str() ))
return i;
}
return -1;
}
12 changes: 10 additions & 2 deletions calculator/icalcpropertycollection.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,27 @@ class ICalcPropertyCollection
*/
virtual void getSpatialAndTopologicalCoordinates( int iRecord, double& x, double& y, double& z, int& i, int& j, int& k ) = 0;

/** Returns a property's index given its name. */
/** Returns a property's index given its name.
* Implementations should return -1 if the property is not found.
*/
virtual int getCalcPropertyIndex( const std::string& name ) = 0;

/**
* Returns a neighbouring value. This only makes sense with property collections that have topology.
* Non-topological implementations (e.g. point sets) or calls to non-existing neighbours (e.g. at edges) should return NaN.
* Non-topological implementations (e.g. point sets) or calls to non-existing neighbours (e.g. at edges)
* should return std::numeric_limits<double>::quiet_NaN();.
* @param iRecord Number of data line.
* @param iVar Index of the variable to retrieve value.
* @param dI Relative topological position, e.g. -1.
* @param dJ Relative topological position.
* @param dK Relative topological position.
*/
virtual double getNeighborValue( int iRecord, int iVar, int dI, int dJ, int dK ) = 0;

/** Returns a property's index given its script-compatible name (with illegal characters replaced
* by underscores). Returns -1 if the property is not found.
*/
int getCalcPropertyIndexByScriptCompatibleName( const std::string& name );
};

#endif // ICALCPROPERTYCOLLECTION_H
Binary file modified docs/GammaRayManual.docx
Binary file not shown.
Loading

0 comments on commit 08fe64b

Please sign in to comment.