Spreadsheet: Removed own expression parser and instead use the one in App.

This commit is contained in:
Eivind Kvedalen
2016-03-17 00:32:00 +01:00
committed by wmayer
parent 4f7470c5e8
commit ae111d11b5
33 changed files with 121 additions and 3666 deletions

View File

@@ -151,17 +151,17 @@ App::DocumentObjectExecReturn *FeatureViewSpreadsheet::execute(void)
float coloffset = 0.0;
float cellheight = 100;
float cellwidth = 100;
std::string celltext;
std::string celltext;
Spreadsheet::Sheet* sheet = static_cast<Spreadsheet::Sheet*>(link);
std::vector<std::string> skiplist;
for (std::vector<std::string>::const_iterator col = columns.begin(); col != columns.end(); ++col) {
for (std::vector<std::string>::const_iterator col = columns.begin(); col != columns.end(); ++col) {
// create a group for each column
result << " <g id=\"" << ViewName << "_col" << (*col) << "\">" << endl;
for (std::vector<int>::const_iterator row = rows.begin(); row != rows.end(); ++row) {
// get cell size
std::stringstream srow;
srow << (*row);
Spreadsheet::CellAddress address((*col) + srow.str());
App::CellAddress address((*col) + srow.str());
cellwidth = sheet->getColumnWidth(address.col());
cellheight = sheet->getRowHeight(address.row());
celltext = "";
@@ -216,7 +216,7 @@ App::DocumentObjectExecReturn *FeatureViewSpreadsheet::execute(void)
if (cell->getSpans(rowspan,colspan)) {
for (int i=0; i<colspan; ++i) {
for (int j=0; j<rowspan; ++j) {
Spreadsheet::CellAddress nextcell(address.row()+j,address.col()+i);
App::CellAddress nextcell(address.row()+j,address.col()+i);
if (i > 0)
cellwidth = cellwidth + sheet->getColumnWidth(nextcell.col());
if (j > 0)
@@ -227,7 +227,7 @@ App::DocumentObjectExecReturn *FeatureViewSpreadsheet::execute(void)
}
}
cell->getAlignment(alignment);
}
}
// skip cell if found in skiplist
if (std::find(skiplist.begin(), skiplist.end(), address.toString()) == skiplist.end()) {
result << " <rect x=\"" << coloffset << "\" y=\"" << rowoffset << "\" width=\"" << cellwidth
@@ -241,7 +241,7 @@ App::DocumentObjectExecReturn *FeatureViewSpreadsheet::execute(void)
result << " <text text-anchor=\"end\" style=\"" << textstyle << "\" x=\"" << coloffset + (cellwidth - FontSize.getValue()/2) << "\" y=\"" << rowoffset + 0.75 * cellheight << "\" font-family=\"" ;
result << Font.getValue() << "\"" << " font-size=\"" << FontSize.getValue() << "\""
<< " fill=\"" << fcolor << "\">" << celltext << "</text>" << endl;
}
}
rowoffset = rowoffset + cellheight;
}
result << " </g>" << endl;

View File

@@ -20,8 +20,6 @@
#include <Base/Console.h>
#include "Sheet.h"
#include "SpreadsheetExpression.h"
namespace Spreadsheet {
class Module : public Py::ExtensionModule<Module>
@@ -46,8 +44,6 @@ PyMODINIT_FUNC initSpreadsheet() {
Spreadsheet::PropertySheet::init();
Spreadsheet::Sheet::init();
Spreadsheet::AggregateFunctionExpression::init();
Spreadsheet::RangeExpression::init();
new Spreadsheet::Module();
Base::Console().Log("Loading Spreadsheet module... done\n");

View File

@@ -17,8 +17,6 @@ set(Spreadsheet_LIBS
)
set(Spreadsheet_SRCS
SpreadsheetExpression.cpp
SpreadsheetExpression.h
Cell.cpp
Cell.h
DisplayUnit.h
@@ -44,8 +42,6 @@ set(Spreadsheet_SRCS
SheetObserver.h
Utils.cpp
Utils.h
Range.h
Range.cpp
AppSpreadsheet.cpp
)

View File

@@ -30,7 +30,7 @@
#include <boost/tokenizer.hpp>
#include <Base/Reader.h>
#include <Base/Writer.h>
#include "SpreadsheetExpression.h"
#include <App/Expression.h>
#include "Sheet.h"
#include <iomanip>
@@ -38,6 +38,7 @@
#define __func__ __FUNCTION__
#endif
using namespace App;
using namespace Base;
using namespace Spreadsheet;
@@ -216,7 +217,7 @@ void Cell::setContent(const char * value)
if (value != 0) {
if (*value == '=') {
try {
expr = Spreadsheet::ExpressionParser::parse(owner->sheet(), value + 1);
expr = App::ExpressionParser::parse(owner->sheet(), value + 1);
}
catch (Base::Exception & e) {
expr = new App::StringExpression(owner->sheet(), value);

View File

@@ -26,6 +26,7 @@
#include <string>
#include <set>
#include <App/Material.h>
#include <App/Range.h>
#include "DisplayUnit.h"
#include "Utils.h"
@@ -49,7 +50,7 @@ class SpreadsheetExport Cell {
public:
Cell(const CellAddress & _address, PropertySheet * _owner);
Cell(const App::CellAddress & _address, PropertySheet * _owner);
Cell(const Cell & other);
@@ -101,7 +102,7 @@ public:
bool hasException() const { return isUsed(EXCEPTION_SET) || isUsed(PARSE_EXCEPTION_SET) || isUsed(RESOLVE_EXCEPTION_SET); }
void moveAbsolute(CellAddress newAddress);
void moveAbsolute(App::CellAddress newAddress);
void restore(Base::XMLReader &reader);
@@ -117,7 +118,7 @@ public:
void visit(App::ExpressionVisitor & v);
CellAddress getAddress() const { return address; }
App::CellAddress getAddress() const { return address; }
/* Alignment */
static const int ALIGNMENT_LEFT;
@@ -172,7 +173,7 @@ private:
static const int PARSE_EXCEPTION_SET;
static const int RESOLVE_EXCEPTION_SET;
CellAddress address;
App::CellAddress address;
PropertySheet * owner;
int used;
@@ -187,7 +188,7 @@ private:
int rowSpan;
int colSpan;
std::string exceptionStr;
CellAddress anchor;
App::CellAddress anchor;
};
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,75 +0,0 @@
/* A Bison parser, made by GNU Bison 2.5. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
under terms of your choice, so long as that work isn't itself a
parser generator using the skeleton or a modified version thereof
as a parser skeleton. Alternatively, if you modify or redistribute
the parser skeleton itself, you may (at your option) remove this
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
/* Tokens. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
FUNC = 258,
ONE = 259,
NUM = 260,
IDENTIFIER = 261,
UNIT = 262,
INTEGER = 263,
CONSTANT = 264,
CELLADDRESS = 265,
EQ = 266,
NEQ = 267,
LT = 268,
GT = 269,
GTE = 270,
LTE = 271,
STRING = 272,
MINUSSIGN = 273,
PROPERTY_REF = 274,
DOCUMENT = 275,
OBJECT = 276,
EXPONENT = 277,
NEG = 278,
POS = 279
};
#endif
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
extern YYSTYPE yylval;

View File

@@ -1,187 +0,0 @@
/* Parser for the FreeCAD Units language */
/* (c) 2010 Juergen Riegel LGPL */
/* (c) 2015 Eivind Kvedalen LGPL */
/* Represents the many different ways we can access our data */
%{
#define YYSTYPE App::ExpressionParser::semantic_type
std::stack<FunctionExpression::Function> functions; /**< Function identifier */
//#define YYSTYPE yystype
#define yyparse ExpressionParser_yyparse
#define yyerror ExpressionParser_yyerror
%}
/* Bison declarations. */
%token FUNC
%token ONE
%token NUM
%token IDENTIFIER
%token UNIT
%token INTEGER
%token CONSTANT
%token CELLADDRESS
%token EQ NEQ LT GT GTE LTE
%token STRING MINUSSIGN PROPERTY_REF
%token DOCUMENT OBJECT
%token EXPONENT
%type <arguments> args
%type <expr> input exp unit_exp cond
%type <quantity> UNIT
%type <string> STRING IDENTIFIER CELLADDRESS
%type <ivalue> INTEGER
%type <string> PROPERTY_REF
%type <fvalue> ONE
%type <fvalue> NUM
%type <constant> CONSTANT
%type <expr> num
%type <expr> basic_num
%type <expr> range
%type <path> identifier
%type <components> path subpath
%type <func> FUNC
%type <string_or_identifier> document
%type <string_or_identifier> object
%type <ivalue> integer
%left ONE
%left NUM
%left INTEGER
%left CONSTANT
%left EQ NEQ LT GT GTE LTE
%left '?' ':'
%left MINUSSIGN '+'
%left '*' '/'
%left NEG /* negation--unary minus */
%left POS /* unary plus */
%right '^' /* exponentiation */
%right EXPONENT
%destructor { delete $$; } exp cond unit_exp
%destructor { std::vector<Expression*>::const_iterator i = $$.begin(); while (i != $$.end()) { delete *i; ++i; } } args
%start input
%%
input: exp { ScanResult = $1; valueExpression = true; }
| unit_exp { ScanResult = $1; unitExpression = true; }
;
exp: num { $$ = $1; }
| STRING { $$ = new StringExpression(DocumentObject, $1); }
| identifier { $$ = new VariableExpression(DocumentObject, $1); }
| MINUSSIGN exp %prec NEG { $$ = new OperatorExpression(DocumentObject, $2, OperatorExpression::NEG, new NumberExpression(DocumentObject, -1)); }
| '+' exp %prec POS { $$ = new OperatorExpression(DocumentObject, $2, OperatorExpression::POS, new NumberExpression(DocumentObject, 1)); }
| exp '+' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::ADD, $3); }
| exp MINUSSIGN exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::SUB, $3); }
| exp '*' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); }
| exp '/' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
| exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
| exp '^' exp %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); }
| '(' exp ')' { $$ = $2; }
| FUNC args ')' { $$ = new AggregateFunctionExpression(DocumentObject, $1, $2); }
| cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); }
;
basic_num: ONE { $$ = new NumberExpression(DocumentObject, $1); }
| NUM { $$ = new NumberExpression(DocumentObject, $1); }
| INTEGER { $$ = new NumberExpression(DocumentObject, (double)$1); }
;
num: basic_num { $$ = $1; }
| CONSTANT { $$ = new ConstantExpression(DocumentObject, $1.name, $1.fvalue); }
| basic_num unit_exp %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::UNIT, $2); }
| CONSTANT unit_exp { $$ = new OperatorExpression(DocumentObject, new ConstantExpression(DocumentObject, $1.name, $1.fvalue), OperatorExpression::UNIT, $2); }
;
args: exp { $$.push_back($1); }
| range { $$.push_back($1); }
| args ',' exp { $1.push_back($3); $$ = $1; }
| args ';' exp { $1.push_back($3); $$ = $1; }
;
range: CELLADDRESS ':' CELLADDRESS { $$ = new RangeExpression(DocumentObject, $1, $3); }
| CELLADDRESS ':' IDENTIFIER { $$ = new RangeExpression(DocumentObject, $1, $3); }
| IDENTIFIER ':' CELLADDRESS { $$ = new RangeExpression(DocumentObject, $1, $3); }
| IDENTIFIER ':' IDENTIFIER { $$ = new RangeExpression(DocumentObject, $1, $3); }
;
cond: exp EQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::EQ, $3); }
| exp NEQ exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::NEQ, $3); }
| exp LT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LT, $3); }
| exp GT exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GT, $3); }
| exp GTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::GTE, $3); }
| exp LTE exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::LTE, $3); }
;
unit_exp: UNIT { $$ = new UnitExpression(DocumentObject, $1.scaler, $1.unitStr ); }
| ONE '/' unit_exp { $$ = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, $1), OperatorExpression::DIV, $3); }
| unit_exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
| unit_exp '*' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); }
| unit_exp '^' basic_num %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); }
| unit_exp '^' MINUSSIGN basic_num %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new OperatorExpression(DocumentObject, $4, OperatorExpression::NEG, new NumberExpression(DocumentObject, -1))); }
| '(' unit_exp ')' { $$ = $2; }
;
identifier: path { /* Path to property within document object */
$$ = ObjectIdentifier(DocumentObject);
$$.addComponents($1);
}
| object '.' path { /* Path to property within document object */
$$ = ObjectIdentifier(DocumentObject);
$$.setDocumentObjectName($1, true);
$$.addComponents($3);
}
| document '#' path { /* Path to property from an external document, within a named document object */
$$ = ObjectIdentifier(DocumentObject);
$$.setDocumentName($1, true);
$$.addComponents($3);
}
| document '#' object '.' path { /* Path to property from an external document, within a named document object */
$$ = ObjectIdentifier(DocumentObject);
$$.setDocumentName($1, true);
$$.setDocumentObjectName($3, true);
$$.addComponents($5);
}
;
integer: INTEGER { $$ = $1; }
| ONE { $$ = $1; }
;
path: IDENTIFIER { $$.push_front(ObjectIdentifier::Component::SimpleComponent($1)); }
| CELLADDRESS { $$.push_front(ObjectIdentifier::Component::SimpleComponent($1)); }
| IDENTIFIER '[' integer ']' { $$.push_front(ObjectIdentifier::Component::ArrayComponent($1, $3)); }
| IDENTIFIER '[' integer ']' '.' subpath { $6.push_front(ObjectIdentifier::Component::ArrayComponent($1, $3)); $$ = $6; }
| IDENTIFIER '[' STRING ']' { $$.push_front(ObjectIdentifier::Component::MapComponent($1, ObjectIdentifier::String($3, true))); }
| IDENTIFIER '[' IDENTIFIER ']' { $$.push_front(ObjectIdentifier::Component::MapComponent($1, $3)); }
| IDENTIFIER '[' STRING ']' '.' subpath { $6.push_front(ObjectIdentifier::Component::MapComponent($1, ObjectIdentifier::String($3, true))); $$ = $6; }
| IDENTIFIER '[' IDENTIFIER ']' '.' subpath { $6.push_front(ObjectIdentifier::Component::MapComponent($1, $3)); $$ = $6; }
| IDENTIFIER '.' subpath { $3.push_front(ObjectIdentifier::Component::SimpleComponent($1)); $$ = $3; }
;
subpath: IDENTIFIER { $$.push_front(ObjectIdentifier::Component::SimpleComponent($1)); }
| STRING { $$.push_front(ObjectIdentifier::Component::SimpleComponent($1)); }
| CELLADDRESS { $$.push_front(ObjectIdentifier::Component::SimpleComponent($1)); }
| IDENTIFIER '[' integer ']' { $$.push_front(ObjectIdentifier::Component::ArrayComponent($1, $3)); }
| IDENTIFIER '[' integer ']' '.' subpath { $6.push_front(ObjectIdentifier::Component::ArrayComponent($1, $3)); $$ = $6; }
| IDENTIFIER '[' STRING ']' { $$.push_front(ObjectIdentifier::Component::MapComponent($1, ObjectIdentifier::String($3, true))); }
| IDENTIFIER '[' IDENTIFIER ']' { $$.push_front(ObjectIdentifier::Component::MapComponent($1, $3)); }
| IDENTIFIER '[' STRING ']' '.' subpath { $6.push_front(ObjectIdentifier::Component::MapComponent($1, ObjectIdentifier::String($3, true))); $$ = $6; }
| IDENTIFIER '[' IDENTIFIER ']' '.' subpath { $6.push_front(ObjectIdentifier::Component::MapComponent($1, $3)); $$ = $6; }
| IDENTIFIER '.' subpath { $3.push_front(ObjectIdentifier::Component::SimpleComponent($1)); $$ = $3; }
;
document: STRING { $$ = ObjectIdentifier::String($1, true); }
| IDENTIFIER { $$ = ObjectIdentifier::String($1); }
;
object: STRING { $$ = ObjectIdentifier::String($1, true); }
| CELLADDRESS { $$ = ObjectIdentifier::String($1, true); }
;
%%

View File

@@ -28,6 +28,7 @@
#include "PropertyColumnWidths.h"
#include <Base/Writer.h>
#include <Base/Reader.h>
#include <App/Range.h>
#include "Utils.h"
#include <PropertyColumnWidthsPy.h>
@@ -132,7 +133,7 @@ void PropertyColumnWidths::Restore(Base::XMLReader &reader)
try {
if (name && width) {
int col = decodeColumn(name);
int col = App::decodeColumn(name);
int colWidth = atoi(width);
setValue(col, colWidth);

View File

@@ -28,6 +28,7 @@
#include "PropertyRowHeights.h"
#include <Base/Writer.h>
#include <Base/Reader.h>
#include <App/Range.h>
#include "Utils.h"
#include <PropertyRowHeightsPy.h>
@@ -126,7 +127,7 @@ void PropertyRowHeights::Restore(Base::XMLReader &reader)
try {
if (name && height) {
int row = decodeRow(name);
int row = App::decodeRow(name);
int rowHeight = atoi(height);
setValue(row, rowHeight);

View File

@@ -38,7 +38,6 @@
#include <Base/PyObjectBase.h>
#include "PropertySheet.h"
#include "Sheet.h"
#include "SpreadsheetExpression.h"
#include "Utils.h"
#include <PropertySheetPy.h>
#include <App/ExpressionVisitors.h>
@@ -158,7 +157,7 @@ bool PropertySheet::isValidAlias(const std::string &candidate)
const boost::sub_match<const char *> rowstr = cm[2];
// A valid cell address?
if (Spreadsheet::validRow(rowstr.str()) >= 0 && Spreadsheet::validColumn(colstr.str()) >= 0)
if (App::validRow(rowstr.str()) >= 0 && App::validColumn(colstr.str()) >= 0)
return false;
}
return true;

View File

@@ -53,55 +53,55 @@ public:
virtual void Restore(Base::XMLReader & reader);
Cell *createCell(CellAddress address);
Cell *createCell(App::CellAddress address);
void setValue() { }
void setContent(CellAddress address, const char * value);
void setContent(App::CellAddress address, const char * value);
void setAlignment(CellAddress address, int _alignment);
void setAlignment(App::CellAddress address, int _alignment);
void setStyle(CellAddress address, const std::set<std::string> & _style);
void setStyle(App::CellAddress address, const std::set<std::string> & _style);
void setForeground(CellAddress address, const App::Color &color);
void setForeground(App::CellAddress address, const App::Color &color);
void setBackground(CellAddress address, const App::Color &color);
void setBackground(App::CellAddress address, const App::Color &color);
void setDisplayUnit(CellAddress address, const std::string & unit);
void setDisplayUnit(App::CellAddress address, const std::string & unit);
void setAlias(CellAddress address, const std::string &alias);
void setAlias(App::CellAddress address, const std::string &alias);
void setComputedUnit(CellAddress address, const Base::Unit & unit);
void setComputedUnit(App::CellAddress address, const Base::Unit & unit);
void setSpans(CellAddress address, int rows, int columns);
void setSpans(App::CellAddress address, int rows, int columns);
void clear(CellAddress address);
void clear(App::CellAddress address);
void clear();
Cell * getValue(CellAddress key);
Cell * getValue(App::CellAddress key);
const Cell * getValue(CellAddress key) const;
const Cell * getValue(App::CellAddress key) const;
const Cell * getValueFromAlias(const std::string &alias) const;
bool isValidAlias(const std::string &candidate);
std::set<CellAddress> getUsedCells() const;
std::set<App::CellAddress> getUsedCells() const;
Sheet * sheet() const { return owner; }
const std::set<CellAddress> & getDirty() { return dirty; }
const std::set<App::CellAddress> & getDirty() { return dirty; }
void setDirty(CellAddress address);
void setDirty(App::CellAddress address);
void clearDirty(CellAddress key) { dirty.erase(key); }
void clearDirty(App::CellAddress key) { dirty.erase(key); }
void clearDirty() { dirty.clear(); purgeTouched(); }
bool isDirty() const { return dirty.size() > 0; }
void moveCell(CellAddress currPos, CellAddress newPos, std::map<App::ObjectIdentifier, App::ObjectIdentifier> &renames);
void moveCell(App::CellAddress currPos, App::CellAddress newPos, std::map<App::ObjectIdentifier, App::ObjectIdentifier> &renames);
void insertRows(int row, int count);
@@ -113,23 +113,23 @@ public:
virtual unsigned int getMemSize (void) const;
bool mergeCells(CellAddress from, CellAddress to);
bool mergeCells(App::CellAddress from, App::CellAddress to);
void splitCell(CellAddress address);
void splitCell(App::CellAddress address);
void getSpans(CellAddress address, int &rows, int &cols) const;
void getSpans(App::CellAddress address, int &rows, int &cols) const;
bool isMergedCell(CellAddress address) const;
bool isMergedCell(App::CellAddress address) const;
bool isHidden(CellAddress address) const;
bool isHidden(App::CellAddress address) const;
const std::set< CellAddress > & getDeps(const std::string & name) const;
const std::set< App::CellAddress > & getDeps(const std::string & name) const;
const std::set<std::string> &getDeps(CellAddress pos) const;
const std::set<std::string> &getDeps(App::CellAddress pos) const;
const std::set<App::DocumentObject*> & getDocDeps() const { return docDeps; }
void recomputeDependencies(CellAddress key);
void recomputeDependencies(App::CellAddress key);
PyObject *getPyObject(void);
@@ -161,24 +161,24 @@ private:
friend class Sheet;
Cell *cellAt(CellAddress address);
Cell *cellAt(App::CellAddress address);
Cell *nonNullCellAt(CellAddress address);
Cell *nonNullCellAt(App::CellAddress address);
const Cell *cellAt(CellAddress address) const;
const Cell *cellAt(App::CellAddress address) const;
bool colSortFunc(const CellAddress &a, const CellAddress &b);
bool colSortFunc(const App::CellAddress &a, const App::CellAddress &b);
bool rowSortFunc(const CellAddress &a, const CellAddress &b);
bool rowSortFunc(const App::CellAddress &a, const App::CellAddress &b);
/*! Set of cells that have been marked dirty */
std::set<CellAddress> dirty;
std::set<App::CellAddress> dirty;
/*! Cell data in this property */
std::map<CellAddress, Cell*> data;
std::map<App::CellAddress, Cell*> data;
/*! Merged cells; cell -> anchor cell */
std::map<CellAddress, CellAddress> mergedCells;
std::map<App::CellAddress, App::CellAddress> mergedCells;
/*! Owner of this property */
Sheet * owner;
@@ -187,9 +187,9 @@ private:
* Cell dependency tracking
*/
void addDependencies(CellAddress key);
void addDependencies(App::CellAddress key);
void removeDependencies(CellAddress key);
void removeDependencies(App::CellAddress key);
void recomputeDependants(const App::Property * prop);
@@ -200,18 +200,18 @@ private:
/*! Cell dependencies, i.e when a change occurs to property given in key,
the set of addresses needs to be recomputed.
*/
std::map<std::string, std::set< CellAddress > > propertyNameToCellMap;
std::map<std::string, std::set< App::CellAddress > > propertyNameToCellMap;
/*! Properties this cell depends on */
std::map<CellAddress, std::set< std::string > > cellToPropertyNameMap;
std::map<App::CellAddress, std::set< std::string > > cellToPropertyNameMap;
/*! Cell dependencies, i.e when a change occurs to documentObject given in key,
the set of addresses needs to be recomputed.
*/
std::map<std::string, std::set< CellAddress > > documentObjectToCellMap;
std::map<std::string, std::set< App::CellAddress > > documentObjectToCellMap;
/*! DocumentObject this cell depends on */
std::map<CellAddress, std::set< std::string > > cellToDocumentObjectMap;
std::map<App::CellAddress, std::set< std::string > > cellToDocumentObjectMap;
/*! Other document objects the sheet depends on */
std::set<App::DocumentObject*> docDeps;
@@ -223,10 +223,10 @@ private:
std::map<const App::Document*, std::string> documentName;
/*! Mapping of cell position to alias property */
std::map<CellAddress, std::string> aliasProp;
std::map<App::CellAddress, std::string> aliasProp;
/*! Mapping of alias property to cell position */
std::map<std::string, CellAddress> revAliasProp;
std::map<std::string, App::CellAddress> revAliasProp;
/*! The associated python object */
Py::Object PythonObject;

View File

@@ -1,96 +0,0 @@
/***************************************************************************
* Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#include "Range.h"
#include <assert.h>
#include <string.h>
using namespace Spreadsheet;
Range::Range(const char * range)
{
std::string from;
std::string to;
assert(range != NULL);
if (strchr(range, ':') == NULL) {
from = range;
to = range;
}
else {
std::string s = range;
from = s.substr(0, s.find(':'));
to = s.substr(s.find(':') + 1);
}
CellAddress begin(from);
CellAddress end(to);
row_begin = begin.row();
col_begin = begin.col();
row_end = end.row();
col_end = end.col();
row_curr = row_begin;
col_curr = col_begin;
}
Range::Range(int _row_begin, int _col_begin, int _row_end, int _col_end)
: row_curr(_row_begin)
, col_curr(_col_begin)
, row_begin(_row_begin)
, col_begin(_col_begin)
, row_end(_row_end)
, col_end(_col_end)
{
}
Range::Range(const CellAddress &from, const CellAddress &to)
: row_curr(from.row())
, col_curr(from.col())
, row_begin(from.row())
, col_begin(from.col())
, row_end(to.row())
, col_end(to.col())
{
}
bool Range::next()
{
if (row_curr < row_end) {
row_curr++;
return true;
}
if (col_curr < col_end) {
if (row_curr == row_end + 1)
return false;
row_curr = row_begin;
++col_curr;
return true;
}
return false;
}

View File

@@ -1,91 +0,0 @@
/***************************************************************************
* Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef RANGE_H
#define RANGE_H
#include "Utils.h"
namespace Spreadsheet {
/**
* @brief The Range class is a spreadsheet range iterator. It takes
* a starting (row, col) and an ending (row, col). Notice that ranges
* are always at least one element. The next() functions is therefore
* used e.g as follows:
*
* do {
* ...
* while (range.next());
*
*/
class SpreadsheetExport Range {
public:
Range(const char *range);
Range(int _row_begin, int _col_begin, int _row_end, int _col_end);
Range(const CellAddress & from, const CellAddress & to);
bool next();
/** Current row */
inline int row() const { return row_curr; }
/** Current column */
inline int column() const { return col_curr; }
/** Position of start of range */
inline CellAddress from() const { return CellAddress(row_begin, col_begin); }
/** Position of end of range */
inline CellAddress to() const { return CellAddress(row_end, col_end); }
/** Start of range as a string */
inline std::string fromCellString() const { return CellAddress(row_begin, col_begin).toString(); }
/** End of range as a string */
inline std::string toCellString() const { return CellAddress(row_end, col_end).toString(); }
/** Current cell as a string */
inline std::string address() const { return CellAddress(row_curr, col_curr).toString(); }
/** The raneg as a string */
inline std::string rangeString() const {
return CellAddress(row_begin, col_begin).toString() + ":" + CellAddress(row_end, col_end).toString();
}
CellAddress operator*() const { return CellAddress(row_curr, col_curr); }
/** Number of elements in range */
inline int size() const { return (row_end - row_begin + 1) * (col_end - col_begin + 1); }
private:
int row_curr, col_curr;
int row_begin, col_begin;
int row_end, col_end;
};
}
#endif // RANGE_H

View File

@@ -38,11 +38,9 @@
#include <Base/Reader.h>
#include <Base/Writer.h>
#include <Base/Tools.h>
#include "SpreadsheetExpression.h"
#include "Sheet.h"
#include "SheetObserver.h"
#include "Utils.h"
#include "Range.h"
#include "SheetPy.h"
#include <ostream>
#include <fstream>

View File

@@ -36,6 +36,7 @@
#include <App/PropertyStandard.h>
#include <App/DynamicProperty.h>
#include <App/Material.h>
#include <App/Range.h>
#include <Base/Unit.h>
#include <map>
#include "PropertySheet.h"
@@ -43,12 +44,12 @@
#include "PropertyRowHeights.h"
#include "Utils.h"
namespace Spreadsheet
{
class Sheet;
class Cell;
class Range;
class SheetObserver;
/** Spreadsheet quantity property
@@ -86,25 +87,25 @@ public:
bool exportToFile(const std::string & filename, char delimiter = '\t', char quoteChar = '\0', char escapeChar = '\\') const;
bool mergeCells(const Range &range);
bool mergeCells(const App::Range &range);
void splitCell(CellAddress address);
void splitCell(App::CellAddress address);
Cell * getCell(CellAddress address);
Cell * getCell(App::CellAddress address);
Cell *getNewCell(CellAddress address);
Cell *getNewCell(App::CellAddress address);
void setCell(const char *address, const char *value);
void setCell(CellAddress address, const char *value);
void setCell(App::CellAddress address, const char *value);
void clearAll();
void clear(CellAddress address, bool all = true);
void clear(App::CellAddress address, bool all = true);
void getSpans(CellAddress address, int & rows, int & cols) const;
void getSpans(App::CellAddress address, int & rows, int & cols) const;
bool isMergedCell(CellAddress address) const;
bool isMergedCell(App::CellAddress address) const;
void setColumnWidth(int col, int width);
@@ -124,31 +125,31 @@ public:
void removeRows(int row, int count);
void setContent(CellAddress address, const char * value);
void setContent(App::CellAddress address, const char * value);
void setAlignment(CellAddress address, int alignment);
void setAlignment(App::CellAddress address, int alignment);
void setStyle(CellAddress address, const std::set<std::string> & style);
void setStyle(App::CellAddress address, const std::set<std::string> & style);
void setForeground(CellAddress address, const App::Color &color);
void setForeground(App::CellAddress address, const App::Color &color);
void setBackground(CellAddress address, const App::Color &color);
void setBackground(App::CellAddress address, const App::Color &color);
void setDisplayUnit(CellAddress address, const std::string & unit);
void setDisplayUnit(App::CellAddress address, const std::string & unit);
void setComputedUnit(CellAddress address, const Base::Unit & unit);
void setComputedUnit(App::CellAddress address, const Base::Unit & unit);
void setAlias(CellAddress address, const std::string & alias);
void setAlias(App::CellAddress address, const std::string & alias);
std::string getAddressFromAlias(const std::string & alias) const;
bool isValidAlias(const std::string &candidate);
void setSpans(CellAddress address, int rows, int columns);
void setSpans(App::CellAddress address, int rows, int columns);
std::set<std::string> dependsOn(CellAddress address) const;
std::set<std::string> dependsOn(App::CellAddress address) const;
void providesTo(CellAddress address, std::set<std::string> & result) const;
void providesTo(App::CellAddress address, std::set<std::string> & result) const;
PyObject *getPyObject();
@@ -160,7 +161,7 @@ public:
App::DocumentObjectExecReturn *execute(void);
void getCellAddress(const App::Property *prop, CellAddress &address);
void getCellAddress(const App::Property *prop, App::CellAddress &address);
std::map<int, int> getColumnWidths() const;
@@ -168,9 +169,9 @@ public:
// Signals
boost::signal<void (Spreadsheet::CellAddress)> cellUpdated;
boost::signal<void (App::CellAddress)> cellUpdated;
boost::signal<void (Spreadsheet::CellAddress)> cellSpanChanged;
boost::signal<void (App::CellAddress)> cellSpanChanged;
boost::signal<void (int, int)> columnWidthChanged;
@@ -231,7 +232,7 @@ public:
protected:
void providesTo(CellAddress address, std::set<CellAddress> & result) const;
void providesTo(App::CellAddress address, std::set<App::CellAddress> & result) const;
void onDocumentRestored();
@@ -239,25 +240,25 @@ protected:
void onRenamedDocument(const App::Document & document);
void recomputeCell(CellAddress p);
void recomputeCell(App::CellAddress p);
App::Property *getProperty(CellAddress key) const;
App::Property *getProperty(App::CellAddress key) const;
App::Property *getProperty(const char * addr) const;
void updateAlias(CellAddress key);
void updateAlias(App::CellAddress key);
void updateProperty(CellAddress key);
void updateProperty(App::CellAddress key);
App::Property *setStringProperty(CellAddress key, const std::string & value) ;
App::Property *setStringProperty(App::CellAddress key, const std::string & value) ;
App::Property *setFloatProperty(CellAddress key, double value);
App::Property *setFloatProperty(App::CellAddress key, double value);
App::Property *setQuantityProperty(CellAddress key, double value, const Base::Unit &unit);
App::Property *setQuantityProperty(App::CellAddress key, double value, const Base::Unit &unit);
void renamedDocumentObject(const App::DocumentObject * docObj);
void aliasRemoved(CellAddress address, const std::string &alias);
void aliasRemoved(App::CellAddress address, const std::string &alias);
void removeAliases();
@@ -267,13 +268,13 @@ protected:
App::DynamicProperty props;
/* Mapping of properties to cell position */
std::map<const App::Property*, CellAddress > propAddress;
std::map<const App::Property*, App::CellAddress > propAddress;
/* Removed (unprocessed) aliases */
std::map<CellAddress, std::string> removedAliases;
std::map<App::CellAddress, std::string> removedAliases;
/* Set of cells with errors */
std::set<CellAddress> cellErrors;
std::set<App::CellAddress> cellErrors;
/* Properties */

View File

@@ -28,7 +28,7 @@
#include <Mod/Spreadsheet/App/Sheet.h>
#include <App/PropertyStandard.h>
#include "Utils.h"
#include "Range.h"
#include <App/Range.h>
// inclusion of the generated files (generated out of SheetPy.xml)
#include "SheetPy.h"

View File

@@ -1,485 +0,0 @@
/***************************************************************************
* Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifdef __GNUC__
# include <unistd.h>
#endif
#include "Base/Exception.h"
#include <Base/Interpreter.h>
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentPy.h>
#include <App/DocumentObject.h>
#include <App/PropertyUnits.h>
#include <Base/QuantityPy.h>
#include <QStringList>
#include <string>
#include <sstream>
#include <math.h>
#include <stdio.h>
#include <stack>
#include <deque>
#include <algorithm>
#include "SpreadsheetExpression.h"
#include <Base/Unit.h>
#include <App/PropertyUnits.h>
#include "Utils.h"
#include <boost/math/special_functions/round.hpp>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef M_E
#define M_E 2.71828182845904523536
#endif
#ifndef DOUBLE_MAX
# define DOUBLE_MAX 1.7976931348623157E+308 /* max decimal value of a "double"*/
#endif
#ifndef DOUBLE_MIN
# define DOUBLE_MIN 2.2250738585072014E-308 /* min decimal value of a "double"*/
#endif
#if defined(_MSC_VER)
#define strtoll _strtoi64
#pragma warning(disable : 4003)
#pragma warning(disable : 4065)
#endif
using namespace App;
using namespace Base;
using namespace Spreadsheet;
//
// FunctionExpression class. This class handles functions with one or two parameters.
//
TYPESYSTEM_SOURCE(Spreadsheet::AggregateFunctionExpression, App::FunctionExpression);
AggregateFunctionExpression::AggregateFunctionExpression(const DocumentObject *_owner,
App::FunctionExpression::Function _f,
std::vector<Expression *> _args)
: FunctionExpression(_owner, static_cast<FunctionExpression::Function>(_f), _args)
{
}
AggregateFunctionExpression::~AggregateFunctionExpression()
{
}
Expression *AggregateFunctionExpression::copy() const
{
std::vector<Expression*>::const_iterator i = args.begin();
std::vector<Expression*> a;
while (i != args.end()) {
a.push_back((*i)->copy());
++i;
}
return new AggregateFunctionExpression(owner, f, a);
}
/**
* Evaluate function. Returns a NumberExpression if evaluation is successfuly.
* Throws an exception if something fails.
*
* @returns A NumberExpression with the result.
*/
Expression * AggregateFunctionExpression::eval() const
{
switch (static_cast<Function>(f)) {
case SUM:
case AVERAGE:
case STDDEV:
case COUNT:
case MIN:
case MAX:
{
RangeExpression * v = freecad_dynamic_cast<RangeExpression>(args[0]);
Quantity q;
Quantity mean;
Quantity M2;
int n = 0;
bool first = true;
if (!v)
throw Exception("Expected range as argument");
Range range(v->getRange());
do {
Property * p = owner->getPropertyByName(range.address().c_str());
PropertyQuantity * qp;
PropertyFloat * fp;
Quantity value;
if (!p)
continue;
if ((qp = freecad_dynamic_cast<PropertyQuantity>(p)) != 0)
value = qp->getQuantityValue();
else if ((fp = freecad_dynamic_cast<PropertyFloat>(p)) != 0)
value = fp->getValue();
else
throw Exception("Invalid property type for aggregate");
if (first) {
q.setUnit(value.getUnit());
mean.setUnit(value.getUnit());
M2.setUnit(value.getUnit());
}
switch (static_cast<Function>(f)) {
case AVERAGE:
n++;
case SUM:
q = q + value;
break;
case STDDEV: {
n++;
const Quantity delta = value - mean;
mean = mean + delta / n;
M2 = M2 + delta * (value - mean);
break;
}
case COUNT:
q = q + 1;
break;
case MIN:
if (first || value < q)
q = value;
break;
case MAX:
if (first || value > q)
q = value;
break;
default:
break;
}
first = false;
} while (range.next());
switch (static_cast<Function>(f)) {
case AVERAGE:
q = q / (double)n;
break;
case STDDEV:
if (n < 2)
q = Quantity();
else
q = (M2 / (n - 1.0)).pow(Quantity(0.5));
break;
default:
break;
}
return new NumberExpression(owner, q);
}
default:
return App::FunctionExpression::eval();
}
}
/**
* Create a string representation of the expression.
*
* @returns A string representing the expression.
*/
std::string AggregateFunctionExpression::toString() const
{
switch (static_cast<Function>(f)) {
case SUM:
return "sum(" + args[0]->toString() + ")";
case COUNT:
return "count(" + args[0]->toString() + ")";
case AVERAGE:
return "average(" + args[0]->toString() + ")";
case STDDEV:
return "stddev(" + args[0]->toString() + ")";
case MIN:
return "min(" + args[0]->toString() + ")";
case MAX:
return "max(" + args[0]->toString() + ")";
default:
return App::FunctionExpression::toString();
}
}
TYPESYSTEM_SOURCE(Spreadsheet::RangeExpression, App::Expression);
RangeExpression::RangeExpression(const DocumentObject *_owner, const std::string &begin, const std::string &end)
: Expression(_owner)
, range((begin + ":" + end).c_str())
{
}
bool RangeExpression::isTouched() const
{
Range i(range);
do {
Property * prop = owner->getPropertyByName(i.address().c_str());
if (prop && prop->isTouched())
return true;
} while (i.next());
return false;
}
Expression *RangeExpression::eval() const
{
throw Exception("Range expression cannot be evaluated");
}
std::string RangeExpression::toString() const
{
return range.rangeString();
}
Expression *RangeExpression::copy() const
{
return new RangeExpression(owner, range.fromCellString(), range.toCellString());
}
void RangeExpression::getDeps(std::set<ObjectIdentifier> &props) const
{
Range i(range);
do {
props.insert(ObjectIdentifier(owner, i.address()));
} while (i.next());
}
Expression *RangeExpression::simplify() const
{
return copy();
}
void RangeExpression::setRange(const Range &r)
{
range = r;
}
namespace Spreadsheet {
namespace ExpressionParser {
/**
* Error function for parser. Throws a generic Base::Exception with the parser error.
*/
void ExpressionParser_yyerror(char *errorinfo)
{
}
/* helper function for tuning number strings with groups in a locale agnostic way... */
double num_change(char* yytext,char dez_delim,char grp_delim)
{
double ret_val;
char temp[40];
int i = 0;
for(char* c=yytext;*c!='\0';c++){
// skipp group delimiter
if(*c==grp_delim) continue;
// check for a dez delimiter othere then dot
if(*c==dez_delim && dez_delim !='.')
temp[i++] = '.';
else
temp[i++] = *c;
// check buffor overflow
if (i>39) return 0.0;
}
temp[i] = '\0';
errno = 0;
ret_val = strtod( temp, NULL );
if (ret_val == 0 && errno == ERANGE)
throw Base::Exception("Number underflow.");
if (ret_val == HUGE_VAL || ret_val == -HUGE_VAL)
throw Base::Exception("Number overflow.");
return ret_val;
}
static Expression * ScanResult = 0; /**< The resulting expression after a successful parsing */
static const DocumentObject * DocumentObject = 0; /**< The DocumentObject that will own the expression */
static bool unitExpression = false; /**< True if the parsed string is a unit only */
static bool valueExpression = false; /**< True if the parsed string is a full expression */
static std::stack<std::string> labels; /**< Label string primitive */
static std::map<std::string, FunctionExpression::Function> registered_functions; /**< Registerd functions */
// show the parser the lexer method
#undef YYTOKENTYPE
#undef YYSTYPE
#undef YYSTYPE_ISDECLARED
#define yylex ExpressionParserlex
int ExpressionParserlex(void);
// Parser, defined in ExpressionParser.y
#include <Mod/Spreadsheet/App/ExpressionParser.tab.c>
#include <Mod/Spreadsheet/App/ExpressionParser.tab.h>
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// Scanner, defined in ExpressionParser.l
#include <Mod/Spreadsheet/App/lex.ExpressionParser.c>
#endif // DOXYGEN_SHOULD_SKIP_THIS
#ifdef _MSC_VER
# define strdup _strdup
#endif
static void initParser(const App::DocumentObject *owner)
{
static bool has_registered_functions = false;
using namespace Spreadsheet::ExpressionParser;
ScanResult = 0;
Spreadsheet::ExpressionParser::DocumentObject = owner;
labels = std::stack<std::string>();
unitExpression = valueExpression = false;
if (!has_registered_functions) {
registered_functions["acos"] = FunctionExpression::ACOS;
registered_functions["asin"] = FunctionExpression::ASIN;
registered_functions["atan"] = FunctionExpression::ATAN;
registered_functions["abs"] = FunctionExpression::ABS;
registered_functions["exp"] = FunctionExpression::EXP;
registered_functions["log"] = FunctionExpression::LOG;
registered_functions["log10"] = FunctionExpression::LOG10;
registered_functions["sin"] = FunctionExpression::SIN;
registered_functions["sinh"] = FunctionExpression::SINH;
registered_functions["tan"] = FunctionExpression::TAN;
registered_functions["tanh"] = FunctionExpression::TANH;
registered_functions["sqrt"] = FunctionExpression::SQRT;
registered_functions["cos"] = FunctionExpression::COS;
registered_functions["cosh"] = FunctionExpression::COSH;
registered_functions["atan2"] = FunctionExpression::ATAN2;
registered_functions["mod"] = FunctionExpression::MOD;
registered_functions["pow"] = FunctionExpression::POW;
registered_functions["round"] = FunctionExpression::ROUND;
registered_functions["trunc"] = FunctionExpression::TRUNC;
registered_functions["ceil"] = FunctionExpression::CEIL;
registered_functions["floor"] = FunctionExpression::FLOOR;
// Aggregates
registered_functions["sum"] = static_cast<FunctionExpression::Function>(AggregateFunctionExpression::SUM);
registered_functions["count"] = static_cast<FunctionExpression::Function>(AggregateFunctionExpression::COUNT);
registered_functions["average"] = static_cast<FunctionExpression::Function>(AggregateFunctionExpression::AVERAGE);
registered_functions["stddev"] = static_cast<FunctionExpression::Function>(AggregateFunctionExpression::STDDEV);
registered_functions["min"] = static_cast<FunctionExpression::Function>(AggregateFunctionExpression::MIN);
registered_functions["max"] = static_cast<FunctionExpression::Function>(AggregateFunctionExpression::MAX);
has_registered_functions = true;
}
}
/**
* Parse the expression given by \a buffer, and use \a owner as the owner of the
* returned expression. If the parser fails for some reason, and exception is thrown.
*
* @param owner The DocumentObject that will own the expression.
* @param buffer The sting buffer to parse.
*
* @returns A pointer to an expression.
*
*/
Expression * parse(const App::DocumentObject *owner, const char* buffer)
{
// parse from buffer
ExpressionParser::YY_BUFFER_STATE my_string_buffer = ExpressionParser_scan_string (buffer);
initParser(owner);
// run the parser
int result = ExpressionParser::ExpressionParser_yyparse ();
// free the scan buffer
ExpressionParser::ExpressionParser_delete_buffer (my_string_buffer);
if (result != 0)
throw Base::Exception("Failed to parse expression.");
if (ScanResult == 0)
throw Base::Exception("Unknown error in expression");
if (valueExpression)
return ScanResult;
else {
delete ScanResult;
throw Expression::Exception("Expression can not evaluate to a value.");
return 0;
}
}
UnitExpression * parseUnit(const App::DocumentObject *owner, const char* buffer)
{
// parse from buffer
ExpressionParser::YY_BUFFER_STATE my_string_buffer = ExpressionParser_scan_string (buffer);
initParser(owner);
// run the parser
int result = ExpressionParser::ExpressionParser_yyparse ();
// free the scan buffer
ExpressionParser::ExpressionParser_delete_buffer (my_string_buffer);
if (result != 0)
throw Base::Exception("Failed to parse expression.");
if (ScanResult == 0)
throw Base::Exception("Unknown error in expression");
// Simplify expression
Expression * simplified = ScanResult->simplify();
delete ScanResult;
if (unitExpression) {
NumberExpression * num = freecad_dynamic_cast<NumberExpression>(simplified);
if (num) {
simplified = new UnitExpression(num->getOwner(), num->getQuantity());
delete num;
}
return freecad_dynamic_cast<UnitExpression>(simplified);
}
else {
delete simplified;
throw Expression::Exception("Expression is not a unit.");
return 0;
}
}
}
}

View File

@@ -1,107 +0,0 @@
/***************************************************************************
* Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef SPREADSHEET_EXPRESSION_H
#define SPREADSHEET_EXPRESSION_H
#include <string>
#include <App/DocumentObject.h>
#include <Base/Exception.h>
#include <Base/Unit.h>
#include <App/Property.h>
#include <Base/BaseClass.h>
#include <Base/Quantity.h>
#include <Mod/Spreadsheet/App/Range.h>
#include <set>
namespace Spreadsheet {
class SpreadsheetExport RangeExpression : public App::Expression {
TYPESYSTEM_HEADER();
public:
RangeExpression(const App::DocumentObject * _owner = 0, const std::string & begin = std::string(), const std::string & end = std::string());
virtual ~RangeExpression() { }
virtual bool isTouched() const;
virtual Expression * eval() const;
virtual std::string toString() const;
virtual Expression * copy() const;
virtual int priority() const { return 20; }
virtual void getDeps(std::set<App::ObjectIdentifier> &props) const;
virtual App::Expression * simplify() const;
Range getRange() const { return range; }
void setRange(const Range & r);
protected:
Range range;
};
/**
* Class implementing various functions, e.g sin, cos, etc.
*
*/
class SpreadsheetExport AggregateFunctionExpression : public App::FunctionExpression {
TYPESYSTEM_HEADER();
public:
enum Function {
NONE,
// Aggregates
SUM = App::FunctionExpression::LAST,
AVERAGE,
STDDEV,
COUNT,
MIN,
MAX
};
AggregateFunctionExpression(const App::DocumentObject *_owner = 0,
App::FunctionExpression::Function _f = App::FunctionExpression::NONE,
std::vector<Expression *> _args = std::vector<Expression*>());
virtual ~AggregateFunctionExpression();
virtual Expression * copy() const;
virtual App::Expression * eval() const;
virtual std::string toString() const;
};
namespace ExpressionParser {
SpreadsheetExport App::Expression * parse(const App::DocumentObject *owner, const char *buffer);
SpreadsheetExport App::UnitExpression * parseUnit(const App::DocumentObject *owner, const char *buffer);
SpreadsheetExport App::ObjectIdentifier parsePath(const App::DocumentObject *owner, const char* buffer);
}
}
#endif // EXPRESSION_H

View File

@@ -32,9 +32,6 @@
#include <Base/Exception.h>
#include "Sheet.h"
const int Spreadsheet::CellAddress::MAX_ROWS = 16384;
const int Spreadsheet::CellAddress::MAX_COLUMNS = 26 * 26 + 26;
/**
* Encode \a col as a string.
*
@@ -74,126 +71,6 @@ std::string Spreadsheet::rowName(int row)
return s.str();
}
/**
* Decode a row specification into a 0-based integer.
*
* @param rowstr Row specified as a string, with "1" being the first row.
*
* @returns The row.
*/
int Spreadsheet::decodeRow(const std::string &rowstr)
{
int row = validRow(rowstr);
if (row >= 0)
return row;
else
throw Base::Exception("Invalid row specification.");
}
/**
* Decode a column specification into a 0-based integer.
*
* @param colstr Column specified as a string, with "A" begin the first column.
*
* @returns The column.
*
*/
int Spreadsheet::decodeColumn(const std::string &colstr)
{
int col = validColumn(colstr);
if (col >= 0)
return col;
else
throw Base::Exception("Invalid column specification");
}
/**
* Determine wheter a row specification is valid or not.
*
* @param rowstr Row specified as a string, with "1" being the first row.
*
* @returns 0 or positive on success, -1 on error.
*/
int Spreadsheet::validRow(const std::string &rowstr)
{
char * end;
int i = strtol(rowstr.c_str(), &end, 10);
if (i <0 || i >= CellAddress::MAX_ROWS || *end)
return -1;
return i - 1;
}
/**
* Determine whether a column specification is valid or not.
*
* @param colstr Column specified as a string, with "A" begin the first column.
*
* @returns 0 or positive on success, -1 on error.
*
*/
int Spreadsheet::validColumn(const std::string &colstr)
{
int col = 0;
if (colstr.length() == 1) {
if ((colstr[0] >= 'A' && colstr[0] <= 'Z'))
col = colstr[0] - 'A';
else
return -1;
}
else {
col = 0;
for (std::string::const_reverse_iterator i = colstr.rbegin(); i != colstr.rend(); ++i) {
int v;
if ((*i >= 'A' && *i <= 'Z'))
v = *i - 'A';
else
return -1;
col = col * 26 + v;
}
col += 26;
}
return col;
}
/**
* Convert a string address into integer \a row and \a column.
* row and col are 0-based.
*
* This function will throw an exception if the specified \a address is invalid.
*
* @param address Address to parse.
* @param row Reference to integer where row position is stored.
* @param col Reference to integer where col position is stored.
*
*/
Spreadsheet::CellAddress Spreadsheet::stringToAddress(const char * strAddress)
{
static const boost::regex e("\\${0,1}([A-Z]{1,2})\\${0,1}([0-9]{1,5})");
boost::cmatch cm;
Q_ASSERT(strAddress != 0);
if (boost::regex_match(strAddress, cm, e)) {
const boost::sub_match<const char *> colstr = cm[1];
const boost::sub_match<const char *> rowstr = cm[2];
return CellAddress(Spreadsheet::decodeRow(rowstr.str()), Spreadsheet::decodeColumn(colstr.str()));
}
else
throw Base::Exception("Invalid cell specifier.");
}
void Spreadsheet::createRectangles(std::set<std::pair<int, int> > & cells, std::map<std::pair<int, int>, std::pair<int, int> > & rectangles)
{
@@ -349,28 +226,3 @@ std::string Spreadsheet::unquote(const std::string & input)
return output;
}
/**
* Convert given \a cell address into its string representation.
*
* @returns Address given as a string.
*/
std::string Spreadsheet::CellAddress::toString() const
{
std::stringstream s;
if (col() < 26)
s << (char)('A' + col());
else {
int colnum = col() - 26;
s << (char)('A' + (colnum / 26));
s << (char)('A' + (colnum % 26));
}
s << (row() + 1);
return s.str();
}

View File

@@ -31,60 +31,13 @@
namespace Spreadsheet {
struct CellAddress;
SpreadsheetExport std::string columnName(int col);
SpreadsheetExport std::string rowName(int row);
int decodeColumn(const std::string &colstr);
int decodeRow(const std::string &rowstr);
int validColumn(const std::string &colstr);
int validRow(const std::string &rowstr);
SpreadsheetExport CellAddress stringToAddress(const char *strAddress);
SpreadsheetExport void createRectangles(std::set<std::pair<int, int> > & cells, std::map<std::pair<int, int>, std::pair<int, int> > & rectangles);
SpreadsheetExport std::string quote(const std::string &input);
SpreadsheetExport std::string unquote(const std::string & input);
struct SpreadsheetExport CellAddress {
CellAddress(int row = -1, int col = -1) : _row(row), _col(col) { }
CellAddress(const char * address) {
*this = stringToAddress(address);
}
CellAddress(const std::string & address) {
*this = stringToAddress(address.c_str());
}
inline int row() const { return _row; }
inline int col() const { return _col; }
inline bool operator<(const CellAddress & other) const { return asInt() < other.asInt(); }
inline bool operator==(const CellAddress & other) const { return asInt() == other.asInt(); }
inline bool operator!=(const CellAddress & other) const { return asInt() != other.asInt(); }
inline bool isValid() { return (row() >=0 && row() < MAX_ROWS && col() >= 0 && col() < MAX_COLUMNS); }
std::string toString() const;
// Static members
static const int MAX_ROWS;
static const int MAX_COLUMNS;
protected:
inline unsigned int asInt() const { return ((_row << 16) | _col); }
short _row;
short _col;
};
}
#endif // UTILS_H

View File

@@ -37,7 +37,7 @@
#include "SpreadsheetView.h"
#include "../App/Sheet.h"
#include "../App/Range.h"
#include <App/Range.h>
#include "ViewProviderSpreadsheet.h"
#include "PropertiesDialog.h"
@@ -46,6 +46,7 @@
using namespace SpreadsheetGui;
using namespace Spreadsheet;
using namespace Base;
using namespace App;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -793,7 +794,7 @@ void CmdSpreadsheetSetAlias::activated(int iMsg)
QModelIndexList selection = sheetView->selectedIndexes();
if (selection.size() == 1) {
std::vector<Spreadsheet::Range> range;
std::vector<Range> range;
range.push_back(Range(selection[0].row(), selection[0].column(),
selection[0].row(), selection[0].column()));

View File

@@ -24,8 +24,7 @@
#include "PreCompiled.h"
#include "PropertiesDialog.h"
#include <Base/Tools.h>
#include <Mod/Spreadsheet/App/SpreadsheetExpression.h>
#include <Mod/Spreadsheet/App/Range.h>
#include <App/Range.h>
#include <Gui/Command.h>
#include "ui_PropertiesDialog.h"
@@ -185,7 +184,7 @@ void PropertiesDialog::displayUnitChanged(const QString & text)
QPalette palette = ui->displayUnit->palette();
try {
std::auto_ptr<UnitExpression> e(Spreadsheet::ExpressionParser::parseUnit(sheet, text.toUtf8().constData()));
std::auto_ptr<UnitExpression> e(App::ExpressionParser::parseUnit(sheet, text.toUtf8().constData()));
displayUnit = DisplayUnit(text.toUtf8().constData(), e->getUnit(), e->getScaler());
palette.setColor(QPalette::Text, Qt::black);

View File

@@ -37,7 +37,7 @@ class PropertiesDialog : public QDialog
Q_OBJECT
public:
explicit PropertiesDialog(Spreadsheet::Sheet *_sheet, const std::vector<Spreadsheet::Range> & _ranges, QWidget *parent = 0);
explicit PropertiesDialog(Spreadsheet::Sheet *_sheet, const std::vector<App::Range> & _ranges, QWidget *parent = 0);
~PropertiesDialog();
void apply();
@@ -52,7 +52,7 @@ private Q_SLOTS:
void aliasChanged(const QString &text);
private:
Spreadsheet::Sheet * sheet;
std::vector<Spreadsheet::Range> ranges;
std::vector<App::Range> ranges;
Ui::PropertiesDialog *ui;
App::Color foregroundColor;
App::Color backgroundColor;

View File

@@ -30,7 +30,6 @@
#include <Gui/Application.h>
#include "SheetModel.h"
#include <Mod/Spreadsheet/App/SpreadsheetExpression.h>
#include <Mod/Spreadsheet/App/Utils.h>
#include "../App/Sheet.h"
#include <Gui/Command.h>

View File

@@ -26,6 +26,7 @@
#include <QAbstractTableModel>
#include <boost/signals/connection.hpp>
#include <Mod/Spreadsheet/App/Utils.h>
#include <App/Range.h>
namespace Spreadsheet {
class Sheet;
@@ -49,7 +50,7 @@ public:
Qt::ItemFlags flags(const QModelIndex &) const;
private:
void cellUpdated(Spreadsheet::CellAddress address);
void cellUpdated(App::CellAddress address);
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection cellUpdatedConnection;
Spreadsheet::Sheet * sheet;

View File

@@ -29,13 +29,14 @@
#include <Gui/Command.h>
#include <boost/bind.hpp>
#include "../App/Utils.h"
#include "../App/Range.h"
#include <App/Range.h>
#include "SheetTableView.h"
#include "LineEdit.h"
#include "PropertiesDialog.h"
using namespace SpreadsheetGui;
using namespace Spreadsheet;
using namespace App;
void SheetViewHeader::mouseReleaseEvent(QMouseEvent *event)
{
@@ -236,7 +237,7 @@ SheetTableView::~SheetTableView()
}
void SheetTableView::updateCellSpan(Spreadsheet::CellAddress address)
void SheetTableView::updateCellSpan(CellAddress address)
{
int rows, cols;

View File

@@ -53,10 +53,10 @@ public:
void edit(const QModelIndex &index);
void setSheet(Spreadsheet::Sheet *_sheet);
std::vector<Spreadsheet::Range> selectedRanges() const;
std::vector<App::Range> selectedRanges() const;
protected Q_SLOTS:
void commitData(QWidget *editor);
void updateCellSpan(Spreadsheet::CellAddress address);
void updateCellSpan(App::CellAddress address);
void insertRows();
void removeRows();
void insertColumns();

View File

@@ -37,9 +37,8 @@
#include "SpreadsheetView.h"
#include "SpreadsheetDelegate.h"
#include <Mod/Spreadsheet/App/SpreadsheetExpression.h>
#include <Mod/Spreadsheet/App/Sheet.h>
#include <Mod/Spreadsheet/App/Range.h>
#include <App/Range.h>
#include <Gui/MainWindow.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
@@ -57,6 +56,7 @@
using namespace SpreadsheetGui;
using namespace Spreadsheet;
using namespace Gui;
using namespace App;
/* TRANSLATOR SpreadsheetGui::SheetView */
@@ -120,7 +120,7 @@ SheetView::SheetView(Gui::Document *pcDocument, App::DocumentObject *docObj, QWi
SheetView::~SheetView()
{
Application::Instance->detachView(this);
Gui::Application::Instance->detachView(this);
//delete delegate;
}

View File

@@ -69,7 +69,7 @@ public:
Spreadsheet::Sheet * getSheet() { return sheet; }
std::vector<Spreadsheet::Range> selectedRanges() const;
std::vector<App::Range> selectedRanges() const;
QModelIndexList selectedIndexes() const;

View File

@@ -36,7 +36,7 @@
#include "SpreadsheetView.h"
#include <Mod/Spreadsheet/App/Sheet.h>
#include <Mod/Spreadsheet/App/Range.h>
#include <App/Range.h>
#include <App/Document.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Application.h>
@@ -49,6 +49,7 @@
using namespace Base;
using namespace Gui;
using namespace App;
using namespace SpreadsheetGui;
using namespace Spreadsheet;

View File

@@ -37,10 +37,11 @@
#include <QToolBar>
#include "qtcolorpicker.h"
#include "Mod/Spreadsheet/App/Sheet.h"
#include "Mod/Spreadsheet/App/Range.h"
#include <App/Range.h>
#include "Mod/Spreadsheet/Gui/SpreadsheetView.h"
using namespace Base;
using namespace App;
using namespace SpreadsheetGui;
using namespace Spreadsheet;