Initial implementation of Spreadsheet module (C++ version) by Eivind Kvedalen.

Various fixes for Windows by
Peter Lama <peterldev94@gmail.com>
Werner Mayer <wmayer@users.sourceforge.net>
This commit is contained in:
Eivind Kvedalen
2013-09-29 21:12:02 +02:00
committed by wmayer
parent 337bd00de0
commit 935ec5b034
80 changed files with 27086 additions and 1221 deletions

View File

@@ -0,0 +1,52 @@
/***************************************************************************
* *
* This program 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. *
* for detail see the LICENCE text file. *
* Jrgen Riegel 2002 *
* Eivind Kvedalen 2015 *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Python.h>
#endif
#include <Base/Console.h>
#include "Sheet.h"
#include "Expression.h"
/* registration table */
static struct PyMethodDef Spreadsheet_methods[] = {
{NULL, NULL} /* end of table marker */
};
/* Python entry */
extern "C" {
void SpreadsheetExport initSpreadsheet() {
(void) Py_InitModule("Spreadsheet", Spreadsheet_methods); /* mod name, table ptr */
Base::Console().Log("Loading Spreadsheet module... done\n");
Spreadsheet::PropertyColumnWidths::init();
Spreadsheet::PropertyRowHeights::init();
Spreadsheet::PropertySheet::init();
Spreadsheet::Sheet::init();
Spreadsheet::Expression::init();
Spreadsheet::UnitExpression::init();
Spreadsheet::NumberExpression::init();
Spreadsheet::ConstantExpression::init();
Spreadsheet::FunctionExpression::init();
Spreadsheet::OperatorExpression::init();
Spreadsheet::VariableExpression::init();
Spreadsheet::ConditionalExpression::init();
Spreadsheet::StringExpression::init();
return;
}
} // extern "C"

View File

@@ -0,0 +1,69 @@
if(WIN32)
add_definitions(-DFCAppSpreadsheet)
endif(WIN32)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${PYTHON_INCLUDE_PATH}
${Boost_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIR}
${XERCESC_INCLUDE_DIR}
${QT_INCLUDE_DIR}
)
set(Spreadsheet_LIBS
FreeCADApp
)
set(Spreadsheet_SRCS
Expression.cpp
Expression.h
Cell.cpp
Cell.h
DisplayUnit.h
PropertySheet.cpp
PropertySheet.h
PropertySheetPy.xml
PropertySheetPyImp.cpp
PropertyColumnWidths.cpp
PropertyColumnWidths.h
PropertyColumnWidthsPy.xml
PropertyColumnWidthsPyImp.cpp
PropertyRowHeights.cpp
PropertyRowHeights.h
PropertyRowHeightsPy.xml
PropertyRowHeightsPyImp.cpp
PreCompiled.cpp
PreCompiled.h
Sheet.cpp
Sheet.h
SheetPy.xml
SheetPyImp.cpp
SheetObserver.cpp
SheetObserver.h
Utils.cpp
Utils.h
Range.h
Range.cpp
AppSpreadsheet.cpp
)
generate_from_xml(SheetPy)
generate_from_xml(PropertySheetPy)
generate_from_xml(PropertyColumnWidthsPy)
generate_from_xml(PropertyRowHeightsPy)
add_library(Spreadsheet SHARED ${Spreadsheet_SRCS})
target_link_libraries(Spreadsheet ${Spreadsheet_LIBS})
fc_target_copy_resource(Spreadsheet
${CMAKE_SOURCE_DIR}/src/Mod/Spreadsheet
${CMAKE_BINARY_DIR}/Mod/Spreadsheet
Init.py)
SET_BIN_DIR(Spreadsheet Spreadsheet /Mod/Spreadsheet)
SET_PYTHON_PREFIX_SUFFIX(Spreadsheet)
INSTALL(TARGETS Spreadsheet DESTINATION ${CMAKE_INSTALL_LIBDIR})

View File

@@ -0,0 +1,814 @@
/***************************************************************************
* 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"
#ifndef _PreComp_
#endif
#include "Cell.h"
#include "Utils.h"
#include <boost/tokenizer.hpp>
#include <Base/Reader.h>
#include <Base/Writer.h>
#include "Expression.h"
#include "Sheet.h"
#include <iomanip>
#ifdef _MSC_VER
#define __func__ __FUNCTION__
#endif
using namespace App;
using namespace Spreadsheet;
const int Cell::EXPRESSION_SET = 1;
const int Cell::ALIGNMENT_SET = 4;
const int Cell::STYLE_SET = 8;
const int Cell::BACKGROUND_COLOR_SET = 0x10;
const int Cell::FOREGROUND_COLOR_SET = 0x20;
const int Cell::DISPLAY_UNIT_SET = 0x40;
const int Cell::COMPUTED_UNIT_SET = 0x80;
const int Cell::ALIAS_SET = 0x100;
const int Cell::SPANS_SET = 0x200;
const int Cell::MARK_SET = 0x40000000;
const int Cell::EXCEPTION_SET = 0x20000000;
const int Cell::PARSE_EXCEPTION_SET = 0x80000000;
const int Cell::RESOLVE_EXCEPTION_SET= 0x01000000;
const int Cell::SPANS_UPDATED = 0x10000000;
/* Alignment */
const int Cell::ALIGNMENT_LEFT = 0x01;
const int Cell::ALIGNMENT_HCENTER = 0x02;
const int Cell::ALIGNMENT_RIGHT = 0x04;
const int Cell::ALIGNMENT_HIMPLIED = 0x08;
const int Cell::ALIGNMENT_HORIZONTAL = 0x0f;
const int Cell::ALIGNMENT_TOP = 0x10;
const int Cell::ALIGNMENT_VCENTER = 0x20;
const int Cell::ALIGNMENT_BOTTOM = 0x40;
const int Cell::ALIGNMENT_VIMPLIED = 0x80;
const int Cell::ALIGNMENT_VERTICAL = 0xf0;
/**
* Construct a CellContent object.
*
* @param _row The row of the cell in the spreadsheet that contains is.
* @param _col The column of the cell in the spreadsheet that contains is.
* @param _owner The spreadsheet that owns this cell.
*
*/
Cell::Cell(const CellAddress &_address, PropertySheet *_owner)
: address(_address)
, owner(_owner)
, used(0)
, expression(0)
, alignment(ALIGNMENT_HIMPLIED | ALIGNMENT_LEFT | ALIGNMENT_VIMPLIED | ALIGNMENT_VCENTER)
, style()
, foregroundColor(0, 0, 0, 1)
, backgroundColor(1, 1, 1, 1)
, displayUnit()
, computedUnit()
, rowSpan(1)
, colSpan(1)
, anchor()
{
assert(address.isValid());
}
/**
* Destroy a CellContent object.
*
*/
Cell::Cell(const Cell &other)
: address(other.address)
, owner(other.owner)
, used(other.used)
, expression(other.expression ? other.expression->copy() : 0)
, style(other.style)
, alignment(other.alignment)
, foregroundColor(other.foregroundColor)
, backgroundColor(other.backgroundColor)
, displayUnit(other.displayUnit)
, computedUnit(other.computedUnit)
, colSpan(other.colSpan)
, rowSpan(other.rowSpan)
{
}
Cell &Cell::operator =(const Cell &rhs)
{
PropertySheet::Signaller signaller(*owner);
used = 0;
address = rhs.address;
owner = rhs.owner;
setExpression(rhs.expression ? rhs.expression->copy() : 0);
setStyle(rhs.style);
setAlignment(rhs.alignment);
setForeground(rhs.foregroundColor);
setBackground(rhs.backgroundColor);
setDisplayUnit(rhs.displayUnit.stringRep);
setComputedUnit(rhs.computedUnit);
setSpans(rhs.rowSpan, rhs.colSpan);
return *this;
}
Cell::~Cell()
{
if (expression)
delete expression;
}
/**
* Set the expression tree to \a expr.
*
*/
void Cell::setExpression(Expression *expr)
{
PropertySheet::Signaller signaller(*owner);
/* Remove dependencies */
owner->removeDependencies(address);
if (expression)
delete expression;
expression = expr;
setUsed(EXPRESSION_SET, expression != 0);
/* Update dependencies */
owner->addDependencies(address);
}
/**
* Get the expression tree.
*
*/
const Expression *Cell::getExpression() const
{
return expression;
}
/**
* Get string content.
*
*/
bool Cell::getStringContent(std::string & s) const
{
if (expression) {
if (freecad_dynamic_cast<StringExpression>(expression)) {
s = static_cast<StringExpression*>(expression)->getText();
char * end;
errno = 0;
strtod(s.c_str(), &end);
if (!*end && errno == 0)
s = "'" + s;
}
else if (freecad_dynamic_cast<ConstantExpression>(expression))
s = "=" + expression->toString();
else if (freecad_dynamic_cast<NumberExpression>(expression))
s = expression->toString();
else
s = "=" + expression->toString();
return true;
}
else {
s = "";
return false;
}
}
void Cell::setContent(const char * value)
{
PropertySheet::Signaller signaller(*owner);
Expression * expr = 0;
setUsed(PARSE_EXCEPTION_SET, false);
if (value != 0) {
if (*value == '=') {
try {
expr = ExpressionParser::parse(owner->sheet(), value + 1);
}
catch (Base::Exception & e) {
QString msg = QString::fromUtf8("ERR: %1").arg(QString::fromUtf8(e.what()));
expr = new StringExpression(owner->sheet(), value);
setUsed(PARSE_EXCEPTION_SET);
}
}
else if (*value == '\'')
expr = new StringExpression(owner->sheet(), value + 1);
else if (*value != '\0') {
char * end;
errno = 0;
double float_value = strtod(value, &end);
if (!*end && errno == 0)
expr = new NumberExpression(owner->sheet(), float_value);
else {
try {
expr = ExpressionParser::parse(owner->sheet(), value);
if (expr)
delete expr->eval();
}
catch (Base::Exception & e) {
expr = new StringExpression(owner->sheet(), value);
}
}
}
}
setExpression(expr);
}
/**
* Set alignment of this cell. Alignment is the or'ed value of
* vertical and horizontal alignment, given by the constants
* defined in the class.
*
*/
void Cell::setAlignment(int _alignment)
{
if (_alignment != alignment) {
PropertySheet::Signaller signaller(*owner);
alignment = _alignment;
setUsed(ALIGNMENT_SET, alignment != (ALIGNMENT_HIMPLIED | ALIGNMENT_LEFT | ALIGNMENT_VIMPLIED | ALIGNMENT_VCENTER));
}
}
/**
* Get alignment.
*
*/
bool Cell::getAlignment(int & _alignment) const
{
_alignment = alignment;
return isUsed(ALIGNMENT_SET);
}
/**
* Set style to the given set \a _style.
*
*/
void Cell::setStyle(const std::set<std::string> & _style)
{
if (_style != style) {
PropertySheet::Signaller signaller(*owner);
style = _style;
setUsed(STYLE_SET, style.size() > 0);
}
}
/**
* Get the style of the cell.
*
*/
bool Cell::getStyle(std::set<std::string> & _style) const
{
_style = style;
return isUsed(STYLE_SET);
}
/**
* Set foreground (i.e text) color of the cell to \a color.
*
*/
void Cell::setForeground(const Color &color)
{
if (color != foregroundColor) {
PropertySheet::Signaller signaller(*owner);
foregroundColor = color;
setUsed(FOREGROUND_COLOR_SET, foregroundColor != App::Color(0, 0, 0, 1));
}
}
/**
* Get foreground color of the cell.
*
*/
bool Cell::getForeground(Color &color) const
{
color = foregroundColor;
return isUsed(FOREGROUND_COLOR_SET);
}
/**
* Set background color of the cell to \a color.
*
*/
void Cell::setBackground(const Color &color)
{
if (color != backgroundColor) {
PropertySheet::Signaller signaller(*owner);
backgroundColor = color;
setUsed(BACKGROUND_COLOR_SET, backgroundColor != App::Color(1, 1, 1, 1));
}
}
/**
* Get the background color of the cell into \a color.
*
* @returns true if the background color was previously set.
*
*/
bool Cell::getBackground(Color &color) const
{
color = backgroundColor;
return isUsed(BACKGROUND_COLOR_SET);
}
/**
* Set the display unit for the cell.
*
*/
void Cell::setDisplayUnit(const std::string &unit)
{
DisplayUnit newDisplayUnit;
if (unit.size() > 0) {
std::auto_ptr<UnitExpression> e(ExpressionParser::parseUnit(owner->sheet(), unit.c_str()));
newDisplayUnit = DisplayUnit(unit, e->getUnit(), e->getScaler());
}
if (newDisplayUnit != displayUnit) {
PropertySheet::Signaller signaller(*owner);
displayUnit = newDisplayUnit;
setUsed(DISPLAY_UNIT_SET, !displayUnit.isEmpty());
}
}
/**
* Get the display unit for the cell into unit.
*
* @returns true if the display unit was previously set.
*
*/
bool Cell::getDisplayUnit(DisplayUnit &unit) const
{
unit = displayUnit;
return isUsed(DISPLAY_UNIT_SET);
}
void Cell::setAlias(const std::string &n)
{
if (alias != n) {
PropertySheet::Signaller signaller(*owner);
alias = n;
setUsed(ALIAS_SET, !alias.empty());
}
}
bool Cell::getAlias(std::string &n) const
{
n = alias;
return isUsed(ALIAS_SET);
}
/**
* Set the computed unit for the cell to \a unit.
*
*/
void Cell::setComputedUnit(const Base::Unit &unit)
{
PropertySheet::Signaller signaller(*owner);
computedUnit = unit;
setUsed(COMPUTED_UNIT_SET, !computedUnit.isEmpty());
}
/**
* Get the computed unit into \a unit.
*
* @returns true if the computed unit was previously set.
*
*/
bool Cell::getComputedUnit(Base::Unit & unit) const
{
unit = computedUnit;
return isUsed(COMPUTED_UNIT_SET);
}
/**
* Set the cell's row and column span to \a rows and \a columns. This
* is done when cells are merged.
*
*/
void Cell::setSpans(int rows, int columns)
{
if (rows != rowSpan || columns != colSpan) {
PropertySheet::Signaller signaller(*owner);
rowSpan = rows;
colSpan = columns;
setUsed(SPANS_SET, (rowSpan != 1 || colSpan != 1) );
setUsed(SPANS_UPDATED);
}
}
/**
* Get the row and column spans for the cell into \a rows and \a columns.
*
*/
bool Cell::getSpans(int &rows, int &columns) const
{
rows = rowSpan;
columns = colSpan;
return isUsed(SPANS_SET);
}
void Cell::setException(const std::string &e)
{
exceptionStr = e;
setUsed(EXCEPTION_SET);
}
void Cell::setParseException(const std::string &e)
{
exceptionStr = e;
setUsed(PARSE_EXCEPTION_SET);
}
void Cell::setResolveException(const std::string &e)
{
exceptionStr = e;
setUsed(RESOLVE_EXCEPTION_SET);
}
void Cell::clearResolveException()
{
setUsed(RESOLVE_EXCEPTION_SET, false);
}
void Cell::clearException()
{
if (!isUsed(PARSE_EXCEPTION_SET))
exceptionStr = "";
setUsed(EXCEPTION_SET, false);
}
void Cell::clearDirty()
{
owner->clearDirty(address);
}
/**
* Move the cell to a new position given by \a _row and \a _col.
*
*/
void Cell::moveAbsolute(CellAddress newAddress)
{
address = newAddress;
}
/**
* Restore cell contents from \a reader.
*
*/
void Cell::restore(Base::XMLReader &reader)
{
const char* style = reader.hasAttribute("style") ? reader.getAttribute("style") : 0;
const char* alignment = reader.hasAttribute("alignment") ? reader.getAttribute("alignment") : 0;
const char* content = reader.hasAttribute("content") ? reader.getAttribute("content") : "";
const char* foregroundColor = reader.hasAttribute("foregroundColor") ? reader.getAttribute("foregroundColor") : 0;
const char* backgroundColor = reader.hasAttribute("backgroundColor") ? reader.getAttribute("backgroundColor") : 0;
const char* displayUnit = reader.hasAttribute("displayUnit") ? reader.getAttribute("displayUnit") : 0;
const char* alias = reader.hasAttribute("alias") ? reader.getAttribute("alias") : 0;
const char* rowSpan = reader.hasAttribute("rowSpan") ? reader.getAttribute("rowSpan") : 0;
const char* colSpan = reader.hasAttribute("colSpan") ? reader.getAttribute("colSpan") : 0;
// Don't trigger multiple updates below; wait until everything is loaded by calling unfreeze() below.
PropertySheet::Signaller signaller(*owner);
if (content) {
setContent(content);
}
if (style) {
using namespace boost;
std::set<std::string> styleSet;
escaped_list_separator<char> e('\0', '|', '\0');
std::string line = std::string(style);
tokenizer<escaped_list_separator<char> > tok(line, e);
for(tokenizer<escaped_list_separator<char> >::iterator i = tok.begin(); i != tok.end();++i)
styleSet.insert(*i);
setStyle(styleSet);
}
if (alignment) {
int alignmentCode = 0;
using namespace boost;
escaped_list_separator<char> e('\0', '|', '\0');
std::string line = std::string(alignment);
tokenizer<escaped_list_separator<char> > tok(line, e);
for(tokenizer<escaped_list_separator<char> >::iterator i = tok.begin(); i != tok.end();++i)
alignmentCode = decodeAlignment(*i, alignmentCode);
setAlignment(alignmentCode);
}
if (foregroundColor) {
Color color = decodeColor(foregroundColor, Color(0, 0, 0, 1));
setForeground(color);
}
if (backgroundColor) {
Color color = decodeColor(backgroundColor, Color(1, 1, 1, 1));
setBackground(color);
}
if (displayUnit)
setDisplayUnit(displayUnit);
if (alias)
setAlias(alias);
if (rowSpan || colSpan) {
int rs = rowSpan ? atoi(rowSpan) : 1;
int cs = colSpan ? atoi(colSpan) : 1;
setSpans(rs, cs);
}
}
/**
* Save cell contents into \a writer.
*
*/
void Cell::save(Base::Writer &writer) const
{
if (!isUsed())
return;
writer.Stream() << writer.ind() << "<Cell ";
writer.Stream() << "address=\"" << addressToString(address) << "\" ";
if (isUsed(EXPRESSION_SET)) {
std::string content;
getStringContent(content);
writer.Stream() << "content=\"" << Property::encodeAttribute(content) << "\" ";
}
if (isUsed(ALIGNMENT_SET))
writer.Stream() << "alignment=\"" << encodeAlignment(alignment) << "\" ";
if (isUsed(STYLE_SET))
writer.Stream() << "style=\"" << encodeStyle(style) << "\" ";
if (isUsed(FOREGROUND_COLOR_SET))
writer.Stream() << "foregroundColor=\"" << encodeColor(foregroundColor) << "\" ";
if (isUsed(BACKGROUND_COLOR_SET))
writer.Stream() << "backgroundColor=\"" << encodeColor(backgroundColor) << "\" ";
if (isUsed(DISPLAY_UNIT_SET))
writer.Stream() << "displayUnit=\"" << Property::encodeAttribute(displayUnit.stringRep) << "\" ";
if (isUsed(ALIAS_SET))
writer.Stream() << "alias=\"" << Property::encodeAttribute(alias) << "\" ";
if (isUsed(SPANS_SET)) {
writer.Stream() << "rowSpan=\"" << rowSpan<< "\" ";
writer.Stream() << "colSpan=\"" << colSpan << "\" ";
}
writer.Stream() << "/>" << std::endl;
}
/**
* Update the \a used member variable with mask (bitwise or'ed).
*
*/
void Cell::setUsed(int mask, bool state)
{
if (state)
used |= mask;
else
used &= ~mask;
owner->setDirty(address);
}
/**
* Determine whether the bits in \a mask are set in the \a used member variable.
*
*/
bool Cell::isUsed(int mask) const
{
return (used & mask) == mask;
}
/**
* Determine if the any of the contents of the cell is set a non-default value.
*
*/
bool Cell::isUsed() const
{
return used != 0;
}
void Cell::visit(ExpressionVisitor &v)
{
if (expression)
v.visit(expression);
}
/**
* Decode aligment into its internal value.
*
* @param itemStr Alignment as a string
* @param alignment Current alignment. This is or'ed with the one in \a itemStr.
*
* @returns New alignment.
*
*/
int Cell::decodeAlignment(const std::string & itemStr, int alignment)
{
if (itemStr == "himplied")
alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_HIMPLIED;
else if (itemStr == "left")
alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_LEFT;
else if (itemStr == "center")
alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_HCENTER;
else if (itemStr == "right")
alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_RIGHT;
else if (itemStr == "vimplied")
alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_VIMPLIED;
else if (itemStr == "top")
alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_TOP;
else if (itemStr == "vcenter")
alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_VCENTER;
else if (itemStr == "bottom")
alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_BOTTOM;
else
throw Base::Exception("Invalid alignment.");
return alignment;
}
/**
* Encode internal alignment value as a string.
*
* @param alignment Alignment as a binary value.
*
* @returns Alignment represented as a string.
*
*/
std::string Cell::encodeAlignment(int alignment)
{
std::string s;
if (alignment & Cell::ALIGNMENT_LEFT)
s += "left";
if (alignment & Cell::ALIGNMENT_HCENTER)
s += "center";
if (alignment & Cell::ALIGNMENT_RIGHT)
s += "right";
if (alignment & Cell::ALIGNMENT_HIMPLIED)
s += "|himplied";
if (alignment & Cell::ALIGNMENT_VERTICAL)
s += "|";
if (alignment & Cell::ALIGNMENT_TOP)
s += "top";
if (alignment & Cell::ALIGNMENT_VCENTER)
s += "vcenter";
if (alignment & Cell::ALIGNMENT_BOTTOM)
s += "bottom";
if (alignment & Cell::ALIGNMENT_VIMPLIED)
s += "|vimplied";
return s;
}
/**
* Encode \a color as a #rrggbbaa string.
*
* @param color Color to encode.
*
* @returns String with encoded color.
*
*/
std::string Cell::encodeColor(const Color & color)
{
std::stringstream tmp;
tmp << "#"
<< std::hex << std::setw(2) << std::setfill('0') << int(color.r * 255.0)
<< std::hex << std::setw(2) << std::setfill('0') << int(color.g * 255.0)
<< std::hex << std::setw(2) << std::setfill('0') << int(color.b * 255.0)
<< std::hex << std::setw(2) << std::setfill('0') << int(color.a * 255.0);
return tmp.str();
}
/**
* Encode set of styles as a string.
*
* @param style Set of string describing the style.
*
* @returns Set encoded as a string.
*
*/
std::string Cell::encodeStyle(const std::set<std::string> & style)
{
std::string s;
std::set<std::string>::const_iterator j = style.begin();
std::set<std::string>::const_iterator j_end = style.end();
while (j != j_end) {
s += *j;
++j;
if (j != j_end)
s += "|";
}
return s;
}
/**
* Decode a string of the format #rrggbb or #rrggbbaa into a Color.
*
* @param color The color to decode.
* @param defaultColor A default color in case the decoding fails.
*
* @returns Decoded color.
*
*/
Color Cell::decodeColor(const std::string & color, const Color & defaultColor)
{
if (color.size() == 7 || color.size() == 9) {
Color c;
if (color[0] != '#')
return defaultColor;
unsigned int value = strtoul(color.c_str() + 1, 0, 16);
if (color.size() == 7)
value = (value << 8) | 0xff;
c.setPackedValue(value);
return c;
}
else
return defaultColor;
}

View File

@@ -0,0 +1,190 @@
/***************************************************************************
* 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 CELL_H
#define CELL_H
#include <string>
#include <set>
#include <App/Material.h>
#include "DisplayUnit.h"
#include "Utils.h"
namespace Base {
class Unit;
class XMLReader;
class Writer;
}
namespace Spreadsheet {
class PropertySheet;
class Expression;
class DisplayUnit;
class ExpressionVisitor;
class SpreadsheetExport Cell {
public:
Cell(const CellAddress & _address, PropertySheet * _owner);
Cell(const Cell & other);
Cell& operator=( const Cell& rhs );
~Cell();
const Expression * getExpression() const;
bool getStringContent(std::string & s) const;
void setContent(const char * value);
void setAlignment(int _alignment);
bool getAlignment(int & _alignment) const;
void setStyle(const std::set<std::string> & _style);
bool getStyle(std::set<std::string> & style) const;
void setForeground(const App::Color &color);
bool getForeground(App::Color &color) const;
void setBackground(const App::Color &color);
bool getBackground(App::Color &color) const;
void setDisplayUnit(const std::string & unit);
bool getDisplayUnit(DisplayUnit &unit) const;
void setAlias(const std::string & n);
bool getAlias(std::string & n ) const;
void setComputedUnit(const Base::Unit & unit);
bool getComputedUnit(Base::Unit & unit) const;
void setSpans(int rows, int columns);
bool getSpans(int & rows, int & columns) const;
void setException(const std::string & e);
void clearException();
void clearDirty();
void setParseException(const std::string & e);
void setResolveException(const std::string &e);
void clearResolveException();
const std::string &getException() const { return exceptionStr; }
bool hasException() const { return isUsed(EXCEPTION_SET) || isUsed(PARSE_EXCEPTION_SET) || isUsed(RESOLVE_EXCEPTION_SET); }
void moveAbsolute(CellAddress newAddress);
void restore(Base::XMLReader &reader);
void save(Base::Writer &writer) const;
bool isUsed() const;
void mark() { setUsed(MARK_SET); }
bool isMarked() const { return isUsed(MARK_SET); }
bool spansChanged() const { return isUsed(SPANS_UPDATED); }
void visit(ExpressionVisitor & v);
/* Alignment */
static const int ALIGNMENT_LEFT;
static const int ALIGNMENT_HCENTER;
static const int ALIGNMENT_RIGHT;
static const int ALIGNMENT_HORIZONTAL;
static const int ALIGNMENT_HIMPLIED;
static const int ALIGNMENT_TOP;
static const int ALIGNMENT_VCENTER;
static const int ALIGNMENT_BOTTOM;
static const int ALIGNMENT_VERTICAL;
static const int ALIGNMENT_VIMPLIED;
/* Static functions */
static int decodeAlignment(const std::string &itemStr, int alignment);
static std::string encodeAlignment(int alignment);
static std::string encodeStyle(const std::set<std::string> &style);
static std::string encodeColor(const App::Color &color);
static App::Color decodeColor(const std::string &color, const App::Color &defaultColor);
private:
//void setExpression(const Expression * expr);
void setExpression(Expression *expr);
void setUsed(int mask, bool state = true);
bool isUsed(int mask) const;
void freeze();
void unfreeze();
/* Used */
static const int EXPRESSION_SET;
static const int ALIGNMENT_SET;
static const int STYLE_SET;
static const int BACKGROUND_COLOR_SET;
static const int FOREGROUND_COLOR_SET;
static const int DISPLAY_UNIT_SET;
static const int COMPUTED_UNIT_SET;
static const int ALIAS_SET;
static const int SPANS_SET;
static const int MARK_SET;
static const int SPANS_UPDATED;
static const int EXCEPTION_SET;
static const int PARSE_EXCEPTION_SET;
static const int RESOLVE_EXCEPTION_SET;
CellAddress address;
PropertySheet * owner;
int used;
Expression * expression;
int alignment;
std::set<std::string> style;
App::Color foregroundColor;
App::Color backgroundColor;
DisplayUnit displayUnit;
std::string alias;
Base::Unit computedUnit;
int rowSpan;
int colSpan;
std::string exceptionStr;
CellAddress anchor;
};
}
#endif // CELL_H

View File

@@ -0,0 +1,61 @@
/***************************************************************************
* 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 DISPLAYUNIT_H
#define DISPLAYUNIT_H
#include <string>
#include <Base/Unit.h>
namespace Spreadsheet {
class DisplayUnit {
public:
std::string stringRep;
Base::Unit unit;
double scaler;
DisplayUnit(const std::string _stringRep = "", const Base::Unit _unit = Base::Unit(), double _scaler = 0.0)
: stringRep(_stringRep)
, unit(_unit)
, scaler(_scaler)
{
}
bool operator==(const DisplayUnit& c) const
{
return c.stringRep == stringRep && c.unit == unit && c.scaler == scaler;
}
bool operator!=(const DisplayUnit& c) const
{
return !operator==(c);
}
bool isEmpty() const { return stringRep.size() == 0; }
};
}
#endif // DISPLAYUNIT_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,548 @@
/***************************************************************************
* 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 EXPRESSION_H
#define 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 Expression;
class SpreadsheetExport ExpressionVisitor {
public:
virtual ~ExpressionVisitor() {}
virtual void visit(Expression * e) = 0;
};
class SpreadsheetExport Path {
public:
class String {
public:
String(const std::string & s = "", bool _isRealString = false) : str(s), isString(_isRealString) { }
std::string getString() const { return str; }
operator std::string() const { return str; }
operator const char *() const { return str.c_str(); }
bool operator==(const String & other) const { return str == other.str; }
bool operator!=(const String & other) const { return str != other.str; }
bool operator>=(const String & other) const { return str >= other.str; }
bool operator<(const String & other) const { return str < other.str; }
bool operator>(const String & other) const { return str > other.str; }
std::string toString() const;
bool isRealString() const { return isString; }
std::string str;
bool isString;
};
struct SpreadsheetExport Component {
enum typeEnum {
SIMPLE,
MAP,
ARRAY
} ;
std::string component;
typeEnum type;
int index;
String key;
bool keyIsString;
Component(const std::string & _component, typeEnum _type = SIMPLE, int _index = -1, String _key = String());
static Component SimpleComponent(const std::string & _component);
static Component ArrayComponent(const std::string & _component, int _index);
static Component MapComponent(const std::string & _component, const String &_key);
bool operator==(const Component & other) const;
bool isSimple() const { return type == SIMPLE; }
bool isMap() const { return type == MAP; }
bool isArray() const { return type == ARRAY; }
std::string toString() const;
};
Path(const App::DocumentObject * _owner = 0, const std::string & property = std::string());
void addComponent(const Component &c) { components.push_back(c); resolve(); }
template<typename C>
void addComponents(const C &cs) { components.insert(components.end(), cs.begin(), cs.end()); resolve(); }
void setDocumentName(const String & name, bool force = false) { documentName = name; documentNameSet = force; }
const String getDocumentName() const { return documentName; }
void setDocumentObjectName(const String & name, bool force = false) { documentObjectName = name; documentObjectNameSet = force; }
const String getDocumentObjectName() const { return documentObjectName; }
const std::string & getPropertyName() const { return components[propertyIndex].component; }
const Component & getPropertyComponent(int i) const { assert(i >=0 && i < components.size()); return components[propertyIndex + i]; }
const std::string & getSubComponent(int i) const { assert(i >= 1); return components[propertyIndex - 1].component; }
std::string getSubPathStr() const;
bool operator==(const Path & other) const;
bool operator!=(const Path & other) const { return !(operator==)(other); }
bool operator<(const Path &other) const;
int numComponents() const;
static Path parse(const App::DocumentObject * _owner, const char * expr);
virtual std::string toString() const;
void resolve();
void resetResolve();
const App::Property *getProperty() const;
std::string getPythonAccessor() const;
void renameDocumentObject(const std::string & oldName, const std::string & newName);
void renameDocument(const std::string &oldName, const std::string &newName);
App::Document *getDocument() const;
protected:
const App::DocumentObject *getDocumentObject(const App::Document *doc, const std::string &name) const;
const App::DocumentObject * owner;
mutable int propertyIndex;
String documentName;
bool documentNameSet;
String documentObjectName;
bool documentObjectNameSet;
std::string propertyName;
std::vector<Component> components;
};
/**
* Base class for expressions.
*
*/
class SpreadsheetExport Expression : public Base::BaseClass {
TYPESYSTEM_HEADER();
public:
Expression(const App::DocumentObject * _owner);
virtual ~Expression();
virtual bool isTouched() const { return false; }
virtual Expression * eval() const = 0;
virtual std::string toString() const = 0;
static Expression * parse(const App::DocumentObject * owner, const std::string& buffer);
virtual Expression * copy() const = 0;
virtual int priority() const { return 0; }
virtual void getDeps(std::set<Path> &props) const { }
virtual Expression * simplify() const = 0;
virtual void visit(ExpressionVisitor & v) { v.visit(this); }
class Exception : public Base::Exception {
public:
Exception(const char *sMessage) : Base::Exception(sMessage) { }
};
const App::DocumentObject * getOwner() const { return owner; }
protected:
const App::DocumentObject * owner; /**< The document object used to access unqualified variables (i.e local scope) */
};
/**
* Part of an expressions that contains a unit.
*
*/
class SpreadsheetExport UnitExpression : public Expression {
TYPESYSTEM_HEADER();
public:
UnitExpression(const App::DocumentObject *_owner = 0, const Base::Quantity & _quantity = Base::Quantity(), const std::string & _unitStr = std::string());
virtual Expression * eval() const;
virtual Expression * simplify() const;
virtual std::string toString() const;
virtual Expression * copy() const;
virtual int priority() const { return 10; }
void setUnit(const Base::Quantity &_quantity);
double getValue() const { return quantity.getValue(); }
const Base::Unit & getUnit() const { return quantity.getUnit(); }
const Base::Quantity & getQuantity() const { return quantity; }
const std::string getUnitString() const { return unitStr; }
double getScaler() const { return quantity.getValue(); }
protected:
Base::Quantity quantity;
std::string unitStr; /**< The unit string from the original parsed string */
};
/**
* Class implementing a number with an optional unit
*/
class SpreadsheetExport NumberExpression : public UnitExpression {
TYPESYSTEM_HEADER();
public:
NumberExpression(const App::DocumentObject *_owner = 0, const Base::Quantity & quantity = Base::Quantity());
virtual Expression * eval() const;
virtual Expression * simplify() const;
virtual Expression * copy() const;
virtual int priority() const { return 10; }
void negate();
virtual std::string toString() const;
protected:
};
class SpreadsheetExport ConstantExpression : public NumberExpression {
TYPESYSTEM_HEADER();
public:
ConstantExpression(const App::DocumentObject *_owner = 0, std::string _name = "", const Base::Quantity &_quantity = Base::Quantity());
virtual std::string toString() const;
virtual Expression * copy() const;
virtual int priority() const { return 10; }
std::string getName() const { return name; }
protected:
std::string name; /**< Constant's name */
};
/**
* Class implementing an infix expression.
*
*/
class SpreadsheetExport OperatorExpression : public UnitExpression {
TYPESYSTEM_HEADER();
public:
enum Operator {
NONE,
ADD,
SUB,
MUL,
DIV,
POW,
EQ,
NEQ,
LT,
GT,
LTE,
GTE,
UNIT
};
OperatorExpression(const App::DocumentObject *_owner = 0, Expression * _left = 0, Operator _op = NONE, Expression * _right = 0);
virtual ~OperatorExpression();
virtual bool isTouched() const;
virtual Expression * eval() const;
virtual Expression * simplify() const;
virtual std::string toString() const;
virtual Expression * copy() const;
virtual int priority() const;
virtual void getDeps(std::set<Path> &props) const;
virtual void visit(ExpressionVisitor & v);
protected:
Operator op; /**< Operator working on left and right */
Expression * left; /**< Left operand */
Expression * right; /**< Right operand */
};
class SpreadsheetExport RangeExpression : public 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 0; }
virtual void getDeps(std::set<Path> &props) const;
virtual Expression * simplify() const;
Range getRange() const { return range; }
protected:
Range range;
};
class SpreadsheetExport ConditionalExpression : public Expression {
TYPESYSTEM_HEADER();
public:
ConditionalExpression(const App::DocumentObject *_owner = 0, Expression * _condition = 0,Expression * _trueExpr = 0, Expression * _falseExpr = 0);
virtual ~ConditionalExpression();
virtual bool isTouched() const;
virtual Expression * eval() const;
virtual Expression * simplify() const;
virtual std::string toString() const;
virtual Expression * copy() const;
virtual int priority() const;
virtual void getDeps(std::set<Path> &props) const;
virtual void visit(ExpressionVisitor & v);
protected:
Expression * condition; /**< Condition */
Expression * trueExpr; /**< Expression if abs(condition) is > 0.5 */
Expression * falseExpr; /**< Expression if abs(condition) is < 0.5 */
};
/**
* Class implementing various functions, e.g sin, cos, etc.
*
*/
class SpreadsheetExport FunctionExpression : public UnitExpression {
TYPESYSTEM_HEADER();
public:
enum Function {
NONE,
// Normal functions taking one or two arguments
ACOS,
ASIN,
ATAN,
ABS,
EXP,
LOG,
LOG10,
SIN,
SINH,
TAN,
TANH,
SQRT,
COS,
COSH,
ATAN2,
MOD,
POW,
// Aggregates
SUM,
AVERAGE,
STDDEV,
COUNT,
MIN,
MAX
};
FunctionExpression(const App::DocumentObject *_owner = 0, Function _f = NONE, std::vector<Expression *> _args = std::vector<Expression*>());
virtual ~FunctionExpression();
virtual bool isTouched() const;
virtual Expression * eval() const;
virtual Expression * simplify() const;
virtual std::string toString() const;
virtual Expression * copy() const;
virtual int priority() const { return 10; }
virtual void getDeps(std::set<Path> &props) const;
virtual void visit(ExpressionVisitor & v);
protected:
Function f; /**< Function to execute */
std::vector<Expression *> args; /** Arguments to function*/
};
/**
* Class implementing a reference to a property. If the name is unqualified,
* the owner of the expression is searched. If it is qualified, the document
* that contains the owning document object is searched for other document
* objects to search. Both labels and internal document names are searched.
*
*/
class SpreadsheetExport VariableExpression : public UnitExpression {
TYPESYSTEM_HEADER();
public:
VariableExpression(const App::DocumentObject *_owner = 0, Path _var = Path());
~VariableExpression();
virtual bool isTouched() const;
virtual Expression * eval() const;
virtual Expression * simplify() const;
virtual std::string toString() const { return var.toString(); }
virtual Expression * copy() const;
virtual int priority() const { return 10; }
virtual void getDeps(std::set<Path> &props) const;
std::string name() const { return var.getPropertyName(); }
Path getPath() const { return var; }
void setName(const std::string & name) { assert(0); }
void resolve();
void renameDocumentObject(const std::string & oldName, const std::string & newName);
void renameDocument(const std::string &oldName, const std::string &newName);
protected:
const App::Property *getProperty() const;
Path var; /**< Variable name */
};
/**
* Class implementing a string. Used to signal either a genuine string or
* a failed evaluation of an expression.
*/
class SpreadsheetExport StringExpression : public Expression {
TYPESYSTEM_HEADER();
public:
StringExpression(const App::DocumentObject *_owner = 0, const std::string & _text = std::string());
virtual Expression * eval() const;
virtual Expression * simplify() const;
virtual std::string toString() const;
virtual std::string getText() const { return text; }
virtual Expression * copy() const;
protected:
std::string text; /**< Text string */
};
namespace ExpressionParser {
SpreadsheetExport Expression * parse(const App::DocumentObject *owner, const char *buffer);
SpreadsheetExport UnitExpression * parseUnit(const App::DocumentObject *owner, const char *buffer);
SpreadsheetExport Path parsePath(const App::DocumentObject *owner, const char* buffer);
}
}
#endif // EXPRESSION_H

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
/* 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 */
%{
class semantic_type {
public:
struct {
Quantity scaler;
std::string unitStr;
} quantity;
Expression * expr;
Path path;
std::deque<Path::Component> components;
int ivalue;
double fvalue;
struct {
std::string name;
double fvalue;
} constant;
std::vector<Expression*> arguments;
std::string string;
FunctionExpression::Function func;
Path::String string_or_identifier;
semantic_type() {}
};
#define YYSTYPE 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 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> NUM
%type <constant> CONSTANT
%type <expr> num
%type <expr> range
%type <path> identifier
%type <components> path
%type <func> FUNC
%type <string_or_identifier> document
%type <string_or_identifier> object
%left NUM
%left INTEGER
%left CONSTANT
%left '-' '+'
%left '*' '/'
%left '?' ':' EQ NEQ LT GT GTE LTE
%left NEG /* negation--unary minus */
%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); }
| exp '+' exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::ADD, $3); }
| exp '-' 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); }
| MINUSSIGN exp %prec NEG { $$ = new OperatorExpression(DocumentObject,
new NumberExpression(DocumentObject, -1.0),
OperatorExpression::MUL, $2); }
| exp '^' exp %prec NUM { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, $3); }
| '(' exp ')' { $$ = $2; }
| FUNC args ')' { $$ = new FunctionExpression(DocumentObject, $1, $2); }
| cond '?' exp ':' exp { $$ = new ConditionalExpression(DocumentObject, $1, $3, $5); }
;
num: NUM { $$ = new NumberExpression(DocumentObject, $1); }
| INTEGER { $$ = new NumberExpression(DocumentObject, (double)$1); }
| CONSTANT { $$ = new ConstantExpression(DocumentObject, $1.name, $1.fvalue); }
| NUM unit_exp %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, $1), OperatorExpression::UNIT, $2); }
| INTEGER unit_exp { $$ = new OperatorExpression(DocumentObject, new NumberExpression(DocumentObject, (double)$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 ); }
| unit_exp '/' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::DIV, $3); }
| unit_exp '*' unit_exp { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::MUL, $3); }
| unit_exp '^' NUM %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, $3)); }
| unit_exp '^' '-' NUM %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, -$4)); }
| unit_exp '^' INTEGER %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, (double)$3)); }
| unit_exp '^' MINUSSIGN INTEGER %prec EXPONENT { $$ = new OperatorExpression(DocumentObject, $1, OperatorExpression::POW, new NumberExpression(DocumentObject, -(double)$4)); }
| '(' unit_exp ')' { $$ = $2; }
;
identifier: path { /* Path to property within document object */
$$ = Path(DocumentObject);
$$.addComponents($1);
}
| object '.' path { /* Path to property within document object */
$$ = Path(DocumentObject);
$$.setDocumentObjectName($1, true);
$$.addComponents($3);
}
| document '#' path { /* Path to property from an external document, within a named document object */
$$ = Path(DocumentObject);
$$.setDocumentName($1, true);
$$.addComponents($3);
}
| document '#' object '.' path { /* Path to property from an external document, within a named document object */
$$ = Path(DocumentObject);
$$.setDocumentName($1, true);
$$.setDocumentObjectName($3, true);
$$.addComponents($5);
}
;
path: IDENTIFIER { $$.push_front(Path::Component::SimpleComponent($1)); }
| CELLADDRESS { $$.push_front(Path::Component::SimpleComponent($1)); }
| IDENTIFIER '[' INTEGER ']' { $$.push_front(Path::Component::ArrayComponent($1, $3)); }
| IDENTIFIER '[' INTEGER ']' '.' path { $6.push_front(Path::Component::ArrayComponent($1, $3)); $$ = $6; }
| IDENTIFIER '[' STRING ']' { $$.push_front(Path::Component::MapComponent($1, Path::String($3, true))); }
| IDENTIFIER '[' IDENTIFIER ']' { $$.push_front(Path::Component::MapComponent($1, $3)); }
| IDENTIFIER '[' STRING ']' '.' path { $6.push_front(Path::Component::MapComponent($1, Path::String($3, true))); $$ = $6; }
| IDENTIFIER '[' IDENTIFIER ']' '.' path { $6.push_front(Path::Component::MapComponent($1, $3)); $$ = $6; }
| IDENTIFIER '.' path { $3.push_front(Path::Component::SimpleComponent($1)); $$ = $3; }
;
document: STRING { $$ = Path::String($1, true); }
| IDENTIFIER { $$ = Path::String($1); }
;
object: STRING { $$ = Path::String($1, true); }
| CELLADDRESS { $$ = Path::String($1, true); }
;
%%

View File

@@ -0,0 +1,24 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2002 *
* *
* 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"

View File

@@ -0,0 +1,59 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2002 *
* *
* 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 __PRECOMPILED__
#define __PRECOMPILED__
#include <FCConfig.h>
// Exporting of App classes
#ifdef FC_OS_WIN32
# define SpreadsheetExport __declspec(dllexport)
#else // for Linux
# define SpreadsheetExport
#endif
#ifdef _PreComp_
/// here get the warnings of to long specifieres disabled (needed for VC6)
#ifdef _MSC_VER
# pragma warning( disable : 4251 )
# pragma warning( disable : 4503 )
# pragma warning( disable : 4786 ) // specifier longer then 255 chars
#endif
// standard
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <assert.h>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <bitset>
#include <Python.h>
#endif // _PreComp_
#endif

View File

@@ -0,0 +1,157 @@
/***************************************************************************
* 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"
#ifndef _PreComp_
#endif
#include "PropertyColumnWidths.h"
#include <Base/Writer.h>
#include <Base/Reader.h>
#include "Utils.h"
#include <PropertyColumnWidthsPy.h>
using namespace App;
using namespace Spreadsheet;
const int PropertyColumnWidths::defaultWidth = 100;
const int PropertyColumnWidths::defaultHeaderWidth = 50;
TYPESYSTEM_SOURCE(Spreadsheet::PropertyColumnWidths , App::Property);
PropertyColumnWidths::PropertyColumnWidths()
{
}
PropertyColumnWidths::PropertyColumnWidths(const PropertyColumnWidths &other)
{
std::map<int, int>::const_iterator i = other.begin();
while (i != other.end()) {
insert(*i);
++i;
}
}
App::Property *PropertyColumnWidths::Copy() const
{
PropertyColumnWidths * prop = new PropertyColumnWidths(*this);
return prop;
}
void PropertyColumnWidths::Paste(const App::Property &from)
{
aboutToSetValue();
const PropertyColumnWidths * frompcw = static_cast<const PropertyColumnWidths*>(&from);
std::map<int, int>::const_iterator i;
/* Mark all as dirty first */
i = begin();
while (i != end()) {
dirty.insert(i->first);
++i;
}
/* Clear old map */
clear();
/* Copy new map from from */
i = frompcw->begin();
while (i != frompcw->end()) {
insert(*i);
dirty.insert(i->first);
++i;
}
hasSetValue();
}
/**
* Set the width (in pixels) of column \a col to \a width.
*
* @param col Column to set
* @param width Width in pixels
*
*/
void PropertyColumnWidths::setValue(int col, int width)
{
if (width >= 0) {
aboutToSetValue();
operator[](col) = width;
dirty.insert(col);
hasSetValue();
}
}
void PropertyColumnWidths::Save(Base::Writer &writer) const
{
// Save column information
writer.Stream() << writer.ind() << "<ColumnInfo Count=\"" << size() << "\">" << std::endl;
writer.incInd(); // indention for 'ColumnInfo'
std::map<int, int>::const_iterator coli = begin();
while (coli != end()) {
writer.Stream() << writer.ind() << "<Column name=\"" << columnName(coli->first) << "\" width=\"" << coli->second << "\" />" << std::endl;
++coli;
}
writer.decInd(); // indention for 'ColumnInfo'
writer.Stream() << writer.ind() << "</ColumnInfo>" << std::endl;
}
void PropertyColumnWidths::Restore(Base::XMLReader &reader)
{
int Cnt;
// Column info
reader.readElement("ColumnInfo");
Cnt = reader.hasAttribute("Count") ? reader.getAttributeAsInteger("Count") : 0;
for (int i = 0; i < Cnt; i++) {
reader.readElement("Column");
const char* name = reader.hasAttribute("name") ? reader.getAttribute("name") : 0;
const char * width = reader.hasAttribute("width") ? reader.getAttribute("width") : 0;
try {
if (name && width) {
int col = decodeColumn(name);
int colWidth = atoi(width);
setValue(col, colWidth);
}
}
catch (...) {
// Something is wrong, skip this column
}
}
reader.readEndElement("ColumnInfo");
}
PyObject *PropertyColumnWidths::getPyObject()
{
if (PythonObject.is(Py::_None())){
// ref counter is set to 1
PythonObject = Py::Object(new PropertyColumnWidthsPy(this),true);
}
return Py::new_reference_to(PythonObject);
}

View File

@@ -0,0 +1,78 @@
/***************************************************************************
* 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 PROPERTYCOLUMNWIDTHS_H
#define PROPERTYCOLUMNWIDTHS_H
#include <map>
#include <App/Property.h>
#include <CXX/Objects.hxx>
namespace Spreadsheet {
class SpreadsheetExport PropertyColumnWidths : public App::Property, std::map<int, int>
{
TYPESYSTEM_HEADER();
public:
PropertyColumnWidths();
PropertyColumnWidths(const PropertyColumnWidths & other);
void setValue() { }
void setValue(int col, int width);
std::map<int, int> getValues() const {
return *this;
}
int getValue(int column) const { return find(column) != end() ? at(column) : defaultWidth; }
virtual Property *Copy(void) const;
virtual void Paste(const Property &from);
virtual void Save (Base::Writer & writer) const;
virtual void Restore(Base::XMLReader & reader);
bool isDirty() const { return dirty.size() > 0; }
void clearDirty() { dirty.clear(); }
const std::set<int> & getDirty() const { return dirty; }
PyObject *getPyObject(void);
static const int defaultWidth;
static const int defaultHeaderWidth;
private:
std::set<int> dirty;
Py::Object PythonObject;
};
}
#endif // PROPERTYCOLUMNWIDTHS_H

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="PersistencePy"
Name="PropertyColumnWidthsPy"
Twin="PropertyColumnWidths"
TwinPointer="PropertyColumnWidths"
Include="Mod/Spreadsheet/App/PropertyColumnWidths.h"
Namespace="Spreadsheet"
FatherInclude="Base/PersistencePy.h"
FatherNamespace="Base"
Constructor="true">
<Documentation>
<Author Licence="LGPL" Name="Eivind Kvedalen" EMail="eivind@kvedalen.name" />
<UserDocu>Internal spreadsheet object</UserDocu>
</Documentation>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,150 @@
/***************************************************************************
* 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"
#ifndef _PreComp_
#endif
#include "PropertyRowHeights.h"
#include <Base/Writer.h>
#include <Base/Reader.h>
#include "Utils.h"
#include <PropertyRowHeightsPy.h>
using namespace App;
using namespace Spreadsheet;
const int PropertyRowHeights::defaultHeight = 20;
TYPESYSTEM_SOURCE(Spreadsheet::PropertyRowHeights , App::Property);
PropertyRowHeights::PropertyRowHeights()
{
}
PropertyRowHeights::PropertyRowHeights(const PropertyRowHeights &other)
{
}
Property *PropertyRowHeights::Copy() const
{
PropertyRowHeights * prop = new PropertyRowHeights(*this);
return prop;
}
void PropertyRowHeights::Paste(const Property &from)
{
aboutToSetValue();
const PropertyRowHeights * fromprh = static_cast<const PropertyRowHeights*>(&from);
std::map<int, int>::const_iterator i;
/* Mark all as dirty first */
i = begin();
while (i != end()) {
dirty.insert(i->first);
++i;
}
/* Clear old map */
clear();
/* Copy new map from from */
i = fromprh->begin();
while (i != fromprh->end()) {
insert(*i);
dirty.insert(i->first);
++i;
}
hasSetValue();
}
void PropertyRowHeights::Save(Base::Writer &writer) const
{
// Save row information
writer.Stream() << writer.ind() << "<RowInfo Count=\"" << size() << "\">" << std::endl;
writer.incInd(); // indention for 'RowInfo'
std::map<int, int>::const_iterator ri = begin();
while (ri != end()) {
writer.Stream() << writer.ind() << "<Row name=\"" << rowName(ri->first) << "\" height=\"" << ri->second << "\" />" << std::endl;
++ri;
}
writer.decInd(); // indention for 'RowInfo'
writer.Stream() << writer.ind() << "</RowInfo>" << std::endl;
}
/**
* Set height of row given by \a row to \a height in pixels.
*
* @param row Address of row
* @param height Height in pixels
*
*/
void PropertyRowHeights::setValue(int row, int height)
{
if (height >= 0) {
aboutToSetValue();
operator[](row) = height;
dirty.insert(row);
hasSetValue();
}
}
void PropertyRowHeights::Restore(Base::XMLReader &reader)
{
int Cnt;
// Row info
reader.readElement("RowInfo");
Cnt = reader.hasAttribute("Count") ? reader.getAttributeAsInteger("Count") : 0;
for (int i = 0; i < Cnt; i++) {
reader.readElement("Row");
const char* name = reader.hasAttribute("name") ? reader.getAttribute("name") : 0;
const char * height = reader.hasAttribute("height") ? reader.getAttribute("height") : 0;
try {
if (name && height) {
int row = decodeRow(name);
int rowHeight = atoi(height);
setValue(row, rowHeight);
}
}
catch (...) {
// Something is wrong, skip this row
}
}
reader.readEndElement("RowInfo");
}
PyObject *PropertyRowHeights::getPyObject()
{
if (PythonObject.is(Py::_None())){
// ref counter is set to 1
PythonObject = Py::Object(new PropertyRowHeightsPy(this),true);
}
return Py::new_reference_to(PythonObject);
}

View File

@@ -0,0 +1,77 @@
/***************************************************************************
* 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 PROPERTYROWHEIGHTS_H
#define PROPERTYROWHEIGHTS_H
#include <map>
#include <App/Property.h>
#include <CXX/Objects.hxx>
namespace Spreadsheet {
class SpreadsheetExport PropertyRowHeights : public App::Property, std::map<int, int>
{
TYPESYSTEM_HEADER();
public:
PropertyRowHeights();
PropertyRowHeights(const PropertyRowHeights & other);
void setValue() { }
void setValue(int row, int height);
int getValue(int row) const { return find(row) != end() ? at(row) : 20; }
std::map<int, int> getValues() const {
return *this;
}
virtual App::Property *Copy(void) const;
virtual void Paste(const App::Property &from);
virtual void Save (Base::Writer & writer) const;
virtual void Restore(Base::XMLReader & reader);
bool isDirty() const { return dirty.size() > 0; }
void clearDirty() { dirty.clear(); }
const std::set<int> & getDirty() const { return dirty; }
PyObject *getPyObject(void);
static const int defaultHeight;
private:
std::set<int> dirty;
Py::Object PythonObject;
};
}
#endif // PROPERTYROWHEIGHTS_H

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="PersistencePy"
Name="PropertyRowHeightsPy"
Twin="PropertyRowHeights"
TwinPointer="PropertyRowHeights"
Include="Mod/Spreadsheet/App/PropertyRowHeights.h"
Namespace="Spreadsheet"
FatherInclude="Base/PersistencePy.h"
FatherNamespace="Base"
Constructor="true">
<Documentation>
<Author Licence="LGPL" Name="Eivind Kvedalen" EMail="eivind@kvedalen.name" />
<UserDocu>Internal spreadsheet object</UserDocu>
</Documentation>
</PythonExport>
</GenerateModel>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,218 @@
/***************************************************************************
* 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 PROPERTYSHEET_H
#define PROPERTYSHEET_H
#include <map>
#include <App/DocumentObserver.h>
#include <App/DocumentObject.h>
#include <App/Property.h>
#include <App/PropertyLinks.h>
#include "Cell.h"
namespace Spreadsheet
{
class Sheet;
class PropertySheet;
class SheetObserver;
class PropertySheet : public App::Property {
TYPESYSTEM_HEADER();
public:
PropertySheet(Sheet * _owner = 0);
PropertySheet(const PropertySheet & other);
~PropertySheet();
virtual Property *Copy(void) const;
virtual void Paste(const Property &from);
virtual void Save (Base::Writer & writer) const;
virtual void Restore(Base::XMLReader & reader);
Cell *createCell(CellAddress address);
void setValue() { }
void setContent(CellAddress address, const char * value);
void setAlignment(CellAddress address, int _alignment);
void setStyle(CellAddress address, const std::set<std::string> & _style);
void setForeground(CellAddress address, const App::Color &color);
void setBackground(CellAddress address, const App::Color &color);
void setDisplayUnit(CellAddress address, const std::string & unit);
void setAlias(CellAddress address, const std::string &alias);
void setComputedUnit(CellAddress address, const Base::Unit & unit);
void setSpans(CellAddress address, int rows, int columns);
void clear(CellAddress address);
void clear();
Cell * getValue(CellAddress key);
std::set<CellAddress> getUsedCells() const;
Sheet * sheet() const { return owner; }
const std::set<CellAddress> & getDirty() { return dirty; }
void setDirty(CellAddress address);
void clearDirty(CellAddress key) { dirty.erase(key); }
void clearDirty() { dirty.clear(); purgeTouched(); }
bool isDirty() const { return dirty.size() > 0; }
void moveCell(CellAddress currPos, CellAddress newPos);
void insertRows(int row, int count);
void removeRows(int row, int count);
void insertColumns(int col, int count);
void removeColumns(int col, int count);
unsigned int getMemSize (void);
bool mergeCells(CellAddress from, CellAddress to);
void splitCell(CellAddress address);
void getSpans(CellAddress address, int &rows, int &cols) const;
bool isMergedCell(CellAddress address) const;
bool isHidden(CellAddress address) const;
const std::set< CellAddress > & getDeps(const std::string & name) const;
const std::set<std::string> &getDeps(CellAddress pos) const;
const std::vector<App::DocumentObject*> & getDocDeps() const { return docDeps; }
class Signaller {
public:
Signaller(PropertySheet & sheet);
~Signaller();
private:
PropertySheet & mSheet;
};
void recomputeDependencies(CellAddress key);
PyObject *getPyObject(void);
void resolveAll();
void invalidateDependants(const App::DocumentObject *docObj);
void renamedDocumentObject(const App::DocumentObject *docObj);
void renamedDocument(const App::Document *doc);
private:
friend class Signaller;
friend class SheetObserver;
Cell *cellAt(CellAddress address);
Cell *nonNullCellAt(CellAddress address);
const Cell *cellAt(CellAddress address) const;
bool colSortFunc(const CellAddress &a, const CellAddress &b);
bool rowSortFunc(const CellAddress &a, const CellAddress &b);
friend class Cell;
std::map<CellAddress, Cell*> data;
std::set<CellAddress> dirty;
/* Merged cells; cell -> anchor cell */
std::map<CellAddress, CellAddress> mergedCells;
Sheet * owner;
/*
* Cell dependency tracking
*/
void addDependencies(CellAddress key);
void removeDependencies(CellAddress key);
void recomputeDependants(const App::Property * prop);
void recomputeDependants(const App::DocumentObject * docObj);
/* 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;
/* Properties this cell depends on */
std::map<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;
/* DocumentObject this cell depends on */
std::map<CellAddress, std::set< std::string > > cellToDocumentObjectMap;
/* Other document objects the sheet depends on */
std::vector<App::DocumentObject*> docDeps;
/* Name of document objects, used for renaming */
std::map<const App::DocumentObject*, std::string> documentObjectName;
/* Name of documents, used for renaming */
std::map<const App::Document*, std::string> documentName;
int signalCounter;
Py::Object PythonObject;
};
}
#endif // PROPERTYSHEET_H

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="PersistencePy"
Name="PropertySheetPy"
Twin="PropertySheet"
TwinPointer="PropertySheet"
Include="Mod/Spreadsheet/App/PropertySheet.h"
Namespace="Spreadsheet"
FatherInclude="Base/PersistencePy.h"
FatherNamespace="Base"
Constructor="true">
<Documentation>
<Author Licence="LGPL" Name="Eivind Kvedalen" EMail="eivind@kvedalen.name" />
<UserDocu>Internal spreadsheet object</UserDocu>
</Documentation>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,86 @@
/***************************************************************************
* 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)
{
}
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

@@ -0,0 +1,89 @@
/***************************************************************************
* 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);
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 addressToString(CellAddress(row_begin, col_begin)); }
/** End of range as a string */
inline std::string toCellString() const { return addressToString(CellAddress(row_end, col_end)); }
/** Current cell as a string */
inline std::string address() const { return addressToString(CellAddress(row_curr, col_curr)); }
/** The raneg as a string */
inline std::string rangeString() const {
return addressToString(CellAddress(row_begin, col_begin)) + ":" + addressToString(CellAddress(row_end, col_end));
}
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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,281 @@
/***************************************************************************
* 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_Spreadsheet_H
#define Spreadsheet_Spreadsheet_H
#ifdef signals
#undef signals
#define signals signals
#endif
#include <App/DocumentObject.h>
#include <App/DocumentObserver.h>
#include <App/PropertyFile.h>
#include <App/PropertyUnits.h>
#include <App/PropertyLinks.h>
#include <App/PropertyStandard.h>
#include <App/DynamicProperty.h>
#include <App/Material.h>
#include <Base/Unit.h>
#include <map>
#include "PropertySheet.h"
#include "PropertyColumnWidths.h"
#include "PropertyRowHeights.h"
#include "Utils.h"
namespace Spreadsheet
{
class Sheet;
class Cell;
class Expression;
class Range;
class SheetObserver;
class SpreadsheetExport Sheet : public App::DocumentObject
{
PROPERTY_HEADER(Sheet::Sheet);
public:
/// Constructor
Sheet();
virtual ~Sheet();
/// returns the type name of the ViewProvider
virtual const char* getViewProviderName(void) const {
return "SpreadsheetGui::ViewProviderSheet";
}
bool importFromFile(const std::string & filename, char delimiter = '\t', char quoteChar = '\0', char escapeChar = '\\');
bool exportToFile(const std::string & filename, char delimiter = '\t', char quoteChar = '\0', char escapeChar = '\\') const;
bool mergeCells(const Range &range);
void splitCell(CellAddress address);
Cell * getCell(CellAddress address);
Cell *getNewCell(CellAddress address);
void setCell(const char *address, const char *value);
void setCell(CellAddress address, const char *value);
void clearAll();
void clear(CellAddress address, bool all = true);
void getSpans(CellAddress address, int & rows, int & cols) const;
bool isMergedCell(CellAddress address) const;
void setColumnWidth(int col, int width);
int getColumnWidth(int col) const;
void setRowHeight(int row, int height);
int getRowHeight(int row) const;
std::vector<std::string> getUsedCells() const;
void insertColumns(int col, int count);
void removeColumns(int col, int count);
void insertRows(int row, int count);
void removeRows(int row, int count);
void setContent(CellAddress address, const char * value);
void setAlignment(CellAddress address, int _alignment);
void setStyle(CellAddress address, const std::set<std::string> & _style);
void setForeground(CellAddress address, const App::Color &color);
void setBackground(CellAddress address, const App::Color &color);
void setDisplayUnit(CellAddress address, const std::string & unit);
void setComputedUnit(CellAddress address, const Base::Unit & unit);
void setAlias(CellAddress address, const std::string & alias);
void setSpans(CellAddress address, int rows, int columns);
std::set<std::string> dependsOn(CellAddress address) const;
void providesTo(CellAddress address, std::set<std::string> & result) const;
PyObject *getPyObject();
App::Property *getPropertyByName(const char *name) const;
const char* getPropertyName(const App::Property* prop) const;
virtual short mustExecute(void) const;
App::DocumentObjectExecReturn *execute(void);
void getCellAddress(const App::Property *prop, CellAddress &address);
std::map<int, int> getColumnWidths() const;
std::map<int, int> getRowHeights() const;
void setPosition(CellAddress address);
// Signals
boost::signal<void (Spreadsheet::CellAddress)> cellUpdated;
boost::signal<void (Spreadsheet::CellAddress)> cellSpanChanged;
boost::signal<void (int, int)> columnWidthChanged;
boost::signal<void (int, int)> rowHeightChanged;
boost::signal<void (CellAddress)> positionChanged;
/** @name Access properties */
//@{
App::Property* addDynamicProperty(
const char* type, const char* name=0,
const char* group=0, const char* doc=0,
short attr=0, bool ro=false, bool hidden=false) {
return props.addDynamicProperty(type, name, group, doc, attr, ro, hidden);
}
virtual bool removeDynamicProperty(const char* name) {
return props.removeDynamicProperty(name);
}
std::vector<std::string> getDynamicPropertyNames() const {
return props.getDynamicPropertyNames();
}
App::Property *getDynamicPropertyByName(const char* name) const {
return props.getDynamicPropertyByName(name);
}
virtual void addDynamicProperties(const App::PropertyContainer* cont) {
return props.addDynamicProperties(cont);
}
/// get all properties of the class (including properties of the parent)
virtual void getPropertyList(std::vector<App::Property*> &List) const {
props.getPropertyList(List);
}
/// get all properties of the class (including parent)
void getPropertyMap(std::map<std::string,App::Property*> &Map) const {
props.getPropertyMap(Map);
}
short getPropertyType(const App::Property *prop) const {
props.getPropertyType(prop);
}
/// get the name of a property
virtual const char* getName(const App::Property* prop) const {
return props.getPropertyName(prop);
}
//@}
void observeDocument(const std::string &docName);
protected:
void providesTo(CellAddress address, std::set<CellAddress> & result) const;
void onDocumentRestored();
void onRelabledDocument(const App::Document & document);
void onRenamedDocument(const App::Document & document);
void recomputeCell(CellAddress p);
App::Property *getProperty(CellAddress key) const;
App::Property *getProperty(const char * addr) const;
void updateProperty(CellAddress key);
App::Property *setStringProperty(CellAddress key, const std::string & value) ;
App::Property *setFloatProperty(CellAddress key, double value);
App::Property *setQuantityProperty(CellAddress key, double value, const Base::Unit &unit);
static std::string toAddress(CellAddress key);
void moveCell(CellAddress currPos, CellAddress newPos);
void renamedDocumentObject(const App::DocumentObject * docObj);
/* Properties for used cells */
App::DynamicProperty props;
/* Mapping of properties to cell position */
std::map<const App::Property*, CellAddress > propAddress;
/* Mapping of cell position to alias property */
std::map<CellAddress, App::Property*> aliasProp;
/* Set of cells with errors */
std::set<CellAddress> cellErrors;
/* Properties */
/* Cell data */
PropertySheet cells;
/* Column widths */
PropertyColumnWidths columnWidths;
/* Row heights */
PropertyRowHeights rowHeights;
App::PropertyInteger currRow;
App::PropertyInteger currColumn;
/* Dependencies to other documents */
App::PropertyLinkList docDeps;
/* Document observers to track changes to external properties */
typedef std::map<std::string, SheetObserver* > ObserverMap;
ObserverMap observers;
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection onRelabledDocumentConnection;
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection onRenamedDocumentConnection;
friend class SheetObserver;
friend class PropertySheet;
};
} //namespace Spreadsheet
#endif // Spreadsheet_Spreadsheet_H

View File

@@ -0,0 +1,126 @@
/***************************************************************************
* 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 "SheetObserver.h"
#include "PropertySheet.h"
using namespace Spreadsheet;
using namespace App;
/**
* The SheetObserver constructor.
*
* @param document The Document we are observing
* @param _sheet The sheet owning this observer.
*
*/
SheetObserver::SheetObserver(App::Document * document, PropertySheet *_sheet)
: DocumentObserver(document)
, sheet(_sheet)
, refCount(1)
{
}
/**
* Unimplemented.
*
*/
void SheetObserver::slotCreatedDocument(const App::Document &Doc)
{
}
/**
* Unimplemented.
*
*/
void SheetObserver::slotDeletedDocument(const App::Document &Doc)
{
}
/**
* Invalidate cells that depend on this document object.
*
*/
void SheetObserver::slotCreatedObject(const DocumentObject &Obj)
{
sheet->invalidateDependants(&Obj);
}
/**
* Invalidate cells that depend on this document object.
*
*/
void SheetObserver::slotDeletedObject(const DocumentObject &Obj)
{
sheet->invalidateDependants(&Obj);
}
/**
* Invoke the sheets recomputeDependants when a change to a Property occurs.
*
*/
void SheetObserver::slotChangedObject(const DocumentObject &Obj, const Property &Prop)
{
const char * name = Obj.getPropertyName(&Prop);
assert(name != 0);
if (&Prop == &Obj.Label)
sheet->renamedDocumentObject(&Obj);
else {
if (isUpdating.find(name) != isUpdating.end())
return;
isUpdating.insert(name);
sheet->recomputeDependants(&Prop);
isUpdating.erase(name);
}
}
/**
* Increase reference count.
*
*/
void SheetObserver::ref()
{
refCount++;
}
/**
* Decrease reference count.
*
*/
bool SheetObserver::unref()
{
refCount--;
return refCount;
}

View File

@@ -0,0 +1,52 @@
/***************************************************************************
* 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 SHEETOBSERVER_H
#define SHEETOBSERVER_H
#include <App/DocumentObserver.h>
namespace Spreadsheet {
class PropertySheet;
class SheetObserver : public App::DocumentObserver {
public:
SheetObserver(App::Document* document, PropertySheet *_sheet);
~SheetObserver() { }
virtual void slotCreatedDocument(const App::Document& Doc);
virtual void slotDeletedDocument(const App::Document& Doc);
virtual void slotCreatedObject(const App::DocumentObject& Obj);
virtual void slotDeletedObject(const App::DocumentObject& Obj);
virtual void slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop);
void ref();
bool unref();
App::Document* getDocument() const { return App::DocumentObserver::getDocument(); }
private:
std::set<std::string> isUpdating;
int refCount;
PropertySheet * sheet;
};
}
#endif // SHEETOBSERVER_H

View File

@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="DocumentObjectPy"
Name="SheetPy"
Twin="Sheet"
TwinPointer="Sheet"
Include="Mod/Spreadsheet/App/Sheet.h"
Namespace="Spreadsheet"
FatherInclude="App/DocumentObjectPy.h"
FatherNamespace="App"
Constructor="true">
<Documentation>
<Author Licence="LGPL" Name="Eivind Kvedalen" EMail="eivind@kvedalen.name" />
<UserDocu>With this object you can manipulate spreadsheets</UserDocu>
</Documentation>
<Methode Name="set">
<Documentation>
<UserDocu>Set data into a cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="get">
<Documentation>
<UserDocu>Get evaluated cell contents</UserDocu>
</Documentation>
</Methode>
<Methode Name="getContents">
<Documentation>
<UserDocu>Get cell contents</UserDocu>
</Documentation>
</Methode>
<Methode Name="clear">
<Documentation>
<UserDocu>Clear a cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="clearAll">
<Documentation>
<UserDocu>Clear all cells in the spreadsheet</UserDocu>
</Documentation>
</Methode>
<Methode Name="importFile">
<Documentation>
<UserDocu>Import file into spreadsheet</UserDocu>
</Documentation>
</Methode>
<Methode Name="exportFile">
<Documentation>
<UserDocu>Export file from spreadsheet</UserDocu>
</Documentation>
</Methode>
<Methode Name="mergeCells">
<Documentation>
<UserDocu>Merge given cell area into one cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="splitCell">
<Documentation>
<UserDocu>Split a perviously merged cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="insertColumns">
<Documentation>
<UserDocu>Insert a given number of columns into the spreadsheet.</UserDocu>
</Documentation>
</Methode>
<Methode Name="removeColumns">
<Documentation>
<UserDocu>Remove a given number of columns from the spreadsheet.</UserDocu>
</Documentation>
</Methode>
<Methode Name="insertRows">
<Documentation>
<UserDocu>Insert a given number of rows into the spreadsheet.</UserDocu>
</Documentation>
</Methode>
<Methode Name="removeRows">
<Documentation>
<UserDocu>Remove a given number of rows from the spreadsheet.</UserDocu>
</Documentation>
</Methode>
<Methode Name="setAlignment">
<Documentation>
<UserDocu>Set alignment of the cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="getAlignment">
<Documentation>
<UserDocu>Get alignment of the cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="setStyle">
<Documentation>
<UserDocu>Set style of the cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="getStyle">
<Documentation>
<UserDocu>Get style of the cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="setDisplayUnit">
<Documentation>
<UserDocu>Set display unit for cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="setAlias">
<Documentation>
<UserDocu>Set alias for cell address</UserDocu>
</Documentation>
</Methode>
<Methode Name="getDisplayUnit">
<Documentation>
<UserDocu>Get display unit for cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="setForeground">
<Documentation>
<UserDocu>Set foreground color of the cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="getForeground">
<Documentation>
<UserDocu>Get foreground color of the cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="setBackground">
<Documentation>
<UserDocu>Set background color of the cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="getBackground">
<Documentation>
<UserDocu>Get background color of the cell</UserDocu>
</Documentation>
</Methode>
<Methode Name="setColumnWidth">
<Documentation>
<UserDocu>Set given spreadsheet column to given width</UserDocu>
</Documentation>
</Methode>
<Methode Name="getColumnWidth">
<Documentation>
<UserDocu>Get given spreadsheet column width</UserDocu>
</Documentation>
</Methode>
<Methode Name="setRowHeight">
<Documentation>
<UserDocu>Set given spreadsheet row to given height</UserDocu>
</Documentation>
</Methode>
<Methode Name="getRowHeight">
<Documentation>
<UserDocu>Get given spreadsheet row height</UserDocu>
</Documentation>
</Methode>
<Methode Name="setPosition">
<Documentation>
<UserDocu>Set focused cell for attached view(s).</UserDocu>
</Documentation>
</Methode>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,892 @@
/***************************************************************************
* Copyright (c) Eivind Kvedalen (eivind@kvedalen.name) 2015 *
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2010 *
* *
* 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 <boost/tokenizer.hpp>
#include <Base/Exception.h>
#include <Mod/Spreadsheet/App/Sheet.h>
#include <App/PropertyStandard.h>
#include "Utils.h"
#include "Range.h"
// inclusion of the generated files (generated out of SheetPy.xml)
#include "SheetPy.h"
#include "SheetPy.cpp"
using namespace Spreadsheet;
using namespace App;
// returns a string which represents the object e.g. when printed in python
std::string SheetPy::representation(void) const
{
return std::string("<Sheet object>");
}
PyObject *SheetPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
{
// create a new instance of SheetPy and the Twin object
return new SheetPy(new Sheet());
}
// constructor method
int SheetPy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
{
return 0;
}
// +++ methodes implementer ++++++++++++++++++++++++++++++++++++++++++++++++
PyObject* SheetPy::set(PyObject *args)
{
char *address;
char *contents;
if (!PyArg_ParseTuple(args, "ss:set", &address, &contents))
return 0;
try {
Range rangeIter(address);
do {
getSheetPtr()->setCell(rangeIter.address().c_str(), contents);
} while (rangeIter.next());
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
Py_Return;
}
PyObject* SheetPy::get(PyObject *args)
{
char *address;
if (!PyArg_ParseTuple(args, "s:get", &address))
return 0;
App::Property * prop = this->getSheetPtr()->getPropertyByName(address);
if (prop == 0) {
PyErr_SetString(PyExc_ValueError, "Invalid address or property.");
return 0;
}
return prop->getPyObject();
}
PyObject* SheetPy::getContents(PyObject *args)
{
char *strAddress;
CellAddress address;
if (!PyArg_ParseTuple(args, "s:getContents", &strAddress))
return 0;
try {
address = stringToAddress(strAddress);
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
std::string contents;
const Cell * cell = this->getSheetPtr()->getCell(address);
if (cell)
cell->getStringContent( contents );
return Py::new_reference_to( Py::String( contents ) );
}
PyObject* SheetPy::clear(PyObject *args)
{
const char * strAddress;
int all = 1;
if (!PyArg_ParseTuple(args, "s|p:clear", &strAddress, &all))
return 0;
try {
Range rangeIter(strAddress);
do {
this->getSheetPtr()->clear(*rangeIter, all);
} while (rangeIter.next());
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
Py_Return;
}
PyObject* SheetPy::clearAll(PyObject *args)
{
this->getSheetPtr()->clearAll();
Py_Return;
}
PyObject* SheetPy::importFile(PyObject *args)
{
const char * filename;
const char * delimiter = "\t";
const char * quoteChar = "\"";
const char * escapeChar = "\\";
if (!PyArg_ParseTuple(args, "s|sss:importFile", &filename, &delimiter, &quoteChar, &escapeChar))
return 0;
if (getSheetPtr()->importFromFile(filename, delimiter[0], quoteChar[0], escapeChar[0]))
return Py::new_reference_to( Py::Boolean(true) );
else
return Py::new_reference_to( Py::Boolean(false) );
}
PyObject* SheetPy::exportFile(PyObject *args)
{
const char * filename;
const char * delimiter = "\t";
const char * quoteChar = "\"";
const char * escapeChar = "\\";
if (!PyArg_ParseTuple(args, "s|sss:importFile", &filename, &delimiter, &quoteChar, &escapeChar))
return 0;
if (getSheetPtr()->exportToFile(filename, delimiter[0], quoteChar[0], escapeChar[0]))
return Py::new_reference_to( Py::Boolean(true) );
else
return Py::new_reference_to( Py::Boolean(false) );
}
PyObject* SheetPy::mergeCells(PyObject *args)
{
const char * range;
if (!PyArg_ParseTuple(args, "s:mergeCells", &range))
return 0;
getSheetPtr()->mergeCells(Range(range));
Py_Return;
}
PyObject* SheetPy::splitCell(PyObject *args)
{
const char * strAddress;
if (!PyArg_ParseTuple(args, "s:splitCell", &strAddress))
return 0;
CellAddress address;
try {
address = stringToAddress(strAddress);
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
getSheetPtr()->splitCell(address);
Py_Return;
}
PyObject* SheetPy::insertColumns(PyObject *args)
{
const char * column;
int count;
if (!PyArg_ParseTuple(args, "si:insertColumns", &column, &count))
return 0;
getSheetPtr()->insertColumns(decodeColumn(column), count);
Py_Return;
}
PyObject* SheetPy::removeColumns(PyObject *args)
{
const char * column;
int count;
if (!PyArg_ParseTuple(args, "si:removeColumns", &column, &count))
return 0;
getSheetPtr()->removeColumns(decodeColumn(column), count);
Py_Return;
}
PyObject* SheetPy::insertRows(PyObject *args)
{
const char * row;
int count;
if (!PyArg_ParseTuple(args, "si:insertRows", &row, &count))
return 0;
getSheetPtr()->insertRows(decodeRow(std::string(row)), count);
Py_Return;
}
PyObject* SheetPy::removeRows(PyObject *args)
{
const char * row;
int count;
if (!PyArg_ParseTuple(args, "si:removeRows", &row, &count))
return 0;
getSheetPtr()->removeRows(decodeRow(std::string(row)), count);
Py_Return;
}
PyObject* SheetPy::setStyle(PyObject *args)
{
const char * cell;
PyObject * value;
std::set<std::string> style;
const char * options = "replace";
if (!PyArg_ParseTuple(args, "sO|s:setStyle", &cell, &value, &options))
return 0;
if (PySet_Check(value)) {
PyObject * copy = PySet_New(value);
while (PySet_Size(copy) > 0) {
PyObject * item = PySet_Pop(copy);
// check on the key:
if (PyString_Check(item))
style.insert(PyString_AsString(item));
else {
std::string error = std::string("type of the set need to be a string, not ") + item->ob_type->tp_name;
PyErr_SetString(PyExc_TypeError, error.c_str());
Py_DECREF(copy);
return 0;
}
}
Py_DECREF(copy);
}
else if (PyString_Check(value)) {
using namespace boost;
escaped_list_separator<char> e('\0', '|', '\0');
std::string line = PyString_AsString(value);
tokenizer<escaped_list_separator<char> > tok(line, e);
for(tokenizer<escaped_list_separator<char> >::iterator i = tok.begin(); i != tok.end();++i)
style.insert(*i);
}
else {
std::string error = std::string("style must be either set or string, not ") + value->ob_type->tp_name;
PyErr_SetString(PyExc_TypeError, error.c_str());
return 0;
}
if (strcmp(options, "replace") == 0) {
Range rangeIter(cell);
do {
getSheetPtr()->setStyle(*rangeIter, style);
} while (rangeIter.next());
}
else if (strcmp(options, "add") == 0) {
Range rangeIter(cell);
do {
std::set<std::string> oldStyle;
const Cell * cell = getSheetPtr()->getCell(*rangeIter);
// Get old styles first
if (cell)
cell->getStyle(oldStyle);
for (std::set<std::string>::const_iterator it = oldStyle.begin(); it != oldStyle.end(); ++it)
style.insert(*it);
// Set new style
getSheetPtr()->setStyle(*rangeIter, style);
} while (rangeIter.next());
}
else if (strcmp(options, "remove") == 0) {
Range rangeIter(cell);
do {
std::set<std::string> oldStyle;
const Cell * cell = getSheetPtr()->getCell(*rangeIter);
// Get old styles first
if (cell)
cell->getStyle(oldStyle);
for (std::set<std::string>::const_iterator it = style.begin(); it != style.end(); ++it)
oldStyle.erase(*it);
// Set new style
getSheetPtr()->setStyle(*rangeIter, oldStyle);
} while (rangeIter.next());
}
else if (strcmp(options, "invert") == 0) {
Range rangeIter(cell);
do {
std::set<std::string> oldStyle;
std::set<std::string> newStyle;
const Cell * cell = getSheetPtr()->getCell(*rangeIter);
// Get old styles first
if (cell) {
cell->getStyle(oldStyle);
newStyle = oldStyle;
}
for (std::set<std::string>::const_iterator i = style.begin(); i != style.end(); ++i) {
if (oldStyle.find(*i) == oldStyle.end())
// Not found in oldstyle; add it to newStyle
newStyle.insert(*i);
else
// Found in oldStyle, remove it from newStyle
newStyle.erase(*i);
}
// Set new style
getSheetPtr()->setStyle(*rangeIter, newStyle);
} while (rangeIter.next());
}
else {
PyErr_SetString(PyExc_ValueError, "Optional parameter must be either 'replace', 'add', 'remove', or 'invert'");
return 0;
}
Py_Return;
}
PyObject* SheetPy::getStyle(PyObject *args)
{
const char * strAddress;
CellAddress address;
if (!PyArg_ParseTuple(args, "s:getStyle", &strAddress))
return 0;
try {
address = stringToAddress(strAddress);
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
std::set<std::string> style;
const Cell * cell = getSheetPtr()->getCell(address);
if (cell && cell->getStyle(style)) {
PyObject * s = PySet_New(NULL);
for (std::set<std::string>::const_iterator i = style.begin(); i != style.end(); ++i)
PySet_Add(s, PyString_FromString((*i).c_str()));
return s;
}
else {
Py_INCREF(Py_None);
return Py_None;
}
}
PyObject* SheetPy::setDisplayUnit(PyObject *args)
{
int row, col;
const char * cell;
const char * value;
if (!PyArg_ParseTuple(args, "ss:setDisplayUnit", &cell, &value))
return 0;
try {
Range rangeIter(cell);
do {
getSheetPtr()->setDisplayUnit(*rangeIter, value);
} while (rangeIter.next());
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
Py_Return;
}
PyObject* SheetPy::setAlias(PyObject *args)
{
CellAddress address;
const char * strAddress;
const char * value;
if (!PyArg_ParseTuple(args, "ss:setAlias", &strAddress, &value))
return 0;
try {
address = stringToAddress(strAddress);
getSheetPtr()->setAlias(address, value);
Py_Return;
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
}
PyObject* SheetPy::getDisplayUnit(PyObject *args)
{
const char * strAddress;
CellAddress address;
if (!PyArg_ParseTuple(args, "s:getDisplayUnit", &strAddress))
return 0;
try {
address = stringToAddress(strAddress);
Spreadsheet::DisplayUnit unit;
const Cell * cell = getSheetPtr()->getCell(address);
if ( cell && cell->getDisplayUnit(unit) )
return Py::new_reference_to( Py::String( unit.stringRep ) );
else
Py_Return;
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
}
PyObject* SheetPy::setAlignment(PyObject *args)
{
const char * cell;
PyObject * value;
int alignment = 0;
const char * options = "replace";
if (!PyArg_ParseTuple(args, "sO|s:setAlignment", &cell, &value, &options))
return 0;
if (PySet_Check(value)) {
// Argument is a set of strings
PyObject * copy = PySet_New(value);
int n = PySet_Size(copy);
while (n-- > 0) {
PyObject * item = PySet_Pop(copy);
if (PyString_Check(item))
alignment = Cell::decodeAlignment(PyString_AsString(item), alignment);
else {
std::string error = std::string("type of the key need to be a string, not") + item->ob_type->tp_name;
PyErr_SetString(PyExc_TypeError, error.c_str());
Py_DECREF(copy);
return 0;
}
}
Py_DECREF(copy);
}
else if (PyString_Check(value)) {
// Argument is a string, combination of alignments, separated by the pipe character
using namespace boost;
escaped_list_separator<char> e('\0', '|', '\0');
std::string line = PyString_AsString(value);
tokenizer<escaped_list_separator<char> > tok(line, e);
for(tokenizer<escaped_list_separator<char> >::iterator i = tok.begin(); i != tok.end();++i)
alignment = Cell::decodeAlignment(*i, alignment);
}
else {
std::string error = std::string("style must be either set or string, not ") + value->ob_type->tp_name;
PyErr_SetString(PyExc_TypeError, error.c_str());
return 0;
}
// Set alignment depending on 'options' variable
if (strcmp(options, "replace") == 0) {
Range rangeIter(cell);
do {
getSheetPtr()->setAlignment(*rangeIter, alignment);
} while (rangeIter.next());
}
else if (strcmp(options, "keep") == 0) {
Range rangeIter(cell);
do {
int oldAlignment = 0;
const Cell * cell = getSheetPtr()->getCell(*rangeIter);
if (cell)
cell->getAlignment(oldAlignment);
if (alignment & Cell::ALIGNMENT_VERTICAL)
oldAlignment &= ~Cell::ALIGNMENT_VERTICAL;
if (alignment & Cell::ALIGNMENT_HORIZONTAL)
oldAlignment &= ~Cell::ALIGNMENT_HORIZONTAL;
getSheetPtr()->setAlignment(*rangeIter, alignment | oldAlignment);
} while (rangeIter.next());
}
else {
PyErr_SetString(PyExc_ValueError, "Optional parameter must be either 'replace' or 'keep'");
return 0;
}
Py_Return;
}
PyObject* SheetPy::getAlignment(PyObject *args)
{
const char * strAddress;
CellAddress address;
if (!PyArg_ParseTuple(args, "s:getAlignment", &strAddress))
return 0;
try {
address = stringToAddress(strAddress);
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
int alignment;
const Cell * cell = getSheetPtr()->getCell(address);
if (cell && cell->getAlignment(alignment)) {
PyObject * s = PySet_New(NULL);
if (alignment & Cell::ALIGNMENT_LEFT)
PySet_Add(s, PyString_FromString("left"));
if (alignment & Cell::ALIGNMENT_HCENTER)
PySet_Add(s, PyString_FromString("center"));
if (alignment & Cell::ALIGNMENT_RIGHT)
PySet_Add(s, PyString_FromString("right"));
if (alignment & Cell::ALIGNMENT_TOP)
PySet_Add(s, PyString_FromString("top"));
if (alignment & Cell::ALIGNMENT_VCENTER)
PySet_Add(s, PyString_FromString("vcenter"));
if (alignment & Cell::ALIGNMENT_BOTTOM)
PySet_Add(s, PyString_FromString("bottom"));
return s;
}
else {
Py_INCREF(Py_None);
return Py_None;
}
}
static float decodeFloat(const PyObject * obj)
{
if (PyFloat_Check(obj))
return PyFloat_AsDouble((PyObject *)obj);
else if (PyInt_Check(obj))
return PyInt_AsLong((PyObject *)obj);
throw Base::TypeError("Float or integer expected");
}
static void decodeColor(PyObject * value, Color & c)
{
if (PyTuple_Check(value)) {
if (PyTuple_Size(value) < 3 || PyTuple_Size(value) > 4)
throw Base::TypeError("Tuple must be either of 3 or 4 floats/ints.");
c.r = decodeFloat(PyTuple_GetItem(value, 0));
c.g = decodeFloat(PyTuple_GetItem(value, 1));
c.b = decodeFloat(PyTuple_GetItem(value, 2));
if (PyTuple_Size(value) == 4) {
c.a = decodeFloat(PyTuple_GetItem(value, 3));
return;
}
else
c.a = 1.0;
}
else
throw Base::TypeError("Tuple required.");
}
PyObject* SheetPy::setForeground(PyObject *args)
{
try {
const char * range;
PyObject * value;
Color c;
if (!PyArg_ParseTuple(args, "sO:setForeground", &range, &value))
return 0;
decodeColor(value, c);
Range rangeIter(range);
do {
getSheetPtr()->setForeground(*rangeIter, c);
} while (rangeIter.next());
Py_Return;
}
catch (const Base::TypeError & e) {
PyErr_SetString(PyExc_TypeError, e.what());
return 0;
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
}
PyObject* SheetPy::getForeground(PyObject *args)
{
const char * strAddress;
CellAddress address;
if (!PyArg_ParseTuple(args, "s:getForeground", &strAddress))
return 0;
try {
address = stringToAddress(strAddress);
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
Color c;
const Cell * cell = getSheetPtr()->getCell(address);
if (cell && cell->getForeground(c)) {
PyObject * t = PyTuple_New(4);
PyTuple_SetItem(t, 0, Py::new_reference_to( Py::Float(c.r) ));
PyTuple_SetItem(t, 1, Py::new_reference_to( Py::Float(c.g) ));
PyTuple_SetItem(t, 2, Py::new_reference_to( Py::Float(c.b) ));
PyTuple_SetItem(t, 3, Py::new_reference_to( Py::Float(c.a) ));
return t;
}
else {
Py_INCREF(Py_None);
return Py_None;
}
}
PyObject* SheetPy::setBackground(PyObject *args)
{
try {
const char * strAddress;
PyObject * value;
Color c;
if (!PyArg_ParseTuple(args, "sO:setBackground", &strAddress, &value))
return 0;
decodeColor(value, c);
Range rangeIter(strAddress);
do {
getSheetPtr()->setBackground(*rangeIter, c);
} while (rangeIter.next());
Py_Return;
}
catch (const Base::TypeError & e) {
PyErr_SetString(PyExc_TypeError, e.what());
return 0;
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
}
PyObject* SheetPy::getBackground(PyObject *args)
{
const char * strAddress;
CellAddress address;
if (!PyArg_ParseTuple(args, "s:setStyle", &strAddress))
return 0;
try {
address = stringToAddress(strAddress);
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
Color c;
const Cell * cell = getSheetPtr()->getCell(address);
if (cell && cell->getBackground(c)) {
PyObject * t = PyTuple_New(4);
PyTuple_SetItem(t, 0, Py::new_reference_to( Py::Float(c.r) ));
PyTuple_SetItem(t, 1, Py::new_reference_to( Py::Float(c.g) ));
PyTuple_SetItem(t, 2, Py::new_reference_to( Py::Float(c.b) ));
PyTuple_SetItem(t, 3, Py::new_reference_to( Py::Float(c.a) ));
return t;
}
else {
Py_INCREF(Py_None);
return Py_None;
}
}
PyObject* SheetPy::setPosition(PyObject *args)
{
const char * strAddress;
CellAddress address;
if (!PyArg_ParseTuple(args, "s:setPosition", &strAddress))
return 0;
try {
address = stringToAddress(strAddress);
getSheetPtr()->setPosition(address);
Py_Return;
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
}
PyObject* SheetPy::setColumnWidth(PyObject *args)
{
const char * columnStr;
int width;
CellAddress address;
if (!PyArg_ParseTuple(args, "si:setColumnWidth", &columnStr, &width))
return 0;
try {
std::string cellAddr = std::string(columnStr) + "1";
address = stringToAddress(cellAddr.c_str());
getSheetPtr()->setColumnWidth(address.col(), width);
Py_Return;
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
}
PyObject* SheetPy::getColumnWidth(PyObject *args)
{
const char * columnStr;
if (!PyArg_ParseTuple(args, "s:getColumnWidth", &columnStr))
return 0;
try {
CellAddress address(std::string(columnStr) + "1");
return Py::new_reference_to( Py::Int( getSheetPtr()->getColumnWidth(address.col()) ) );
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
}
PyObject* SheetPy::setRowHeight(PyObject *args)
{
const char * rowStr;
int height;
if (!PyArg_ParseTuple(args, "si:setRowHeight", &rowStr, &height))
return 0;
try {
CellAddress address("A" + std::string(rowStr));
getSheetPtr()->setRowHeight(address.row(), height);
Py_Return;
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
}
PyObject* SheetPy::getRowHeight(PyObject *args)
{
const char * rowStr;
int row, col;
if (!PyArg_ParseTuple(args, "s:getRowHeight", &rowStr))
return 0;
try {
CellAddress address("A" + std::string(rowStr));
return Py::new_reference_to( Py::Int( getSheetPtr()->getRowHeight(address.row()) ) );
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
}
// +++ custom attributes implementer ++++++++++++++++++++++++++++++++++++++++
PyObject *SheetPy::getCustomAttributes(const char* attr) const
{
App::Property * prop = this->getSheetPtr()->getPropertyByName(attr);
if (prop == 0) {
PyErr_SetString(PyExc_ValueError, "Invalid address or property.");
return 0;
}
return prop->getPyObject();
}
int SheetPy::setCustomAttributes(const char* attr, PyObject* obj)
{
// Parse attr; if it looks like a cell address specifier, it probably is...
char *contents;
if (!PyArg_ParseTuple(obj, "s:setCustomAttributes", &contents))
return 0;
try {
CellAddress address(attr);
getSheetPtr()->setCell(address, contents);
return 0;
}
catch (const Base::Exception & e) {
PyErr_SetString(PyExc_ValueError, e.what());
return 0;
}
}

View File

@@ -0,0 +1,344 @@
/***************************************************************************
* 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"
#ifndef _PreComp_
#endif
#include "Utils.h"
#include <sstream>
#include <stdlib.h>
#include <boost/regex.hpp>
#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.
*
* @param col Column given as a 0-based column position.
*
* @returns String with column position, with "A" being the first column, "B" being the second and so on.
*
*/
std::string Spreadsheet::columnName(int col)
{
std::stringstream s;
if (col < 26)
s << ((char)('A' + col));
else
s << ((char)('A' + (col - 26) / 26 )) << ((char)('A' + (col - 26) % 26));
return s.str();
}
/**
* Encode \a row as a string.
*
* @param row Row given as a 0-based row position.
*
* @returns String with row position, with "1" being the first row.
*
*/
std::string Spreadsheet::rowName(int row)
{
std::stringstream s;
s << (row + 1);
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)
{
char * end;
int i = strtol(rowstr.c_str(), &end, 10);
if (i <0 || i >= CellAddress::MAX_ROWS || *end)
throw Base::Exception("Invalid row specification.");
return i - 1;
}
/**
* 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 = 0;
if (colstr.length() == 1) {
if ((colstr[0] >= 'A' && colstr[0] <= 'Z'))
col = colstr[0] - 'A';
else
col = colstr[0] - 'a';
}
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 if ((*i >= 'a' && *i <= 'z'))
v = *i - 'a';
else
throw Base::Exception("Invalid column specification");
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)
{
int i = 0;
static const boost::regex e("\\${0,1}([A-Za-z]+)\\${0,1}([0-9]+)");
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.");
}
/**
* Convert given \a row and \a col into a string address.
*
* @param row Row address.
* @param col Column address.
*
* @returns Address given as a string.
*/
std::string Spreadsheet::addressToString(const CellAddress &address)
{
std::stringstream s;
if (address.col() < 26)
s << (char)('A' + address.col());
else {
int col = address.col() - 26;
s << (char)('A' + (col / 26));
s << (char)('A' + (col % 26));
}
s << (address.row() + 1);
return s.str();
}
void Spreadsheet::createRectangles(std::set<std::pair<int, int> > & cells, std::map<std::pair<int, int>, std::pair<int, int> > & rectangles)
{
while (cells.size() != 0) {
int row, col;
int orgRow;
int rows = 1;
int cols = 1;
orgRow = row = (*cells.begin()).first;
col = (*cells.begin()).second;
// Expand right first
while (cells.find(std::make_pair(row, col + cols)) != cells.end())
++cols;
// Expand left
while (cells.find(std::make_pair(row, col + cols)) != cells.end()) {
col--;
++cols;
}
// Try to expand cell up (the complete row above from [col,col + cols> needs to be in the cells variable)
bool ok = true;
while (ok) {
for (int i = col; i < col + cols; ++i) {
if ( cells.find(std::make_pair(row - 1, i)) == cells.end()) {
ok = false;
break;
}
}
if (ok) {
// Complete row
row--;
rows++;
}
else
break;
}
// Try to expand down (the complete row below from [col,col + cols> needs to be in the cells variable)
ok = true;
while (ok) {
for (int i = col; i < col + cols; ++i) {
if ( cells.find(std::make_pair(orgRow + 1, i)) == cells.end()) {
ok = false;
break;
}
}
if (ok) {
// Complete row
orgRow++;
rows++;
}
else
break;
}
// Remove entries from cell set for this rectangle
for (int r = row; r < row + rows; ++r)
for (int c = col; c < col + cols; ++c)
cells.erase(std::make_pair(r, c));
// Insert into output variable
rectangles[std::make_pair(row, col)] = std::make_pair(rows, cols);
}
}
std::string Spreadsheet::quote(const std::string &input)
{
std::stringstream output;
std::string::const_iterator cur = input.begin();
std::string::const_iterator end = input.end();
output << "<<";
while (cur != end) {
switch (*cur) {
case '\t':
output << "\\t";
break;
case '\n':
output << "\\n";
break;
case '\r':
output << "\\r";
break;
case '\\':
output << "\\\\";
break;
case '\'':
output << "\\'";
break;
case '"':
output << "\\\"";
break;
case '>':
output << "\\>";
break;
default:
output << *cur;
}
++cur;
}
output << ">>";
return output.str();
}
std::string Spreadsheet::unquote(const std::string & input)
{
assert(input.size() >= 4);
std::string output;
std::string::const_iterator cur = input.begin() + 2;
std::string::const_iterator end = input.end() - 2;
output.reserve(input.size());
bool escaped = false;
while (cur != end) {
if (escaped) {
switch (*cur) {
case 't':
output += '\t';
break;
case 'n':
output += '\n';
break;
case 'r':
output += '\r';
break;
case '\\':
output += '\\';
break;
case '\'':
output += '\'';
break;
case '"':
output += '"';
break;
}
escaped = false;
}
else {
if (*cur == '\\')
escaped = true;
else
output += *cur;
}
++cur;
}
return output;
}

View File

@@ -0,0 +1,92 @@
/***************************************************************************
* 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 UTILS_H
#define UTILS_H
#include <string>
#include <map>
#include <set>
#include <memory>
#include <Base/BaseClass.h>
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);
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);
SpreadsheetExport std::string addressToString(const CellAddress & address);
struct CellAddress {
CellAddress(unsigned int _value) : value(_value) { }
CellAddress(int row = -1, int col = -1) : value(((row & 0xffff) << 16) | (col & 0xffff)) { }
CellAddress(const char * address) {
*this = stringToAddress(address);
}
CellAddress(const std::string & address) {
*this = stringToAddress(address.c_str());
}
inline int row() const { return (value >> 16) & 0xffff; }
inline int col() const { return value & 0xffff; }
inline bool operator<(const CellAddress & other) const { return value < other.value; }
inline bool operator==(const CellAddress & other) const { return value == other.value; }
inline bool operator!=(const CellAddress & other) const { return value != other.value; }
inline bool isValid() { return (row() >=0 && row() < MAX_ROWS && col() >= 0 && col() < MAX_COLUMNS); }
// Static members
static const int MAX_ROWS;
static const int MAX_COLUMNS;
protected:
unsigned int value;
};
template<typename T> T * freecad_dynamic_cast(Base::BaseClass * t)
{
if (t && t->isDerivedFrom(T::getClassTypeId()))
return static_cast<T*>(t);
else
return 0;
}
}
#endif // UTILS_H

View File

@@ -0,0 +1,21 @@
#!/bin/sh
# DerivedGeneralCategory.txt used below can be downloaded from
# http://www.unicode.org/Public/UNIDATA/extracted/DerivedGeneralCategory.txt
exec 2>/dev/null
export PATH=../../../../build/src/Mod/Spreadsheet/App:$PATH
for l in Cc Cf Cn Co Cs Ll Lm Lo Lt Lu Mc Me Mn Nd Nl No Pc Pd Pe Pf Pi Po Ps Sc Sk Sm So Zl Zp Zs ; do
grep "; $l" DerivedGeneralCategory.txt > $l.txt
genregexps $l $l.txt
done
genregexps L Ll.txt Lm.txt Lo.txt Lt.txt Lu.txt
genregexps C Cc.txt Cf.txt Cn.txt Co.txt Cs.txt
genregexps M Mc.txt Me.txt Mn.txt
genregexps N Nd.txt Nl.txt No.txt
genregexps P Pc.txt Pd.txt Pe.txt Pf.txt Pi.txt Po.txt Ps.txt
genregexps S Sc.txt Sk.txt Sm.txt So.txt
genregexps Z Zl.txt Zp.txt Zs.txt

View File

@@ -0,0 +1,232 @@
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
int genUtf8(int c, unsigned char * b)
{
if (c<0x80) { *b++=c, *b++ = '\0'; return 1; }
else if (c<0x800) { *b++=192+c/64, *b++=128+c%64, *b++ = '\0'; return 2; }
else if (c-0xd800u < 0x800) goto error;
else if (c<0x10000) { *b++=224+c/4096, *b++=128+c/64%64, *b++=128+c%64, *b++ = '\0'; return 3; }
else if (c<0x110000) { *b++=240+c/262144, *b++=128+c/4096%64, *b++=128+c/64%64, *b++=128+c%64, *b++ = '\0'; return 4; }
else goto error;
error:
// printf("Error! %x\n", c);
// exit(1);
return -1;
}
typedef std::basic_string<unsigned char> String;
typedef std::vector<String > StringList;
StringList list;
unsigned char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
static String escape(unsigned char c)
{
switch (c) {
case '*':
case '+':
case '-':
case '(':
case ')':
case '\\':
case '.':
case '[':
case ']':
case '?':
case '{':
case '}':
case '#':
case '^':
case '|':
case ':':
case '$':
case '/':
case '\'':
case '"':
return String((const unsigned char*)"\\") + c;
default:
return String((const unsigned char*)"") + c;
}
}
static String encode(unsigned char c)
{
if (c <= 32 || c > 126)
return String((const unsigned char*)"\\x") + hex[c >> 4] + hex[c & 0xf];
else {
return String((const unsigned char*)"") + c;
}
}
static String encodeString(String c)
{
int i;
String result;
for (i = 0; i < c.size(); ++i)
result += encode(c[i]);
return result;
}
static String encodeRange(String r)
{
String result;
int i, j;
for (i = 0; i < r.size(); ++i) {
int n = 0;
for (j = i; j < r.size() && r[i] + n == r[j]; ++j, ++n);
if (n > 1) {
result += escape(r[i]);
result += (const unsigned char*)"-";
result += escape(r[j - 1]);
i = j - 1;
}
else
result += escape(r[i]);
}
return result;
}
static String commonPrefix(int indent, StringList::const_iterator S, StringList::const_iterator E, int k)
{
StringList::const_iterator i = S;
String leafs;
String branches;
int nBranches = 0;
bool first = true;
if (S->size() <= k)
return String((const unsigned char*)"");
while (i != E) {
StringList::const_iterator start = i;
StringList::const_iterator end = i;
int n = 0;
if (i->size() == k + 1) {
leafs += i->at(k);
++i;
}
else {
/* Common path */
while (end != E &&
end->size() >= start->size() &&
end->at(k) == start->at(k)) {
++n;
++end;
}
//if (leafs.size() > 0)
if (!first)
branches += (const unsigned char*)"|";
branches += escape(start->at(k)) + commonPrefix(indent + 1, start, end, k + 1);
first = false;
nBranches++;
i = end;
}
}
if (leafs.size() > 1)
leafs = (const unsigned char*)"[" + encodeRange(leafs) + (const unsigned char*)"]";
if (nBranches == 0)
return leafs;
else {
if (leafs.size() > 0)
leafs += (const unsigned char*)"|";
return (const unsigned char*)"(" + leafs + branches + (const unsigned char*)")";
}
}
static void readFile(FILE * f)
{
while (!feof(f)) {
char line[2048];
int start;
int end;
char cat[128];
unsigned char out[8];
int i;
if (fgets(line, sizeof(line), f) == NULL)
break;
if (sscanf(line, "%4X..%4X ; %s", &start, &end, cat) == 3) {
for (i = start; i <= end; ++i) {
int n = genUtf8(i, out);
if (n > 0) {
list.push_back(String(out, n));
fprintf(stderr, "%6X %d %s\n", i, n, out);
}
}
}
else if (sscanf(line, "%X ; %s", &start, cat) == 2) {
int n = genUtf8(start, out);
if (n > 0) {
list.push_back(String(out, n));
fprintf(stderr, "%6X %d %s\n", start, n, out);
}
}
}
}
static String subdivide(String prefix, StringList::const_iterator S, StringList::const_iterator E, StringList & result)
{
String regexp = commonPrefix(0, S, E, 0);
regexp = encodeString(regexp);
if (regexp.size() < 2000) {
return regexp;
}
else {
int n = E - S;
StringList::const_iterator M = S + n / 2;
result.push_back( prefix + (const unsigned char*)"1\t" + subdivide(prefix + (const unsigned char*)"1", S, M, result) + (const unsigned char*)"\n");
result.push_back( prefix + (const unsigned char*)"2\t" + subdivide(prefix + (const unsigned char*)"2", M, E, result) + (const unsigned char*)"\n");
return (const unsigned char*)"({" + prefix + (const unsigned char*)"1}|" +
(const unsigned char*)"{" + prefix + (const unsigned char*)"2})";
}
}
int main(int argc, char * argv[])
{
for (int i = 2; i < argc; ++i) {
FILE * f = fopen(argv[i], "r");
if (f == NULL) {
perror("fopen");
return 1;
}
readFile(f);
fclose(f);
}
sort(list.begin(), list.end());
StringList result;
String regexp = subdivide((const unsigned char*)argv[1], list.begin(), list.end(), result);
for (StringList::const_iterator i = result.begin(); i != result.end(); ++i)
printf("%s", i->c_str());
printf("%s\t%s\n", argv[1], regexp.c_str());
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,9 @@
PYSIDE_WRAP_RC(Spreadsheet_QRC_SRCS Resources/Spreadsheet.qrc)
SET(Spreadsheet_SRCS
Init.py
InitGui.py
Spreadsheet.py
)
SOURCE_GROUP("" FILES ${Spreadsheet_SRCS})
SET(all_files ${Spreadsheet_SRCS})
ADD_CUSTOM_TARGET(Spreadsheet ALL
SOURCES ${all_files} ${Spreadsheet_QRC_SRCS}
)
fc_copy_sources(Spreadsheet "${CMAKE_BINARY_DIR}/Mod/Spreadsheet" ${all_files})
add_subdirectory(App)
if(BUILD_GUI)
add_subdirectory(Gui)
endif(BUILD_GUI)
fc_target_copy_resource(Spreadsheet
${CMAKE_CURRENT_BINARY_DIR}
@@ -21,6 +11,9 @@ fc_target_copy_resource(Spreadsheet
Spreadsheet_rc.py)
INSTALL(
FILES ${Spreadsheet_SRCS} ${Spreadsheet_QRC_SRCS}
DESTINATION Mod/Spreadsheet
FILES
Init.py
InitGui.py
DESTINATION
Mod/Spreadsheet
)

View File

@@ -0,0 +1,64 @@
/***************************************************************************
* *
* This program 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. *
* for detail see the LICENCE text file. *
* Jrgen Riegel 2002 *
* Eivind Kvedalen 2015 *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Python.h>
#endif
#include <Base/Console.h>
#include <Gui/Application.h>
#include <Gui/Language/Translator.h>
#include "Workbench.h"
#include "ViewProviderSpreadsheet.h"
#include "SpreadsheetView.h"
#include "qrc_Spreadsheet.cxx"
// use a different name to CreateCommand()
void CreateSpreadsheetCommands(void);
void loadSpreadsheetResource()
{
// add resources and reloads the translators
Q_INIT_RESOURCE(Spreadsheet);
Gui::Translator::instance()->refresh();
}
/* registration table */
extern struct PyMethodDef SpreadsheetGui_Import_methods[];
/* Python entry */
extern "C" {
void SpreadsheetGuiExport initSpreadsheetGui()
{
if (!Gui::Application::Instance) {
PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application.");
return;
}
(void) Py_InitModule("SpreadsheetGui", SpreadsheetGui_Import_methods); /* mod name, table ptr */
Base::Console().Log("Loading GUI of Spreadsheet module... done\n");
// instantiating the commands
CreateSpreadsheetCommands();
SpreadsheetGui::ViewProviderSheet::init();
SpreadsheetGui::Workbench::init();
// SpreadsheetGui::SheetView::init();
// add resources and reloads the translators
loadSpreadsheetResource();
}
} // extern "C" {

View File

@@ -0,0 +1,71 @@
/***************************************************************************
* Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) *
* Copyright (c) 2006 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* 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"
#ifndef _PreComp_
# include <QIcon>
# include <QImage>
# include <QFileInfo>
#endif
#include "SpreadsheetView.h"
#include <Mod/Spreadsheet/App/Sheet.h>
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/FileInfo.h>
#include <App/Application.h>
#include <Gui/MainWindow.h>
#include <Gui/Document.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
using namespace SpreadsheetGui;
using namespace Spreadsheet;
/* module functions */
static PyObject *
open(PyObject *self, PyObject *args)
{
const char* Name;
const char* DocName=0;
if (!PyArg_ParseTuple(args, "s|s",&Name,&DocName))
return NULL;
PY_TRY {
Base::FileInfo file(Name);
App::Document *pcDoc = App::GetApplication().newDocument(DocName ? DocName : QT_TR_NOOP("Unnamed"));
Sheet *pcSheet = (Sheet *)pcDoc->addObject("Spreadsheet::Sheet", file.fileNamePure().c_str());
pcSheet->importFromFile(Name, '\t', '"', '\\');
pcSheet->execute();
} PY_CATCH;
Py_Return;
}
/* registration table */
struct PyMethodDef SpreadsheetGui_Import_methods[] = {
{"open" ,open , 1}, /* method name, C func ptr, always-tuple */
{NULL, NULL} /* end of table marker */
};

View File

@@ -0,0 +1,91 @@
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${Boost_INCLUDE_DIRS}
${COIN3D_INCLUDE_DIR}
${QT_INCLUDE_DIR}
${ZLIB_INCLUDE_DIR}
${SOQT_INCLUDE_DIR}
${PYTHON_INCLUDE_PATH}
${XERCESC_INCLUDE_DIR}
)
set(SpreadsheetGui_LIBS
Spreadsheet
FreeCADGui
)
set(SpreadsheetGui_MOC_HDRS
SpreadsheetView.h
SheetModel.h
SheetTableView.h
SpreadsheetDelegate.h
Workbench.h
PropertiesDialog.h
qtcolorpicker.h
)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/moc_qtcolorpicker-internal.cpp
COMMAND ${QT_MOC_EXECUTABLE} -o ${CMAKE_CURRENT_BINARY_DIR}/moc_qtcolorpicker-internal.cpp ${CMAKE_CURRENT_SOURCE_DIR}/qtcolorpicker.cpp
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/qtcolorpicker.cpp)
set_property(SOURCE qtcolorpicker.cpp APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/moc_qtcolorpicker-internal.cpp)
fc_wrap_cpp(SpreadsheetGui_MOC_SRCS ${SpreadsheetGui_MOC_HDRS})
SOURCE_GROUP("Moc" FILES ${SpreadsheetGui_MOC_SRCS})
SET(SpreadsheetGui_RES_SRCS
Resources/Spreadsheet.qrc
)
#fc_add_resources(SpreadsheetGui_QRC_SRCS ${SpreadsheetGui_RES_SRCS})
qt4_add_resources(SpreadsheetGui_QRC_SRCS ${SpreadsheetGui_RES_SRCS})
set(SpreadsheetGui_UIC_SRCS
Sheet.ui
PropertiesDialog.ui
)
qt4_wrap_ui(SpreadsheetGui_UIC_HDRS ${SpreadsheetGui_UIC_SRCS})
SET(SpreadsheetGui_SRCS
# ${SpreadsheetGui_MOC_SRCS}
# ${SpreadsheetGui_QRC_SRCS}
AppSpreadsheetGui.cpp
AppSpreadsheetGuiPy.cpp
Command.cpp
ViewProviderSpreadsheet.cpp
ViewProviderSpreadsheet.h
Resources/Spreadsheet.qrc
SpreadsheetView.cpp
SpreadsheetView.h
SpreadsheetDelegate.h
SpreadsheetDelegate.cpp
SheetTableView.cpp
SheetTableView.h
SheetModel.h
SheetModel.cpp
PreCompiled.cpp
PreCompiled.h
Workbench.cpp
Workbench.h
qtcolorpicker.h
qtcolorpicker.cpp
PropertiesDialog.h
PropertiesDialog.cpp
${SpreadsheetGui_UIC_HDRS}
)
add_library(SpreadsheetGui SHARED ${SpreadsheetGui_SRCS})
target_link_libraries(SpreadsheetGui ${SpreadsheetGui_LIBS})
fc_target_copy_resource(SpreadsheetGui
${CMAKE_SOURCE_DIR}/src/Mod/Spreadsheet
${CMAKE_BINARY_DIR}/Mod/Spreadsheet
InitGui.py)
SET_BIN_DIR(SpreadsheetGui SpreadsheetGui /Mod/Spreadsheet)
SET_PYTHON_PREFIX_SUFFIX(SpreadsheetGui)
INSTALL(TARGETS SpreadsheetGui DESTINATION ${CMAKE_INSTALL_LIBDIR})

View File

@@ -0,0 +1,812 @@
/***************************************************************************
* *
* This program 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. *
* for detail see the LICENCE text file. *
* Jürgen Riegel 2002 *
* Eivind Kvedalen 2015 *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <QAction>
# include <QFileDialog>
# include <QImage>
# include <QImageReader>
# include <QMessageBox>
# include <QTextStream>
#endif
#include <time.h>
#include <sys/timeb.h>
#include <Base/Exception.h>
#include <Base/Interpreter.h>
#include <App/Document.h>
#include <Gui/Application.h>
#include <Gui/MainWindow.h>
#include <Gui/Command.h>
#include <Gui/Document.h>
#include <Gui/ViewProvider.h>
#include <Gui/BitmapFactory.h>
# include <Gui/FileDialog.h>
#include "SpreadsheetView.h"
#include "../App/Sheet.h"
#include "../App/Range.h"
#include "ViewProviderSpreadsheet.h"
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
using namespace SpreadsheetGui;
using namespace Spreadsheet;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetMergeCells);
CmdSpreadsheetMergeCells::CmdSpreadsheetMergeCells()
: Command("Spreadsheet_MergeCells")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Merge cells");
sToolTipText = QT_TR_NOOP("Merge selected cells in spreadsheet");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetMergeCells";
}
void CmdSpreadsheetMergeCells::activated(int iMsg)
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
std::vector<Range> ranges = sheetView->selectedRanges();
// Execute mergeCells commands
if (ranges.size() > 0) {
Gui::Command::openCommand("Merge cells");
std::vector<Range>::const_iterator i = ranges.begin();
for (; i != ranges.end(); ++i)
if (i->size() > 1)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.mergeCells('%s')", sheet->getNameInDocument(),
i->rangeString().c_str());
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.%s.setPosition('%s')", sheet->getNameInDocument(),
ranges[0].address().c_str());
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
bool CmdSpreadsheetMergeCells::isActive()
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
if (activeWindow && freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow))
return true;
}
return false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetSplitCell);
CmdSpreadsheetSplitCell::CmdSpreadsheetSplitCell()
: Command("Spreadsheet_SplitCell")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Split cell");
sToolTipText = QT_TR_NOOP("Split previously merged cells in spreadsheet");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetSplitCell";
}
void CmdSpreadsheetSplitCell::activated(int iMsg)
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
QModelIndex current = sheetView->currentIndex();
if (current.isValid()) {
std::string address = addressToString(CellAddress(current.row(), current.column()));
Gui::Command::openCommand("Split cell");
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.splitCell('%s')", sheet->getNameInDocument(),
address.c_str());
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
bool CmdSpreadsheetSplitCell::isActive()
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
QModelIndex current = sheetView->currentIndex();
Sheet * sheet = sheetView->getSheet();
if (current.isValid())
return sheet->isMergedCell(CellAddress(current.row(), current.column()));
}
}
return false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetImport);
CmdSpreadsheetImport::CmdSpreadsheetImport()
: Command("Spreadsheet_Import")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Import spreadsheet");
sToolTipText = QT_TR_NOOP("Import CSV file into spreadsheet");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetImport";
}
void CmdSpreadsheetImport::activated(int iMsg)
{
QString selectedFilter;
QString formatList = QObject::tr("All (*)");
QString fileName = Gui::FileDialog::getOpenFileName(Gui::getMainWindow(),
QObject::tr("Import file"),
QString(),
formatList,
&selectedFilter);
if (!fileName.isEmpty()) {
std::string FeatName = getUniqueObjectName("Spreadsheet");
Sheet * sheet = freecad_dynamic_cast<Sheet>(App::GetApplication().getActiveDocument()->addObject("Spreadsheet::Sheet", FeatName.c_str()));
sheet->importFromFile(fileName.toStdString(), '\t', '"', '\\');
sheet->execute();
}
}
bool CmdSpreadsheetImport::isActive()
{
return getActiveGuiDocument() ? true : false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetExport);
CmdSpreadsheetExport::CmdSpreadsheetExport()
: Command("Spreadsheet_Export")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Export spreadsheet");
sToolTipText = QT_TR_NOOP("Export spreadsheet to CSV file");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetExport";
}
void CmdSpreadsheetExport::activated(int iMsg)
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
QString selectedFilter;
QString formatList = QObject::tr("All (*)");
QString fileName = Gui::FileDialog::getSaveFileName(Gui::getMainWindow(),
QObject::tr("Export file"),
QString(),
formatList,
&selectedFilter);
if (!fileName.isEmpty())
sheet->exportToFile(fileName.toStdString(), '\t', '"', '\\');
}
}
}
bool CmdSpreadsheetExport::isActive()
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
if (activeWindow && freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow))
return true;
}
return false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetAlignLeft);
CmdSpreadsheetAlignLeft::CmdSpreadsheetAlignLeft()
: Command("Spreadsheet_AlignLeft")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Align left");
sToolTipText = QT_TR_NOOP("Left-align contents of selected cells");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetAlignLeft";
}
void CmdSpreadsheetAlignLeft::activated(int iMsg)
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
std::vector<Range> ranges = sheetView->selectedRanges();
if (ranges.size() > 0) {
std::vector<Range>::const_iterator i = ranges.begin();
Gui::Command::openCommand("Left-align cell");
for (; i != ranges.end(); ++i)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', 'left', 'keep')", sheet->getNameInDocument(),
i->rangeString().c_str());
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
bool CmdSpreadsheetAlignLeft::isActive()
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
if (activeWindow && freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow))
return true;
}
return false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetAlignCenter);
CmdSpreadsheetAlignCenter::CmdSpreadsheetAlignCenter()
: Command("Spreadsheet_AlignCenter")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Align center");
sToolTipText = QT_TR_NOOP("Center-align contents of selected cells");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetAlignCenter";
}
void CmdSpreadsheetAlignCenter::activated(int iMsg)
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
std::vector<Range> ranges = sheetView->selectedRanges();
if (ranges.size() > 0) {
std::vector<Range>::const_iterator i = ranges.begin();
Gui::Command::openCommand("Center cell");
for (; i != ranges.end(); ++i)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', 'center', 'keep')", sheet->getNameInDocument(),
i->rangeString().c_str());
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
bool CmdSpreadsheetAlignCenter::isActive()
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
if (activeWindow && freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow))
return true;
}
return false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetAlignRight);
CmdSpreadsheetAlignRight::CmdSpreadsheetAlignRight()
: Command("Spreadsheet_AlignRight")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Align right");
sToolTipText = QT_TR_NOOP("Right-align contents of selected cells");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetAlignRight";
}
void CmdSpreadsheetAlignRight::activated(int iMsg)
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
std::vector<Range> ranges = sheetView->selectedRanges();
if (ranges.size() > 0) {
std::vector<Range>::const_iterator i = ranges.begin();
Gui::Command::openCommand("Right-align cell");
for (; i != ranges.end(); ++i)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', 'right', 'keep')", sheet->getNameInDocument(),
i->rangeString().c_str());
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
bool CmdSpreadsheetAlignRight::isActive()
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
if (activeWindow && freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow))
return true;
}
return false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetAlignTop);
CmdSpreadsheetAlignTop::CmdSpreadsheetAlignTop()
: Command("Spreadsheet_AlignTop")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Align top");
sToolTipText = QT_TR_NOOP("Top-align contents of selected cells");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetAlignTop";
}
void CmdSpreadsheetAlignTop::activated(int iMsg)
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
std::vector<Range> ranges = sheetView->selectedRanges();
if (ranges.size() > 0) {
std::vector<Range>::const_iterator i = ranges.begin();
Gui::Command::openCommand("Top-align cell");
for (; i != ranges.end(); ++i)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', 'top', 'keep')", sheet->getNameInDocument(),
i->rangeString().c_str());
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
bool CmdSpreadsheetAlignTop::isActive()
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
if (activeWindow && freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow))
return true;
}
return false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetAlignBottom);
CmdSpreadsheetAlignBottom::CmdSpreadsheetAlignBottom()
: Command("Spreadsheet_AlignBottom")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Align bottom");
sToolTipText = QT_TR_NOOP("Bottom-align contents of selected cells");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetAlignBottom";
}
void CmdSpreadsheetAlignBottom::activated(int iMsg)
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
std::vector<Range> ranges = sheetView->selectedRanges();
if (ranges.size() > 0) {
std::vector<Range>::const_iterator i = ranges.begin();
Gui::Command::openCommand("Bottom-align cell");
for (; i != ranges.end(); ++i)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', 'bottom', 'keep')", sheet->getNameInDocument(),
i->rangeString().c_str());
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
bool CmdSpreadsheetAlignBottom::isActive()
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
if (activeWindow && freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow))
return true;
}
return false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetAlignVCenter);
CmdSpreadsheetAlignVCenter::CmdSpreadsheetAlignVCenter()
: Command("Spreadsheet_AlignVCenter")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Vertically center-align");
sToolTipText = QT_TR_NOOP("Center-align contents vertically of selected cells");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetAlignVCenter";
}
void CmdSpreadsheetAlignVCenter::activated(int iMsg)
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
std::vector<Range> ranges = sheetView->selectedRanges();
if (ranges.size() > 0) {
std::vector<Range>::const_iterator i = ranges.begin();
Gui::Command::openCommand("Vertically center cells");
for (; i != ranges.end(); ++i)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', 'vcenter', 'keep')", sheet->getNameInDocument(),
i->rangeString().c_str());
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
bool CmdSpreadsheetAlignVCenter::isActive()
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
if (activeWindow && freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow))
return true;
}
return false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetStyleBold);
CmdSpreadsheetStyleBold::CmdSpreadsheetStyleBold()
: Command("Spreadsheet_StyleBold")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Bold text");
sToolTipText = QT_TR_NOOP("Set bold text in selected cells");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetStyleBold";
}
void CmdSpreadsheetStyleBold::activated(int iMsg)
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
QModelIndexList selection = sheetView->selectedIndexes();
if (selection.size() > 0) {
bool allBold = true;
for (QModelIndexList::const_iterator it = selection.begin(); it != selection.end(); ++it) {
std::set<std::string> style;
sheet->getCell(CellAddress((*it).row(), (*it).column()))->getStyle(style);
if (style.find("bold") == style.end()) {
allBold = false;
break;
}
}
std::vector<Range> ranges = sheetView->selectedRanges();
std::vector<Range>::const_iterator i = ranges.begin();
Gui::Command::openCommand("Set bold text");
for (; i != ranges.end(); ++i) {
if (!allBold)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', 'bold', 'add')", sheet->getNameInDocument(),
i->rangeString().c_str());
else
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', 'bold', 'remove')", sheet->getNameInDocument(),
i->rangeString().c_str());
}
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
bool CmdSpreadsheetStyleBold::isActive()
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
if (activeWindow && freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow))
return true;
}
return false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetStyleItalic);
CmdSpreadsheetStyleItalic::CmdSpreadsheetStyleItalic()
: Command("Spreadsheet_StyleItalic")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Italic text");
sToolTipText = QT_TR_NOOP("Set italic text in selected cells");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetStyleItalic";
}
void CmdSpreadsheetStyleItalic::activated(int iMsg)
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
QModelIndexList selection = sheetView->selectedIndexes();
if (selection.size() > 0) {
bool allItalic = true;
for (QModelIndexList::const_iterator it = selection.begin(); it != selection.end(); ++it) {
std::set<std::string> style;
sheet->getCell(CellAddress((*it).row(), (*it).column()))->getStyle(style);
if (style.find("italic") == style.end()) {
allItalic = false;
break;
}
}
std::vector<Range> ranges = sheetView->selectedRanges();
std::vector<Range>::const_iterator i = ranges.begin();
Gui::Command::openCommand("Set italic text");
for (; i != ranges.end(); ++i) {
if (!allItalic)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', 'italic', 'add')", sheet->getNameInDocument(),
i->rangeString().c_str());
else
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', 'italic', 'remove')", sheet->getNameInDocument(),
i->rangeString().c_str());
}
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
bool CmdSpreadsheetStyleItalic::isActive()
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
if (activeWindow && freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow))
return true;
}
return false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdSpreadsheetStyleUnderline);
CmdSpreadsheetStyleUnderline::CmdSpreadsheetStyleUnderline()
: Command("Spreadsheet_StyleUnderline")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Underline text");
sToolTipText = QT_TR_NOOP("Set underline text in selected cells");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "SpreadsheetStyleUnderline";
}
void CmdSpreadsheetStyleUnderline::activated(int iMsg)
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
QModelIndexList selection = sheetView->selectedIndexes();
if (selection.size() > 0) {
bool allUnderline = true;
for (QModelIndexList::const_iterator it = selection.begin(); it != selection.end(); ++it) {
std::set<std::string> style;
sheet->getCell(CellAddress((*it).row(), (*it).column()))->getStyle(style);
if (style.find("underline") == style.end()) {
allUnderline = false;
break;
}
}
std::vector<Range> ranges = sheetView->selectedRanges();
std::vector<Range>::const_iterator i = ranges.begin();
Gui::Command::openCommand("Set underline text");
for (; i != ranges.end(); ++i) {
if (!allUnderline)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', 'underline', 'add')", sheet->getNameInDocument(),
i->rangeString().c_str());
else
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', 'underline', 'remove')", sheet->getNameInDocument(),
i->rangeString().c_str());
}
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
bool CmdSpreadsheetStyleUnderline::isActive()
{
if (getActiveGuiDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
if (activeWindow && freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow))
return true;
}
return false;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DEF_STD_CMD_A(CmdCreateSpreadsheet);
CmdCreateSpreadsheet::CmdCreateSpreadsheet()
:Command("Spreadsheet_CreateSheet")
{
sAppModule = "Spreadsheet";
sGroup = QT_TR_NOOP("Spreadsheet");
sMenuText = QT_TR_NOOP("Create spreadsheet");
sToolTipText = QT_TR_NOOP("Create a new spreadsheet");
sWhatsThis = sToolTipText;
sStatusTip = sToolTipText;
sPixmap = "Spreadsheet";
}
void CmdCreateSpreadsheet::activated(int iMsg)
{
std::string FeatName = getUniqueObjectName("Spreadsheet");
openCommand("Create Spreadsheet");
doCommand(Doc,"App.activeDocument().addObject('Spreadsheet::Sheet','%s\')",FeatName.c_str());
commitCommand();
}
bool CmdCreateSpreadsheet::isActive()
{
return App::GetApplication().getActiveDocument();
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void CreateSpreadsheetCommands(void)
{
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
rcCmdMgr.addCommand(new CmdCreateSpreadsheet());
rcCmdMgr.addCommand(new CmdSpreadsheetMergeCells());
rcCmdMgr.addCommand(new CmdSpreadsheetSplitCell());
rcCmdMgr.addCommand(new CmdSpreadsheetImport());
rcCmdMgr.addCommand(new CmdSpreadsheetExport());
rcCmdMgr.addCommand(new CmdSpreadsheetAlignLeft());
rcCmdMgr.addCommand(new CmdSpreadsheetAlignCenter());
rcCmdMgr.addCommand(new CmdSpreadsheetAlignRight());
rcCmdMgr.addCommand(new CmdSpreadsheetAlignTop());
rcCmdMgr.addCommand(new CmdSpreadsheetAlignVCenter());
rcCmdMgr.addCommand(new CmdSpreadsheetAlignBottom());
rcCmdMgr.addCommand(new CmdSpreadsheetStyleBold());
rcCmdMgr.addCommand(new CmdSpreadsheetStyleItalic());
rcCmdMgr.addCommand(new CmdSpreadsheetStyleUnderline());
}

View File

@@ -0,0 +1,24 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2002 *
* *
* 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"

View File

@@ -0,0 +1,79 @@
/***************************************************************************
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2002 *
* *
* 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 __PRECOMPILED_GUI__
#define __PRECOMPILED_GUI__
#include <FCConfig.h>
// Importing of App classes
#ifdef FC_OS_WIN32
# define SpreadsheetExport __declspec(dllimport)
# define SpreadsheetGuiExport __declspec(dllexport)
#else // for Linux
# define SpreadsheetExport
# define SpreadsheetGuiExport
#endif
// here get the warnings of too long specifiers disabled (needed for VC6)
#ifdef _MSC_VER
# pragma warning( disable : 4251 )
# pragma warning( disable : 4503 )
# pragma warning( disable : 4786 ) // specifier longer then 255 chars
#endif
#ifdef _PreComp_
// Python
#include <Python.h>
// standard
#include <iostream>
#include <assert.h>
#include <math.h>
// STL
#include <vector>
#include <map>
#include <string>
#include <list>
#include <set>
#include <algorithm>
#include <stack>
#include <queue>
#include <bitset>
#ifdef FC_OS_WIN32
# include <windows.h>
#endif
// Qt Toolkit
#ifndef __Qt4All__
# include <Gui/Qt4All.h>
#endif
#endif //_PreComp_
#endif // __PRECOMPILED_GUI__

View File

@@ -0,0 +1,297 @@
/***************************************************************************
* 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 "PropertiesDialog.h"
#include <Base/Tools.h>
#include <Mod/Spreadsheet/App/Expression.h>
#include <Mod/Spreadsheet/App/Range.h>
#include <Gui/Command.h>
#include "ui_PropertiesDialog.h"
using namespace Spreadsheet;
using namespace SpreadsheetGui;
PropertiesDialog::PropertiesDialog(Sheet *_sheet, const std::vector<Range> &_ranges, QWidget *parent) :
QDialog(parent),
sheet(_sheet),
ranges(_ranges),
ui(new Ui::PropertiesDialog),
alignment(0),
displayUnitOk(true),
aliasOk(true)
{
ui->setupUi(this);
ui->foregroundColor->setStandardColors();
ui->backgroundColor->setStandardColors();
assert(ranges.size() > 0);
Range range = ranges[0];
sheet->getNewCell(*range)->getForeground(foregroundColor);
sheet->getCell(*range)->getBackground(backgroundColor);
sheet->getCell(*range)->getAlignment(alignment);
sheet->getCell(*range)->getStyle(style);
sheet->getCell(*range)->getDisplayUnit(displayUnit);
sheet->getCell(*range)->getAlias(alias);
orgForegroundColor = foregroundColor;
orgBackgroundColor = backgroundColor;
orgAlignment = alignment;
orgStyle = style;
orgDisplayUnit = displayUnit;
orgAlias = alias;
ui->foregroundColor->setCurrentColor(QColor::fromRgbF(foregroundColor.r,
foregroundColor.g,
foregroundColor.b,
foregroundColor.a));
ui->backgroundColor->setCurrentColor(QColor::fromRgbF(backgroundColor.r,
backgroundColor.g,
backgroundColor.b,
backgroundColor.a));
if (alignment & Cell::ALIGNMENT_LEFT)
ui->alignLeft->setChecked(true);
else if (alignment & Cell::ALIGNMENT_HCENTER)
ui->alignHCenter->setChecked(true);
else if (alignment & Cell::ALIGNMENT_RIGHT)
ui->alignRight->setChecked(true);
if (alignment & Cell::ALIGNMENT_TOP)
ui->alignTop->setChecked(true);
else if (alignment & Cell::ALIGNMENT_VCENTER)
ui->alignVCenter->setChecked(true);
else if (alignment & Cell::ALIGNMENT_BOTTOM)
ui->alignBottom->setChecked(true);
if (style.find("bold") != style.end())
ui->styleBold->setChecked(true);
if (style.find("italic") != style.end())
ui->styleItalic->setChecked(true);
if (style.find("underline") != style.end())
ui->styleUnderline->setChecked(true);
ui->displayUnit->setText(QString::fromStdString(displayUnit.stringRep));
ui->alias->setText(QString::fromStdString(alias));
// Colors
connect(ui->foregroundColor, SIGNAL(colorChanged(QColor)), this, SLOT(foregroundColorChanged(QColor)));
connect(ui->backgroundColor, SIGNAL(colorChanged(QColor)), this, SLOT(backgroundColorChanged(QColor)));
// Alignment
connect(ui->alignLeft, SIGNAL(clicked()), this, SLOT(alignmentChanged()));
connect(ui->alignRight, SIGNAL(clicked()), this, SLOT(alignmentChanged()));
connect(ui->alignHCenter, SIGNAL(clicked()), this, SLOT(alignmentChanged()));
connect(ui->alignTop, SIGNAL(clicked()), this, SLOT(alignmentChanged()));
connect(ui->alignVCenter, SIGNAL(clicked()), this, SLOT(alignmentChanged()));
connect(ui->alignBottom, SIGNAL(clicked()), this, SLOT(alignmentChanged()));
// Style
connect(ui->styleBold, SIGNAL(clicked()), this, SLOT(styleChanged()));
connect(ui->styleItalic, SIGNAL(clicked()), this, SLOT(styleChanged()));
connect(ui->styleUnderline, SIGNAL(clicked()), this, SLOT(styleChanged()));
// Display unit
connect(ui->displayUnit, SIGNAL(textEdited(QString)), this, SLOT(displayUnitChanged(QString)));
// Alias is only allowed for a single cell
ui->tabWidget->widget(4)->setEnabled(_ranges.size() == 1 && _ranges[0].size() == 1);
// Alias
connect(ui->alias, SIGNAL(textEdited(QString)), this, SLOT(aliasChanged(QString)));
ui->tabWidget->setCurrentIndex(0);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(displayUnitOk && aliasOk);
}
void PropertiesDialog::foregroundColorChanged(const QColor & color)
{
foregroundColor = App::Color(color.redF(), color.greenF(), color.blueF(), color.alphaF());
}
void PropertiesDialog::backgroundColorChanged(const QColor & color)
{
backgroundColor = App::Color(color.redF(), color.greenF(), color.blueF(), color.alphaF());
}
void PropertiesDialog::alignmentChanged()
{
if (sender() == ui->alignLeft)
alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_LEFT;
else if (sender() == ui->alignHCenter)
alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_HCENTER;
else if (sender() == ui->alignRight)
alignment = (alignment & ~Cell::ALIGNMENT_HORIZONTAL) | Cell::ALIGNMENT_RIGHT;
else if (sender() == ui->alignTop)
alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_TOP;
else if (sender() == ui->alignVCenter)
alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_VCENTER;
else if (sender() == ui->alignBottom)
alignment = (alignment & ~Cell::ALIGNMENT_VERTICAL) | Cell::ALIGNMENT_BOTTOM;
}
void PropertiesDialog::styleChanged()
{
if (sender() == ui->styleBold) {
if (ui->styleBold->isChecked())
style.insert("bold");
else
style.erase("bold");
}
else if (sender() == ui->styleItalic) {
if (ui->styleItalic->isChecked())
style.insert("italic");
else
style.erase("italic");
}
else if (sender() == ui->styleUnderline) {
if (ui->styleUnderline->isChecked())
style.insert("underline");
else
style.erase("underline");
}
}
void PropertiesDialog::displayUnitChanged(const QString & text)
{
if (text == "") {
displayUnit = DisplayUnit();
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
return;
}
QPalette palette = ui->displayUnit->palette();
try {
std::auto_ptr<UnitExpression> e(ExpressionParser::parseUnit(sheet, text.toUtf8().constData()));
displayUnit = DisplayUnit(text.toUtf8().constData(), e->getUnit(), e->getScaler());
palette.setColor(QPalette::Text, Qt::black);
displayUnitOk = true;
}
catch (...) {
displayUnit = DisplayUnit();
palette.setColor(QPalette::Text, text.size() == 0 ? Qt::black : Qt::red);
displayUnitOk = false;
}
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(displayUnitOk && aliasOk);
ui->displayUnit->setPalette(palette);
}
void PropertiesDialog::aliasChanged(const QString & text)
{
QPalette palette = ui->alias->palette();
if (text.indexOf(QRegExp("^[A-Za-z][_A-Za-z0-9]*$")) >= 0) {
try {
CellAddress address(text.toUtf8().constData());
palette.setColor(QPalette::Text, Qt::red);
aliasOk = false;
alias = "";
}
catch (...) {
aliasOk = true;
palette.setColor(QPalette::Text, Qt::black);
alias = text.toStdString();
}
}
else {
if (text == "") {
aliasOk = true;
palette.setColor(QPalette::Text, Qt::black);
}
else {
aliasOk = false;
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
palette.setColor(QPalette::Text, Qt::red);
}
alias = "";
}
ui->alias->setPalette(palette);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(displayUnitOk && aliasOk);
}
PropertiesDialog::~PropertiesDialog()
{
delete ui;
}
void PropertiesDialog::apply()
{
if (ranges.size() > 0) {
Gui::Command::openCommand("Set cell properties");
std::vector<Range>::const_iterator i = ranges.begin();
bool changes = false;
for (; i != ranges.end(); ++i) {
if (orgAlignment != alignment) {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlignment('%s', '%s')", sheet->getNameInDocument(),
i->rangeString().c_str(), Cell::encodeAlignment(alignment).c_str());
changes = true;
}
if (orgStyle != style) {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setStyle('%s', '%s')", sheet->getNameInDocument(),
i->rangeString().c_str(), Cell::encodeStyle(style).c_str());
changes = true;
}
if (orgForegroundColor != foregroundColor) {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setForeground('%s', (%f,%f,%f,%f))", sheet->getNameInDocument(),
i->rangeString().c_str(),
foregroundColor.r,
foregroundColor.g,
foregroundColor.b,
foregroundColor.a);
changes = true;
}
if (orgBackgroundColor != backgroundColor) {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setBackground('%s', (%f,%f,%f,%f))", sheet->getNameInDocument(),
i->rangeString().c_str(),
backgroundColor.r,
backgroundColor.g,
backgroundColor.b,
backgroundColor.a);
changes = true;
}
if (orgDisplayUnit != displayUnit) {
std::string escapedstr = Base::Tools::escapedUnicodeFromUtf8(displayUnit.stringRep.c_str());
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setDisplayUnit('%s', '%s')", sheet->getNameInDocument(),
i->rangeString().c_str(), escapedstr.c_str());
changes = true;
}
if (ranges.size() == 1 && ranges[0].size() == 1 && orgAlias != alias) {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setAlias('%s', '%s')", sheet->getNameInDocument(),
i->address().c_str(), alias.c_str());
changes = true;
}
}
if (changes) {
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
else
Gui::Command::abortCommand();
}
}
#include "moc_PropertiesDialog.cpp"

View File

@@ -0,0 +1,77 @@
/***************************************************************************
* 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 PROPERTIESDIALOG_H
#define PROPERTIESDIALOG_H
#include <QDialog>
#include "PreCompiled.h"
#include <Mod/Spreadsheet/App/Sheet.h>
namespace Ui {
class PropertiesDialog;
}
namespace SpreadsheetGui {
class PropertiesDialog : public QDialog
{
Q_OBJECT
public:
explicit PropertiesDialog(Spreadsheet::Sheet *_sheet, const std::vector<Spreadsheet::Range> & _ranges, QWidget *parent = 0);
~PropertiesDialog();
void apply();
private Q_SLOTS:
void foregroundColorChanged(const QColor &color);
void backgroundColorChanged(const QColor &color);
void alignmentChanged();
void styleChanged();
void displayUnitChanged(const QString &text);
void aliasChanged(const QString &text);
private:
Spreadsheet::Sheet * sheet;
std::vector<Spreadsheet::Range> ranges;
Ui::PropertiesDialog *ui;
App::Color foregroundColor;
App::Color backgroundColor;
int alignment;
std::set<std::string> style;
Spreadsheet::DisplayUnit displayUnit;
std::string alias;
App::Color orgForegroundColor;
App::Color orgBackgroundColor;
int orgAlignment;
std::set<std::string> orgStyle;
Spreadsheet::DisplayUnit orgDisplayUnit;
std::string orgAlias;
bool displayUnitOk;
bool aliasOk;
};
}
#endif // PROPERTIESDIALOG_H

View File

@@ -0,0 +1,345 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PropertiesDialog</class>
<widget class="QDialog" name="PropertiesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>426</width>
<height>249</height>
</rect>
</property>
<property name="windowTitle">
<string>Cell properties</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>&amp;Color</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Text</string>
</property>
</widget>
</item>
<item row="0" column="4">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>240</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QtColorPicker" name="foregroundColor" native="true"/>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Background</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QtColorPicker" name="backgroundColor" native="true"/>
</item>
<item row="1" column="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>&amp;Alignment</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Horizontal</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="alignLeft">
<property name="text">
<string>Left</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="alignHCenter">
<property name="text">
<string>Center</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="alignRight">
<property name="text">
<string>Right</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Vertical</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="alignTop">
<property name="text">
<string>Top</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="alignVCenter">
<property name="text">
<string>Center</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="alignBottom">
<property name="text">
<string>Bottom</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>&amp;Style</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="styleBold">
<property name="text">
<string>Bold</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="styleItalic">
<property name="text">
<string>Italic</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="styleUnderline">
<property name="text">
<string>Underline</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>&amp;Display unit</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="1">
<widget class="QLineEdit" name="displayUnit"/>
</item>
<item row="1" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>123</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Unit string</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_5">
<attribute name="title">
<string>A&amp;lias</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="1">
<widget class="QLineEdit" name="alias"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Alias for this cell</string>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QtColorPicker</class>
<extends>QWidget</extends>
<header>qtcolorpicker.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>PropertiesDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>PropertiesDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,19 @@
<RCC>
<qresource prefix="/">
<file>icons/Spreadsheet.svg</file>
<file>icons/SpreadsheetController.svg</file>
<file>icons/SpreadsheetImport.svg</file>
<file>icons/SpreadsheetExport.svg</file>
<file>icons/SpreadsheetSplitCell.svg</file>
<file>icons/SpreadsheetMergeCells.svg</file>
<file>icons/SpreadsheetAlignRight.svg</file>
<file>icons/SpreadsheetAlignLeft.svg</file>
<file>icons/SpreadsheetAlignCenter.svg</file>
<file>icons/SpreadsheetAlignVCenter.svg</file>
<file>icons/SpreadsheetAlignTop.svg</file>
<file>icons/SpreadsheetAlignBottom.svg</file>
<file>icons/SpreadsheetStyleUnderline.svg</file>
<file>icons/SpreadsheetStyleItalic.svg</file>
<file>icons/SpreadsheetStyleBold.svg</file>
</qresource>
</RCC>

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.1 r9760"
sodipodi:docname="SpreadsheetAlignTop.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="10.658514"
inkscape:cy="35.257738"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1600"
inkscape:window-height="876"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#030000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3068"
width="65.090912"
height="64.36364"
x="-0.90909213"
y="-0.36363849" />
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3002"
width="56.18182"
height="46.545456"
x="4"
y="9.272728" />
<path
style="fill:none;stroke:#000000;stroke-width:4.49824524;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 7.3625277,29.636364 47.0931263,0"
id="path3790"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.98300838;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 7.6478315,40.793448 31.7952445,0"
id="path3794"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:4.49824524;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 6.635255,52.181818 47.093126,0"
id="path3790-40"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.1 r9760"
sodipodi:docname="SpreadsheetAlignCenter.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="10.658514"
inkscape:cy="35.257738"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1600"
inkscape:window-height="876"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#030000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3068"
width="65.090912"
height="64.36364"
x="-0.90909213"
y="-0.36363849" />
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3002"
width="56.18182"
height="46.545456"
x="4"
y="9.272728" />
<path
style="fill:none;stroke:#000000;stroke-width:4.49824524;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 8.2716186,20.545455 47.0931264,0"
id="path3790"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.98300838;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 15.647832,32.429811 31.795245,0"
id="path3794"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.94518471;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 4.7572062,44.483064 54.1219518,0"
id="path3796"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:4.25173235;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 11.077051,8.9090905 41.118626,0"
id="path3790-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:4.20950508;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 15.997228,56 31.278271,0"
id="path3790-4"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.1 r9760"
sodipodi:docname="SpreadsheetAlignLeft.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="10.658514"
inkscape:cy="35.257738"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1600"
inkscape:window-height="876"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#030000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3068"
width="65.090912"
height="64.36364"
x="-0.90909249"
y="-0.18182078" />
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3002"
width="56.18182"
height="46.545456"
x="4"
y="9.272728" />
<path
style="fill:none;stroke:#000000;stroke-width:3.95484757;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 4,20.545455 54.38739,0"
id="path3790"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.55215096;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 4,32.429811 43.4453,0"
id="path3794"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.57292891;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 4,44.483064 44.390244,0"
id="path3796"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.97173762;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 4.1936752,9.454545 40.4175278,0"
id="path3790-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.85852957;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 3.8181816,56 55.588692,56"
id="path3790-4"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.1 r9760"
sodipodi:docname="SpreadsheetAlignRight.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="10.658514"
inkscape:cy="35.257738"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1600"
inkscape:window-height="876"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#030000;stroke-width:3.59999989999999981;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3068"
width="65.090912"
height="64.36364"
x="0.18181819"
y="0" />
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3002"
width="56.18182"
height="46.545456"
x="4"
y="9.272728" />
<path
style="fill:none;stroke:#000000;stroke-width:3.88404441;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 16.124723,20.545455 43.511641,0"
id="path3790"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.83060455;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 8.5672727,32.429811 50.5236363,0"
id="path3794"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.69230366;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 20.693459,44.483064 38.942905,0"
id="path3796"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:4.20847988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 11.896315,8.9090905 47.558231,0"
id="path3790-8"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.4652288;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 17.700111,56 41.754435,0"
id="path3790-4"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.1 r9760"
sodipodi:docname="SpreadsheetAlignTop.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="10.658514"
inkscape:cy="35.257738"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1600"
inkscape:window-height="876"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#030000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3068"
width="65.090912"
height="64.36364"
x="-0.90909213"
y="-0.36363849" />
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3002"
width="56.18182"
height="46.545456"
x="4"
y="9.272728" />
<path
style="fill:none;stroke:#000000;stroke-width:4.49824524;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 7.1807095,10.909091 47.0931265,0"
id="path3790"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.98300838;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 7.4660133,22.247993 31.7952447,0"
id="path3794"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:4.49824524;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 7.1807095,33.272727 47.0931265,0"
id="path3790-40"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.1 r9760"
sodipodi:docname="SpreadsheetAlignVCenter.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="10.658514"
inkscape:cy="35.257738"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1600"
inkscape:window-height="876"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#030000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3068"
width="65.090912"
height="64.36364"
x="-0.90909213"
y="-0.36363849" />
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3002"
width="56.18182"
height="46.545456"
x="4"
y="9.272728" />
<path
style="fill:none;stroke:#000000;stroke-width:4.49824524;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 8.2716186,20.545455 47.0931264,0"
id="path3790"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.98300838;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 9.2841951,32.066175 31.7952449,0"
id="path3794"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:4.49824524;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 7.5443459,43.454545 47.0931261,0"
id="path3790-40"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.1 r9760"
sodipodi:docname="Spreadsheet.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11"
inkscape:cx="43.689905"
inkscape:cy="36.551269"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1600"
inkscape:window-height="876"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3002"
width="56.18182"
height="46.545456"
x="4"
y="9.272728" />
<rect
style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3002-9"
width="56.18182"
height="46.545456"
x="4"
y="9.272728" />
<path
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 4.9090909,25.338902 60,25.338902"
id="path3794"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 4.5454546,41.392155 55.6363634,0"
id="path3796"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.47719836px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 23.727274,42.363636 c 0,14.181818 0,14.181818 0,14.181818"
id="path4679"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.47719836px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 41.818182,41.636364 c 0,14.181817 0,14.181817 0,14.181817"
id="path4679-2"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.47719836px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 23.272727,9.818182 c 0,14.181818 0,14.181818 0,14.181818"
id="path4679-3"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3.47719836px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 41.636364,9.8181824 c 0,14.1818166 0,14.1818166 0,14.1818166"
id="path4679-5"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#0000ff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 19.678277,29.014962 -6.587368,3.803219 37.090909,0 -6.664684,-3.847857"
id="path5239"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
style="fill:none;stroke:#0000ff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 19.678277,37.606563 -6.587368,-3.803219 37.090909,0 -6.664684,3.847857"
id="path5239-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.1 r9760"
sodipodi:docname="SpreadsheetStyleBold.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="10.658514"
inkscape:cy="35.257738"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1600"
inkscape:window-height="876"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#030000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3068"
width="65.090912"
height="64.36364"
x="-0.90909249"
y="-0.18182078" />
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3002"
width="56.18182"
height="46.545456"
x="4"
y="9.272728" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
x="16.363634"
y="45.999996"
id="text4123"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4125"
x="16.363634"
y="45.999996"
style="font-weight:bold">B</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.1 r9760"
sodipodi:docname="SpreadsheetStyleBold.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="10.658514"
inkscape:cy="35.257738"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1600"
inkscape:window-height="876"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#030000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3068"
width="65.090912"
height="64.36364"
x="-0.90909249"
y="-0.18182078" />
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3002"
width="56.18182"
height="46.545456"
x="4"
y="9.272728" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
x="23.81818"
y="46.545452"
id="text4123"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4125"
x="23.81818"
y="46.545452"
style="font-style:italic;font-weight:normal">i</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64px"
height="64px"
id="svg2860"
sodipodi:version="0.32"
inkscape:version="0.48.1 r9760"
sodipodi:docname="SpreadsheetStyleUnderline.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.1">
<defs
id="defs2862">
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3692"
cx="45.883327"
cy="28.869568"
fx="45.883327"
fy="28.869568"
r="19.467436"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3703"
gradientUnits="userSpaceOnUse"
cx="135.38333"
cy="97.369568"
fx="135.38333"
fy="97.369568"
r="19.467436"
gradientTransform="matrix(0.97435,0.2250379,-0.4623105,2.0016728,48.487554,-127.99883)" />
<linearGradient
id="linearGradient3377">
<stop
id="stop3379"
offset="0"
style="stop-color:#faff2b;stop-opacity:1;" />
<stop
id="stop3381"
offset="1"
style="stop-color:#ffaa00;stop-opacity:1;" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3377"
id="radialGradient3705"
gradientUnits="userSpaceOnUse"
cx="148.88333"
cy="81.869568"
fx="148.88333"
fy="81.869568"
r="19.467436"
gradientTransform="matrix(1.3852588,-0.05136783,0.03705629,0.9993132,-60.392403,7.7040438)" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 32 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="64 : 32 : 1"
inkscape:persp3d-origin="32 : 21.333333 : 1"
id="perspective2868" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="10.658514"
inkscape:cy="35.257738"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="1600"
inkscape:window-height="876"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata2865">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#030000;stroke-width:3.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3068"
width="65.090912"
height="64.36364"
x="-0.90909249"
y="-0.18182078" />
<rect
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect3002"
width="56.18182"
height="46.545456"
x="4"
y="9.272728" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
x="16.727272"
y="42.909088"
id="text4123"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4125"
x="16.727272"
y="42.909088"
style="font-style:normal;font-weight:normal">U</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:3.11890268px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 20.363637,48.181818 22.795883,0"
id="path4186"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Sheet</class>
<widget class="QWidget" name="Sheet">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>727</width>
<height>596</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;Contents</string>
</property>
<property name="buddy">
<cstring>cellContent</cstring>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="cellContent">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="SpreadsheetGui::SheetTableView" name="cells"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SpreadsheetGui::SheetTableView</class>
<extends>QTableView</extends>
<header>SheetTableView.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>cells</tabstop>
<tabstop>cellContent</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,435 @@
/***************************************************************************
* 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"
#ifndef _PreComp_
#include <QtCore>
# include <QApplication>
# include <QMessageBox>
#endif
#include "SheetModel.h"
#include <Mod/Spreadsheet/App/Expression.h>
#include <Mod/Spreadsheet/App/Utils.h>
#include "../App/Sheet.h"
#include <Gui/Command.h>
#include <strstream>
#include <boost/bind.hpp>
using namespace SpreadsheetGui;
using namespace Spreadsheet;
using namespace App;
SheetModel::SheetModel(Sheet *_sheet, QObject *parent)
: QAbstractTableModel(parent)
, sheet(_sheet)
{
cellUpdatedConnection = sheet->cellUpdated.connect(bind(&SheetModel::cellUpdated, this, _1));
}
SheetModel::~SheetModel()
{
cellUpdatedConnection.disconnect();
}
int SheetModel::rowCount(const QModelIndex &parent) const
{
return 16384;
}
int SheetModel::columnCount(const QModelIndex &parent) const
{
return 26 * 26 + 26;
}
static void appendUnit(int l, bool isNumerator, std::string unit, std::vector<std::string> & v)
{
if (l == 0)
return;
if ((l < 0) ^ isNumerator ) {
std::ostringstream s;
s << unit;
if (abs(l) > 1)
s << "^" << abs(l);
v.push_back(s.str());
}
}
static std::string getUnitString(const Base::Unit & unit)
{
std::vector<std::string> numerator;
std::vector<std::string> denominator;
const Base::UnitSignature & sig = unit.getSignature();
// Nominator
appendUnit(sig.Length, true, "mm", numerator);
appendUnit(sig.Mass, true, "kg", numerator);
appendUnit(sig.Time, true, "s", numerator);
appendUnit(sig.ElectricCurrent, true, "A", numerator);
appendUnit(sig.ThermodynamicTemperature, true, "K", numerator);
appendUnit(sig.AmountOfSubstance, true, "mol", numerator);
appendUnit(sig.LuminoseIntensity, true, "cd", numerator);
appendUnit(sig.Angle, true, "deg", numerator);
// Denominator
appendUnit(sig.Length, false, "mm", denominator);
appendUnit(sig.Mass, false, "kg", denominator);
appendUnit(sig.Time, false, "s", denominator);
appendUnit(sig.ElectricCurrent, false, "A", denominator);
appendUnit(sig.ThermodynamicTemperature, false, "K", denominator);
appendUnit(sig.AmountOfSubstance, false, "mol", denominator);
appendUnit(sig.LuminoseIntensity, false, "cd", denominator);
appendUnit(sig.Angle, false, "deg", denominator);
std::string unitStr;
if (numerator.size() > 0) {
for (int i = 0; i < numerator.size(); ++i) {
if (i > 0)
unitStr += "*";
unitStr += numerator[i];
}
}
if (denominator.size() > 0) {
if (numerator.size() == 0)
unitStr = "1";
unitStr += "/";
if (denominator.size() > 1)
unitStr += "(";
for (int i = 0; i < denominator.size(); ++i) {
if (i > 0)
unitStr += "*";
unitStr += denominator[i];
}
if (denominator.size() > 1)
unitStr += ")";
}
return unitStr;
}
QVariant SheetModel::data(const QModelIndex &index, int role) const
{
static const Cell * emptyCell = new Cell(CellAddress(0, 0), 0);
int row = index.row();
int col = index.column();
const Cell * cell = sheet->getCell(CellAddress(row, col));
if (cell == 0)
cell = emptyCell;
//#define DEBUG_DEPS
#ifdef DEBUG_DEPS
if (role == Qt::ToolTipRole) {
QString v;
std::set<std::string> deps = sheet->dependsOn(row, col);
std::set<std::string> provides;
sheet->providesTo(row, col, provides);
if (deps.size() > 0) {
v += QString::fromUtf8("Depends on:");
for (std::set<std::string>::const_iterator i = deps.begin(); i != deps.end(); ++i)
v += QString::fromUtf8("\n\t") + QString::fromStdString(*i);
v += QString::fromUtf8("\n");
}
if (provides.size() > 0) {
v += QString::fromUtf8("Used by:");
for (std::set<std::string>::const_iterator i = provides.begin(); i != provides.end(); ++i)
v += QString::fromUtf8("\n\t") + QString::fromStdString(*i);
v += QString::fromUtf8("\n");
}
return QVariant(v);
}
#endif
if (cell->hasException()) {
switch (role) {
case Qt::ToolTipRole:
return QVariant::fromValue(QString::fromStdString(cell->getException()));
case Qt::DisplayRole:
#ifdef DEBUG_DEPS
return QVariant::fromValue(QString::fromUtf8("#ERR: %1").arg(QString::fromStdString(cell->getException())));
#else
return QVariant::fromValue(QString::fromUtf8("#ERR"));
#endif
case Qt::TextAlignmentRole:
return QVariant(Qt::AlignVCenter | Qt::AlignLeft);
default:
break;
}
}
// Get edit value by querying the sheet
if (role == Qt::EditRole || role == Qt::StatusTipRole) {
std::string str;
if (cell->getStringContent(str))
return QVariant(QString::fromUtf8(str.c_str()));
else
return QVariant();
}
// Get display value as computed property
std::string address = addressToString(CellAddress(row, col));
Property * prop = sheet->getPropertyByName(address.c_str());
if (prop == 0)
return QVariant();
Color color;
if (role == Qt::TextColorRole || role == Qt::ForegroundRole) {
if (cell->getForeground(color))
return QVariant::fromValue(QColor(255.0 * color.r, 255.0 * color.g, 255.0 * color.b, 255.0 * color.a));
else
return QVariant();
}
if (role == Qt::BackgroundRole) {
if (cell->getBackground(color))
return QVariant::fromValue(QColor(255.0 * color.r, 255.0 * color.g, 255.0 * color.b, 255.0 * color.a));
else
return QVariant();
}
int qtAlignment = 0;
int alignment;
cell->getAlignment(alignment);
if (alignment & Cell::ALIGNMENT_LEFT)
qtAlignment |= Qt::AlignLeft;
if (alignment & Cell::ALIGNMENT_HCENTER)
qtAlignment |= Qt::AlignHCenter;
if (alignment & Cell::ALIGNMENT_RIGHT)
qtAlignment |= Qt::AlignRight;
if (alignment & Cell::ALIGNMENT_TOP)
qtAlignment |= Qt::AlignTop;
if (alignment & Cell::ALIGNMENT_VCENTER)
qtAlignment |= Qt::AlignVCenter;
if (alignment & Cell::ALIGNMENT_BOTTOM)
qtAlignment |= Qt::AlignBottom;
std::set<std::string> style;
if (role == Qt::FontRole && cell->getStyle(style)) {
QFont f;
for (std::set<std::string>::const_iterator i = style.begin(); i != style.end(); ++i) {
if (*i == "bold")
f.setBold(true);
else if (*i == "italic")
f.setItalic(true);
else if (*i == "underline")
f.setUnderline(true);
}
return QVariant::fromValue(f);
}
if (prop->isDerivedFrom(App::PropertyString::getClassTypeId())) {
/* String */
const App::PropertyString * stringProp = static_cast<const App::PropertyString*>(prop);
switch (role) {
case Qt::TextColorRole:
return QVariant::fromValue(QColor(Qt::black));
case Qt::DisplayRole:
return QVariant(QString::fromUtf8(stringProp->getValue()));
case Qt::TextAlignmentRole: {
if (alignment & Cell::ALIGNMENT_HIMPLIED) {
qtAlignment &= ~(Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight);
qtAlignment |= Qt::AlignLeft;
}
if (alignment & Cell::ALIGNMENT_VIMPLIED) {
qtAlignment &= ~(Qt::AlignTop | Qt::AlignVCenter | Qt::AlignBottom);
qtAlignment |= Qt::AlignVCenter;
}
return QVariant::fromValue(qtAlignment);
}
default:
return QVariant();
}
}
else if (prop->isDerivedFrom(App::PropertyQuantity::getClassTypeId())) {
/* Number */
const App::PropertyQuantity * floatProp = static_cast<const App::PropertyQuantity*>(prop);
switch (role) {
case Qt::TextColorRole:
if (floatProp->getValue() < 0)
return QVariant::fromValue(QColor(Qt::red));
else
return QVariant::fromValue(QColor(Qt::blue));
case Qt::TextAlignmentRole: {
if (alignment & Cell::ALIGNMENT_HIMPLIED) {
qtAlignment &= ~(Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight);
qtAlignment |= Qt::AlignRight;
}
if (alignment & Cell::ALIGNMENT_VIMPLIED) {
qtAlignment &= ~(Qt::AlignTop | Qt::AlignVCenter | Qt::AlignBottom);
qtAlignment |= Qt::AlignVCenter;
}
return QVariant::fromValue(qtAlignment);
}
case Qt::DisplayRole: {
QString v;
const Base::Unit & computedUnit = floatProp->getUnit();
DisplayUnit displayUnit;
if (cell->getDisplayUnit(displayUnit)) {
if (computedUnit.isEmpty() || computedUnit == displayUnit.unit)
v = QString::number(floatProp->getValue() / displayUnit.scaler) + QString::fromStdString(" " + displayUnit.stringRep);
else
v = QString::fromUtf8("ERR: unit");
}
else {
if (!computedUnit.isEmpty())
v = QString::number(floatProp->getValue()) + QString::fromStdString(" " + getUnitString(computedUnit));
else
v = QString::number(floatProp->getValue());
}
return QVariant(v);
}
default:
return QVariant();
}
}
else if (prop->isDerivedFrom(App::PropertyFloat::getClassTypeId())) {
/* Number */
const App::PropertyFloat * floatProp = static_cast<const App::PropertyFloat*>(prop);
switch (role) {
case Qt::TextColorRole:
if (floatProp->getValue() < 0)
return QVariant::fromValue(QColor(Qt::red));
else
return QVariant::fromValue(QColor(Qt::blue));
case Qt::TextAlignmentRole: {
if (alignment & Cell::ALIGNMENT_HIMPLIED) {
qtAlignment &= ~(Qt::AlignLeft | Qt::AlignHCenter | Qt::AlignRight);
qtAlignment |= Qt::AlignRight;
}
if (alignment & Cell::ALIGNMENT_VIMPLIED) {
qtAlignment &= ~(Qt::AlignTop | Qt::AlignVCenter | Qt::AlignBottom);
qtAlignment |= Qt::AlignVCenter;
}
return QVariant::fromValue(qtAlignment);
}
case Qt::DisplayRole: {
QString v;
DisplayUnit displayUnit;
if (cell->getDisplayUnit(displayUnit))
v = QString::number(floatProp->getValue() / displayUnit.scaler) + QString::fromStdString(" " + displayUnit.stringRep);
else
v = QString::number(floatProp->getValue());
return QVariant(v);
}
default:
return QVariant();
}
}
}
QVariant SheetModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::SizeHintRole) {
if (orientation == Qt::Horizontal)
return QVariant(QSize(sheet->getColumnWidth(section), PropertyRowHeights::defaultHeight));
else
return QVariant(QSize(PropertyColumnWidths::defaultHeaderWidth, sheet->getRowHeight(section)));
}
if (role == Qt::DisplayRole) {
if (orientation == Qt::Horizontal) {
static QString labels = QString::fromUtf8("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
if (section < 26) {
return QVariant(labels[section]);
}
else {
section -= 26;
return QVariant(QString(labels[section / 26]) + QString(labels[section % 26]));
}
}
else {
return QString::number(section + 1);
}
}
return QVariant();
}
bool SheetModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
if (role == Qt::DisplayRole) {
// Nothing to do, it will get updated by the sheet in the application logic
}
else if (role == Qt::EditRole) {
CellAddress address(index.row(), index.column());
try {
std::string strAddress = addressToString(address);
std::string next_address = addressToString(CellAddress(address.row() + 1, address.col()));
QString str = value.toString();
std::string content;
Cell * cell = sheet->getCell(address);
if (cell)
cell->getStringContent(content);
if ( content != str.toStdString()) {
str.replace(QString::fromUtf8("'"), QString::fromUtf8("\\'"));
Gui::Command::openCommand("Edit cell");
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.set('%s', '%s')", sheet->getNameInDocument(),
strAddress.c_str(), str.toUtf8().constData());
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setPosition('%s')", sheet->getNameInDocument(),
next_address.c_str());
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
catch (const Base::Exception& e) {
QMessageBox::critical(qApp->activeWindow(), QObject::tr("Cell contents"), QString::fromUtf8(e.what()));
Gui::Command::abortCommand();
}
}
return true;
}
Qt::ItemFlags SheetModel::flags(const QModelIndex & /*index*/) const
{
return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled;
}
void SheetModel::cellUpdated(CellAddress address)
{
QModelIndex i = index(address.row(), address.col());
dataChanged(i, i);
}
#include "moc_SheetModel.cpp"

View File

@@ -0,0 +1,60 @@
/***************************************************************************
* 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 SHEETMODEL_H
#define SHEETMODEL_H
#include <QAbstractTableModel>
#include <boost/signals/connection.hpp>
#include <Mod/Spreadsheet/App/Utils.h>
namespace Spreadsheet {
class Sheet;
}
namespace SpreadsheetGui {
class SheetModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit SheetModel(Spreadsheet::Sheet * _sheet, QObject *parent = 0);
~SheetModel();
SheetModel(QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const ;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
Qt::ItemFlags flags(const QModelIndex &) const;
private:
void cellUpdated(Spreadsheet::CellAddress address);
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection cellUpdatedConnection;
Spreadsheet::Sheet * sheet;
};
}
#endif // SHEETMODEL_H

View File

@@ -0,0 +1,299 @@
/***************************************************************************
* 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"
#ifndef _PreComp_
#endif
#include "SheetTableView.h"
#include <QKeyEvent>
#include <QAction>
#include <Gui/Command.h>
#include "PropertiesDialog.h"
#include "../App/Utils.h"
#include "../App/Range.h"
#include <boost/bind.hpp>
using namespace SpreadsheetGui;
using namespace Spreadsheet;
void SheetViewHeader::mouseReleaseEvent(QMouseEvent *event)
{
QHeaderView::mouseReleaseEvent(event);
resizeFinished();
}
SheetTableView::SheetTableView(QWidget *parent)
: QTableView(parent)
{
QAction * insertRows = new QAction(tr("Insert rows"), this);
QAction * removeRows = new QAction(tr("Remove rows"), this);
QAction * insertColumns = new QAction(tr("Insert columns"), this);
QAction * removeColumns = new QAction(tr("Remove columns"), this);
setHorizontalHeader(new SheetViewHeader(Qt::Horizontal));
setVerticalHeader(new SheetViewHeader(Qt::Vertical));
horizontalHeader()->addAction(insertColumns);
horizontalHeader()->addAction(removeColumns);
horizontalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu);
verticalHeader()->addAction(insertRows);
verticalHeader()->addAction(removeRows);
verticalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu);
connect(insertRows, SIGNAL(triggered()), this, SLOT(insertRows()));
connect(insertColumns, SIGNAL(triggered()), this, SLOT(insertColumns()));
connect(removeRows, SIGNAL(triggered()), this, SLOT(removeRows()));
connect(removeColumns, SIGNAL(triggered()), this, SLOT(removeColumns()));
QAction * cellProperties = new QAction(tr("Properties..."), this);
setContextMenuPolicy(Qt::ActionsContextMenu);
addAction(cellProperties);
connect(cellProperties, SIGNAL(triggered()), this, SLOT(cellProperties()));
}
void SheetTableView::cellProperties()
{
std::auto_ptr<PropertiesDialog> dialog(new PropertiesDialog(sheet, selectedRanges(), this));
if (dialog->exec() == QDialog::Accepted) {
dialog->apply();
}
}
std::vector<Range> SheetTableView::selectedRanges() const
{
QModelIndexList list = selectionModel()->selectedIndexes();
std::vector<Range> result;
// Insert selected cells into set. This variable should ideally be a hash_set
// but that is not part of standard stl.
std::set<std::pair<int, int> > cells;
for (QModelIndexList::const_iterator it = list.begin(); it != list.end(); ++it)
cells.insert(std::make_pair<int,int>((*it).row(), (*it).column()));
// Create rectangular cells from the unordered collection of selected cells
std::map<std::pair<int, int>, std::pair<int, int> > rectangles;
createRectangles(cells, rectangles);
std::map<std::pair<int, int>, std::pair<int, int> >::const_iterator i = rectangles.begin();
for (; i != rectangles.end(); ++i) {
std::pair<int, int> ul = (*i).first;
std::pair<int, int> size = (*i).second;
result.push_back(Range(ul.first, ul.second,
ul.first + size.first - 1, ul.second + size.second - 1));
}
return result;
}
void SheetTableView::insertRows()
{
assert(sheet != 0);
QModelIndexList rows = selectionModel()->selectedRows();
std::vector<int> sortedRows;
/* Make sure rows are sorted in ascending order */
for (QModelIndexList::const_iterator it = rows.begin(); it != rows.end(); ++it)
sortedRows.push_back(it->row());
std::sort(sortedRows.begin(), sortedRows.end());
/* Insert rows */
Gui::Command::openCommand("Insert rows");
std::vector<int>::const_reverse_iterator it = sortedRows.rbegin();
while (it != sortedRows.rend()) {
int prev = *it;
int count = 1;
/* Collect neighbouring rows into one chunk */
++it;
while (it != sortedRows.rend()) {
if (*it == prev - 1) {
prev = *it;
++count;
++it;
}
else
break;
}
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.insertRows('%s', %d)", sheet->getNameInDocument(),
rowName(prev).c_str(), count);
}
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
void SheetTableView::removeRows()
{
assert(sheet != 0);
QModelIndexList rows = selectionModel()->selectedRows();
std::vector<int> sortedRows;
int extra = 0;
/* Make sure rows are sorted in descending order */
for (QModelIndexList::const_iterator it = rows.begin(); it != rows.end(); ++it)
sortedRows.push_back(it->row());
std::sort(sortedRows.begin(), sortedRows.end(), std::greater<int>());
/* Remove rows */
Gui::Command::openCommand("Remove rows");
for (std::vector<int>::const_iterator it = sortedRows.begin(); it != sortedRows.end(); ++it) {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.removeRows('%s', %d)", sheet->getNameInDocument(),
rowName(*it).c_str(), 1);
}
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
void SheetTableView::insertColumns()
{
assert(sheet != 0);
QModelIndexList cols = selectionModel()->selectedColumns();
std::vector<int> sortedColumns;
/* Make sure rows are sorted in ascending order */
for (QModelIndexList::const_iterator it = cols.begin(); it != cols.end(); ++it)
sortedColumns.push_back(it->column());
std::sort(sortedColumns.begin(), sortedColumns.end());
/* Insert columns */
Gui::Command::openCommand("Insert columns");
std::vector<int>::const_reverse_iterator it = sortedColumns.rbegin();
while (it != sortedColumns.rend()) {
int prev = *it;
int count = 1;
/* Collect neighbouring columns into one chunk */
++it;
while (it != sortedColumns.rend()) {
if (*it == prev - 1) {
prev = *it;
++count;
++it;
}
else
break;
}
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.insertColumns('%s', %d)", sheet->getNameInDocument(),
columnName(prev).c_str(), count);
}
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
void SheetTableView::removeColumns()
{
assert(sheet != 0);
QModelIndexList cols = selectionModel()->selectedColumns();
std::vector<int> sortedColumns;
/* Make sure rows are sorted in descending order */
for (QModelIndexList::const_iterator it = cols.begin(); it != cols.end(); ++it)
sortedColumns.push_back(it->column());
std::sort(sortedColumns.begin(), sortedColumns.end(), std::greater<int>());
/* Remove columns */
Gui::Command::openCommand("Remove rows");
for (std::vector<int>::const_iterator it = sortedColumns.begin(); it != sortedColumns.end(); ++it)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.removeColumns('%s', %d)", sheet->getNameInDocument(),
columnName(*it).c_str(), 1);
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
SheetTableView::~SheetTableView()
{
}
void SheetTableView::updateCellSpan(Spreadsheet::CellAddress address)
{
int rows, cols;
sheet->getSpans(address, rows, cols);
if (rows != rowSpan(address.row(), address.col()) || cols != columnSpan(address.row(), address.col()))
setSpan(address.row(), address.col(), rows, cols);
}
void SheetTableView::setSheet(Sheet * _sheet)
{
sheet = _sheet;
cellSpanChangedConnection = sheet->cellSpanChanged.connect(bind(&SheetTableView::updateCellSpan, this, _1));
// Update row and column spans
std::vector<std::string> usedCells = sheet->getUsedCells();
for (std::vector<std::string>::const_iterator i = usedCells.begin(); i != usedCells.end(); ++i) {
CellAddress address(*i);
if (sheet->isMergedCell(address))
updateCellSpan(address);
}
// Update column widths and row height
std::map<int, int> columWidths = sheet->getColumnWidths();
for (std::map<int, int>::const_iterator i = columWidths.begin(); i != columWidths.end(); ++i) {
int newSize = i->second;
if (newSize > 0 && horizontalHeader()->sectionSize(i->first) != newSize)
setColumnWidth(i->first, newSize);
}
std::map<int, int> rowHeights = sheet->getRowHeights();
for (std::map<int, int>::const_iterator i = rowHeights.begin(); i != rowHeights.end(); ++i) {
int newSize = i->second;
if (newSize > 0 && verticalHeader()->sectionSize(i->first) != newSize)
setRowHeight(i->first, newSize);
}
}
void SheetTableView::commitData ( QWidget * editor )
{
QTableView::commitData(editor);
}
bool SheetTableView::edit ( const QModelIndex & index, EditTrigger trigger, QEvent * event )
{
if (trigger & (QAbstractItemView::DoubleClicked | QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed) )
currentEditIndex = index;
return QTableView::edit(index, trigger, event);
}
void SheetTableView::edit ( const QModelIndex & index )
{
currentEditIndex = index;
QTableView::edit(index);
}
#include "moc_SheetTableView.cpp"

View File

@@ -0,0 +1,76 @@
/***************************************************************************
* 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 SHEETTABLEVIEW_H
#define SHEETTABLEVIEW_H
#include <QTableView>
#include <QHeaderView>
#include <boost/signals/connection.hpp>
#include "PreCompiled.h"
#include <Mod/Spreadsheet/App/Sheet.h>
#include <Mod/Spreadsheet/App/Utils.h>
namespace SpreadsheetGui {
class SheetViewHeader : public QHeaderView {
Q_OBJECT
public:
SheetViewHeader(Qt::Orientation o) : QHeaderView(o) {
setClickable(true);
}
Q_SIGNALS:
void resizeFinished();
protected:
void mouseReleaseEvent(QMouseEvent * event);
};
class SheetTableView : public QTableView
{
Q_OBJECT
public:
explicit SheetTableView(QWidget *parent = 0);
~SheetTableView();
void edit(const QModelIndex &index);
void setSheet(Spreadsheet::Sheet *_sheet);
std::vector<Spreadsheet::Range> selectedRanges() const;
protected Q_SLOTS:
void commitData(QWidget *editor);
void updateCellSpan(Spreadsheet::CellAddress address);
void insertRows();
void removeRows();
void insertColumns();
void removeColumns();
void cellProperties();
protected:
bool edit(const QModelIndex &index, EditTrigger trigger, QEvent *event);
QModelIndex currentEditIndex;
Spreadsheet::Sheet * sheet;
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection cellSpanChangedConnection;
};
}
#endif // SHEETTABLEVIEW_H

View File

@@ -0,0 +1,79 @@
/***************************************************************************
* Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This file is based on the Qt spreadsheet example code. *
* *
* 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.1 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 "SpreadsheetDelegate.h"
#include <QItemDelegate>
#include <QLineEdit>
using namespace SpreadsheetGui;
SpreadsheetDelegate::SpreadsheetDelegate(QWidget *parent) :
QItemDelegate(parent)
{
}
QWidget *SpreadsheetDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &,
const QModelIndex &index) const
{
QLineEdit *editor = new QLineEdit(parent);
connect(editor, SIGNAL(returnPressed()), this, SLOT(commitAndCloseEditor()));
return editor;
}
void SpreadsheetDelegate::commitAndCloseEditor()
{
QLineEdit *editor = qobject_cast<QLineEdit *>(sender());
emit commitData(editor);
emit closeEditor(editor);
}
void SpreadsheetDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
if (edit) {
edit->setText(index.model()->data(index, Qt::EditRole).toString());
return;
}
}
void SpreadsheetDelegate::setModelData(QWidget *editor,
QAbstractItemModel *model, const QModelIndex &index) const
{
QLineEdit *edit = qobject_cast<QLineEdit *>(editor);
if (edit) {
model->setData(index, edit->text());
return;
}
}
QSize SpreadsheetDelegate::sizeHint( const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
return QSize();
}
#include "moc_SpreadsheetDelegate.cpp"

View File

@@ -0,0 +1,51 @@
/***************************************************************************
* Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This file is based on the Qt spreadsheet example code. *
* *
* 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.1 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 SPREADSHEETDELEGATE_H
#define SPREADSHEETDELEGATE_H
#include <QItemDelegate>
namespace SpreadsheetGui {
class SpreadsheetDelegate : public QItemDelegate
{
Q_OBJECT
public:
explicit SpreadsheetDelegate(QWidget *parent = 0);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &,
const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
private Q_SLOTS:
void commitAndCloseEditor();
};
}
#endif // SPREADSHEETDELEGATE_H

View File

@@ -0,0 +1,327 @@
/***************************************************************************
* 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"
#ifndef _PreComp_
# include <QAction>
# include <QApplication>
# include <QMenu>
# include <QMouseEvent>
# include <QSlider>
# include <QStatusBar>
# include <QToolBar>
# include <QTableWidgetItem>
# include <QMessageBox>
# include <QPalette>
# include <cmath>
#endif
#include "SpreadsheetView.h"
#include "SpreadsheetDelegate.h"
#include <Mod/Spreadsheet/App/Expression.h>
#include <Mod/Spreadsheet/App/Sheet.h>
#include <Mod/Spreadsheet/App/Range.h>
#include <Gui/MainWindow.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <App/DocumentObject.h>
#include <App/PropertyStandard.h>
#include <Gui/Command.h>
#include <boost/bind.hpp>
#include <Mod/Spreadsheet/App/Utils.h>
#include "qtcolorpicker.h"
#include "ui_Sheet.h"
using namespace SpreadsheetGui;
using namespace Spreadsheet;
using namespace Gui;
/* TRANSLATOR SpreadsheetGui::SheetView */
TYPESYSTEM_SOURCE_ABSTRACT(SpreadsheetGui::SheetView, Gui::MDIView);
SheetView::SheetView(Gui::Document *pcDocument, App::DocumentObject *docObj, QWidget *parent)
: MDIView(pcDocument, parent)
, sheet(static_cast<Sheet*>(docObj))
{
// Set up ui
model = new SheetModel(static_cast<Sheet*>(docObj));
ui = new Ui::Sheet();
QWidget * w = new QWidget(this);
ui->setupUi(w);
setCentralWidget(w);
delegate = new SpreadsheetDelegate();
ui->cells->setModel(model);
ui->cells->setItemDelegate(delegate);
ui->cells->setSheet(sheet);
// Connect signals
connect(ui->cells->selectionModel(), SIGNAL( currentChanged( QModelIndex, QModelIndex ) ),
this, SLOT( currentChanged( QModelIndex, QModelIndex ) ) );
connect(ui->cells->horizontalHeader(), SIGNAL(resizeFinished()),
this, SLOT(columnResizeFinished()));
connect(ui->cells->horizontalHeader(), SIGNAL(sectionResized ( int, int, int ) ),
this, SLOT(columnResized(int, int, int)));
connect(ui->cells->verticalHeader(), SIGNAL(resizeFinished()),
this, SLOT(rowResizeFinished()));
connect(ui->cells->verticalHeader(), SIGNAL(sectionResized ( int, int, int ) ),
this, SLOT(rowResized(int, int, int)));
connect(ui->cellContent, SIGNAL(returnPressed()), this, SLOT( editingFinished() ));
columnWidthChangedConnection = sheet->columnWidthChanged.connect(bind(&SheetView::resizeColumn, this, _1, _2));
rowHeightChangedConnection = sheet->rowHeightChanged.connect(bind(&SheetView::resizeRow, this, _1, _2));
positionChangedConnection = sheet->positionChanged.connect(bind(&SheetView::setPosition, this, _1));
QPalette palette = ui->cells->palette();
palette.setColor(QPalette::Base, QColor(255, 255, 255));
palette.setColor(QPalette::Text, QColor(0, 0, 0));
ui->cells->setPalette(palette);
QList<QtColorPicker*> bgList = Gui::getMainWindow()->findChildren<QtColorPicker*>(QString::fromAscii("Spreadsheet_BackgroundColor"));
if (bgList.size() > 0)
bgList[0]->setCurrentColor(palette.color(QPalette::Base));
QList<QtColorPicker*> fgList = Gui::getMainWindow()->findChildren<QtColorPicker*>(QString::fromAscii("Spreadsheet_ForegroundColor"));
if (fgList.size() > 0)
fgList[0]->setCurrentColor(palette.color(QPalette::Text));
}
SheetView::~SheetView()
{
Application::Instance->detachView(this);
//delete delegate;
}
bool SheetView::onMsg(const char *pMsg, const char **ppReturn)
{
if(strcmp("Undo",pMsg) == 0 ) {
getGuiDocument()->undo(1);
App::Document* doc = getAppDocument();
if (doc)
doc->recomputeFeature(sheet);
return true;
}
else if(strcmp("Redo",pMsg) == 0 ) {
getGuiDocument()->redo(1);
App::Document* doc = getAppDocument();
if (doc)
doc->recomputeFeature(sheet);
return true;
}
else if (strcmp("Save",pMsg) == 0) {
getGuiDocument()->save();
return true;
}
else if (strcmp("SaveAs",pMsg) == 0) {
getGuiDocument()->saveAs();
return true;
}
else
return false;
}
bool SheetView::onHasMsg(const char *pMsg) const
{
if (strcmp("Undo",pMsg) == 0) {
App::Document* doc = getAppDocument();
return doc && doc->getAvailableUndos() > 0;
}
else if (strcmp("Redo",pMsg) == 0) {
App::Document* doc = getAppDocument();
return doc && doc->getAvailableRedos() > 0;
}
else if (strcmp("Save",pMsg) == 0)
return true;
else if (strcmp("SaveAs",pMsg) == 0)
return true;
else
return false;
}
void SheetView::setCurrentCell(QString str)
{
updateContentLine();
}
void SheetView::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Delete) {
if (event->modifiers() == 0) {
//model()->setData(currentIndex(), QVariant(), Qt::EditRole);
}
else if (event->modifiers() == Qt::ControlModifier) {
//model()->setData(currentIndex(), QVariant(), Qt::EditRole);
}
}
else
Gui::MDIView::keyPressEvent(event);
}
void SheetView::updateContentLine()
{
QModelIndex i = ui->cells->currentIndex();
if (i.isValid()) {
std::string str;
Cell * cell = sheet->getCell(CellAddress(i.row(), i.column()));
if (cell)
cell->getStringContent(str);
ui->cellContent->setText(QString::fromUtf8(str.c_str()));
ui->cellContent->setEnabled(true);
}
}
void SheetView::columnResizeFinished()
{
if (newColumnSizes.size() == 0)
return;
blockSignals(true);
Gui::Command::openCommand("Resize column");
QMap<int, int>::const_iterator i = newColumnSizes.begin();
while (i != newColumnSizes.end()) {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setColumnWidth('%s', %d)", sheet->getNameInDocument(),
columnName(i.key()).c_str(), i.value());
++i;
}
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
blockSignals(false);
newColumnSizes.clear();
}
void SheetView::rowResizeFinished()
{
if (newRowSizes.size() == 0)
return;
blockSignals(true);
Gui::Command::openCommand("Resize row");
QMap<int, int>::const_iterator i = newRowSizes.begin();
while (i != newRowSizes.end()) {
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setRowHeight('%s', %d)", sheet->getNameInDocument(),
rowName(i.key()).c_str(), i.value());
++i;
}
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
blockSignals(false);
newRowSizes.clear();
}
void SheetView::columnResized(int col, int oldSize, int newSize)
{
newColumnSizes[col] = newSize;
}
void SheetView::rowResized(int row, int oldSize, int newSize)
{
newRowSizes[row] = newSize;
}
void SheetView::resizeColumn(int col, int newSize)
{
if (ui->cells->horizontalHeader()->sectionSize(col) != newSize)
ui->cells->setColumnWidth(col, newSize);
}
void SheetView::setPosition(CellAddress address)
{
QModelIndex curr = ui->cells->currentIndex();
QModelIndex i = ui->cells->model()->index(address.row(), address.col());
if (i.isValid() && (curr.row() != address.row() || curr.column() != address.col())) {
ui->cells->clearSelection();
ui->cells->setCurrentIndex(i);
}
}
void SheetView::resizeRow(int col, int newSize)
{
if (ui->cells->verticalHeader()->sectionSize(col) != newSize)
ui->cells->setRowHeight(col, newSize);
}
void SheetView::editingFinished()
{
QModelIndex i = ui->cells->currentIndex();
// Update data in cell
ui->cells->model()->setData(i, QVariant(ui->cellContent->text()), Qt::EditRole);
}
void SheetView::currentChanged ( const QModelIndex & current, const QModelIndex & previous )
{
updateContentLine();
sheet->setPosition(CellAddress(current.row(), current.column()));
}
void SheetView::updateCell(const App::Property *prop)
{
try {
CellAddress address;
sheet->getCellAddress(prop, address);
updateContentLine();
}
catch (...) {
// Property is not a cell
return;
}
}
std::vector<Range> SheetView::selectedRanges() const
{
return ui->cells->selectedRanges();
}
QModelIndexList SheetView::selectedIndexes() const
{
return ui->cells->selectionModel()->selectedIndexes();
}
QModelIndex SheetView::currentIndex() const
{
return ui->cells->currentIndex();
}
PyObject *SheetView::getPyObject()
{
Py_Return;
}
void SheetView::deleteSelf()
{
Gui::MDIView::deleteSelf();
}
#include "moc_SpreadsheetView.cpp"

View File

@@ -0,0 +1,111 @@
/***************************************************************************
* 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 SpreadsheetView_H
#define SpreadsheetView_H
#include <Gui/MDIView.h>
#include <QHeaderView>
#include "SheetModel.h"
#include <Mod/Spreadsheet/App/Sheet.h>
class QSlider;
class QAction;
class QActionGroup;
class QPopupMenu;
class QToolBar;
namespace App {
class DocumentObject;
class Property;
}
namespace Ui {
class Sheet;
}
class QTableWidgetItem;
namespace SpreadsheetGui
{
class SpreadsheetDelegate;
class SpreadsheetGuiExport SheetView : public Gui::MDIView
{
Q_OBJECT
TYPESYSTEM_HEADER();
public:
SheetView(Gui::Document* pcDocument, App::DocumentObject* docObj, QWidget* parent);
~SheetView();
const char *getName(void) const {return "SheetView";}
bool onMsg(const char* pMsg,const char** ppReturn);
bool onHasMsg(const char* pMsg) const;
void updateCell(const App::Property * prop);
Spreadsheet::Sheet * getSheet() { return sheet; }
std::vector<Spreadsheet::Range> selectedRanges() const;
QModelIndexList selectedIndexes() const;
QModelIndex currentIndex() const;
PyObject *getPyObject(void);
virtual void deleteSelf();
protected Q_SLOTS:
void editingFinished();
void currentChanged( const QModelIndex & current, const QModelIndex & previous );
void columnResized(int col, int oldSize, int newSize);
void rowResized(int row, int oldSize, int newSize);
void columnResizeFinished();
void rowResizeFinished();
protected:
void setPosition(Spreadsheet::CellAddress address);
void updateContentLine();
void setCurrentCell(QString str);
void keyPressEvent(QKeyEvent *event);
void resizeColumn(int col, int newSize);
void resizeRow(int col, int newSize);
Ui::Sheet * ui;
Spreadsheet::Sheet * sheet;
SpreadsheetDelegate * delegate;
SheetModel * model;
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection columnWidthChangedConnection;
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection rowHeightChangedConnection;
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection positionChangedConnection;
QMap<int, int> newColumnSizes;
QMap<int, int> newRowSizes;
};
} // namespace SpreadsheetModGui
#endif // SpreadsheetView_H

View File

@@ -0,0 +1,193 @@
/***************************************************************************
* Copyright (c) 2011 Jrgen Riegel (juergen.riegel@web.de) *
* Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) *
* *
* 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"
#ifndef _PreComp_
# include <QFile>
# include <QFileInfo>
# include <QImage>
# include <QString>
# include <QMenu>
#endif
#include "ViewProviderSpreadsheet.h"
#include "SpreadsheetView.h"
#include <Mod/Spreadsheet/App/Sheet.h>
#include <App/Document.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Application.h>
#include <Gui/MainWindow.h>
#include <Gui/Command.h>
#include <Base/FileInfo.h>
#include <Base/Stream.h>
#include <Base/Console.h>
#include <sstream>
using namespace Gui;
using namespace SpreadsheetGui;
using namespace Spreadsheet;
PROPERTY_SOURCE(SpreadsheetGui::ViewProviderSheet, Gui::ViewProviderDocumentObject)
ViewProviderSheet::ViewProviderSheet()
: Gui::ViewProviderDocumentObject()
{
}
ViewProviderSheet::~ViewProviderSheet()
{
if (!view.isNull()) {
Gui::getMainWindow()->removeWindow(view);
// delete view;
}
}
void ViewProviderSheet::setDisplayMode(const char* ModeName)
{
ViewProviderDocumentObject::setDisplayMode(ModeName);
}
std::vector<std::string> ViewProviderSheet::getDisplayModes(void) const
{
std::vector<std::string> StrList;
StrList.push_back("Spreadsheet");
return StrList;
}
QIcon ViewProviderSheet::getIcon() const
{
static const char * const Points_Feature_xpm[] = {
"16 16 3 1",
" c None",
". c #000000",
"+ c #FFFFFF",
" ",
" ",
"................",
".++++.++++.++++.",
".++++.++++.++++.",
"................",
".++++.++++.++++.",
".++++.++++.++++.",
"................",
".++++.++++.++++.",
".++++.++++.++++.",
"................",
".++++.++++.++++.",
".++++.++++.++++.",
"................",
" "};
QPixmap px(Points_Feature_xpm);
return px;
}
bool ViewProviderSheet::setEdit(int ModNum)
{
if (ModNum == ViewProvider::Default) {
if (!this->view) {
showSpreadsheetView();
view->viewAll();
}
Gui::getMainWindow()->setActiveWindow(this->view);
return false;
}
return false;
}
bool ViewProviderSheet::doubleClicked()
{
if (!this->view) {
showSpreadsheetView();
view->viewAll();
}
Gui::getMainWindow()->setActiveWindow(this->view);
return true;
}
void ViewProviderSheet::setupContextMenu(QMenu * menu, QObject *receiver, const char *member)
{
QAction* act;
act = menu->addAction(QObject::tr("Show spreadsheet"), receiver, member);
act->setData(QVariant((int)ViewProvider::Default));
}
Sheet *ViewProviderSheet::getSpreadsheetObject() const
{
return freecad_dynamic_cast<Sheet>(pcObject);
}
bool ViewProviderSheet::onDelete(const std::vector<std::string> &)
{
// If view is closed, delete the object
if (view.isNull())
return true;
// View is not closed, delete cell contents instead if it is active
if (Gui::Application::Instance->activeDocument()) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
QModelIndexList selection = sheetView->selectedIndexes();
if (selection.size() > 0) {
Gui::Command::openCommand("Clear cell(s)");
for (QModelIndexList::const_iterator it = selection.begin(); it != selection.end(); ++it) {
std::string address = Spreadsheet::addressToString(CellAddress((*it).row(), (*it).column()));
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.clear('%s')", sheet->getNameInDocument(),
address.c_str());
}
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
return false;
}
SheetView *ViewProviderSheet::showSpreadsheetView()
{
if (!view){
Gui::Document* doc = Gui::Application::Instance->getDocument
(this->pcObject->getDocument());
view = new SheetView(doc, this->pcObject, Gui::getMainWindow());
view->setWindowIcon(Gui::BitmapFactory().pixmap(":icons/Spreadsheet.svg"));
view->setWindowTitle(QString::fromUtf8(pcObject->Label.getValue()) + QString::fromAscii("[*]"));
Gui::getMainWindow()->addWindow(view);
startEditing();
}
return view;
}
void ViewProviderSheet::updateData(const App::Property* prop)
{
if (view)
view->updateCell(prop);
}

View File

@@ -0,0 +1,78 @@
/***************************************************************************
* Copyright (c) 2011 Jrgen Riegel (juergen.riegel@web.de) *
* Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) *
* *
* 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_ViewProviderImagePlane_H
#define SPREADSHEET_ViewProviderImagePlane_H
#include <Gui/ViewProviderDocumentObject.h>
#include <QPointer>
namespace Spreadsheet {
class Sheet;
}
namespace SpreadsheetGui
{
class SheetView;
class SpreadsheetGuiExport ViewProviderSheet : public Gui::ViewProviderDocumentObject
{
PROPERTY_HEADER(SpreadsheetGui::ViewProviderSheet);
public:
/// constructor.
ViewProviderSheet();
/// destructor.
~ViewProviderSheet();
void setDisplayMode(const char* ModeName);
virtual bool useNewSelectionModel(void) const {return false;}
std::vector<std::string> getDisplayModes() const;
virtual bool doubleClicked(void);
void setupContextMenu(QMenu* menu, QObject* receiver, const char* member);
Spreadsheet::Sheet* getSpreadsheetObject() const;
virtual bool onDelete(const std::vector<std::string> &);
QIcon getIcon() const;
virtual bool setEdit(int ModNum);
virtual bool isShow(void) const { return true; }
protected:
SheetView* showSpreadsheetView();
void updateData(const App::Property *prop);
private:
QPointer<SheetView> view;
};
} //namespace Spreadsheet
#endif // SPREADSHEET_ViewProviderSpreadsheet_H

View File

@@ -0,0 +1,240 @@
/***************************************************************************
* Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net> *
* Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) *
* *
* 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"
#ifndef _PreComp_
# include <qobject.h>
#endif
#include "Workbench.h"
#include <Gui/ToolBarManager.h>
#include <Gui/MenuManager.h>
#include <Gui/Application.h>
#include <Gui/MainWindow.h>
#include <Gui/Command.h>
#include <QToolBar>
#include "qtcolorpicker.h"
#include "Mod/Spreadsheet/App/Sheet.h"
#include "Mod/Spreadsheet/App/Range.h"
#include "Mod/Spreadsheet/Gui/SpreadsheetView.h"
using namespace SpreadsheetGui;
using namespace Spreadsheet;
#if 0 // needed for Qt's lupdate utility
qApp->translate("Workbench", "Spreadsheet");
#endif
/// @namespace ImageGui @class Workbench
TYPESYSTEM_SOURCE(SpreadsheetGui::Workbench, Gui::StdWorkbench)
Workbench::Workbench()
: Gui::StdWorkbench()
, initialized(false)
, workbenchHelper(new WorkbenchHelper)
{
}
Workbench::~Workbench()
{
}
void Workbench::activated()
{
if (!initialized) {
QList<QToolBar*> bars = Gui::getMainWindow()->findChildren<QToolBar*>(QString::fromAscii("Spreadsheet"));
if (bars.size() == 1) {
QToolBar * bar = bars[0];
QtColorPicker * foregroundColor;
QtColorPicker * backgroundColor;
QPalette palette = Gui::getMainWindow()->palette();
QList<QtColorPicker*> fgList = Gui::getMainWindow()->findChildren<QtColorPicker*>(QString::fromAscii("Spreadsheet_ForegroundColor"));
if (fgList.size() > 0)
foregroundColor = fgList[0];
else {
foregroundColor = new QtColorPicker();
foregroundColor->setObjectName(QString::fromAscii("Spreadsheet_ForegroundColor"));
foregroundColor->setStandardColors();
foregroundColor->setCurrentColor(palette.color(QPalette::Foreground));
QObject::connect(foregroundColor, SIGNAL(colorSet(QColor)), workbenchHelper.get(), SLOT(setForegroundColor(QColor)));
}
bar->addWidget(foregroundColor);
QList<QtColorPicker*> bgList = Gui::getMainWindow()->findChildren<QtColorPicker*>(QString::fromAscii("Spreadsheet_BackgroundColor"));
if (bgList.size() > 0)
backgroundColor = bgList[0];
else {
backgroundColor = new QtColorPicker();
backgroundColor->setObjectName(QString::fromAscii("Spreadsheet_BackgroundColor"));
backgroundColor->setStandardColors();
backgroundColor->setCurrentColor(palette.color(QPalette::Base));
QObject::connect(backgroundColor, SIGNAL(colorSet(QColor)), workbenchHelper.get(), SLOT(setBackgroundColor(QColor)));
}
bar->addWidget(backgroundColor);
initialized = false;
}
}
}
void WorkbenchHelper::setForegroundColor(const QColor & color)
{
Gui::Document * doc = Gui::Application::Instance->activeDocument();
if (doc) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
std::vector<Range> ranges = sheetView->selectedRanges();
// Execute mergeCells commands
if (ranges.size() > 0) {
std::vector<Range>::const_iterator i = ranges.begin();
Gui::Command::openCommand("Set foreground color");
for (; i != ranges.end(); ++i)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setForeground('%s', (%f,%f,%f))", sheet->getNameInDocument(),
i->rangeString().c_str(), color.redF(), color.greenF(), color.blueF());
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
void WorkbenchHelper::setBackgroundColor(const QColor & color)
{
Gui::Document * doc = Gui::Application::Instance->activeDocument();
if (doc) {
Gui::MDIView* activeWindow = Gui::getMainWindow()->activeWindow();
SpreadsheetGui::SheetView * sheetView = freecad_dynamic_cast<SpreadsheetGui::SheetView>(activeWindow);
if (sheetView) {
Sheet * sheet = sheetView->getSheet();
std::vector<Range> ranges = sheetView->selectedRanges();
// Execute mergeCells commands
if (ranges.size() > 0) {
std::vector<Range>::const_iterator i = ranges.begin();
Gui::Command::openCommand("Set background color");
for (; i != ranges.end(); ++i)
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setBackground('%s', (%f,%f,%f))", sheet->getNameInDocument(),
i->rangeString().c_str(), color.redF(), color.greenF(), color.blueF());
Gui::Command::commitCommand();
Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()");
}
}
}
}
Gui::MenuItem *Workbench::setupMenuBar() const
{
Gui::MenuItem* root = StdWorkbench::setupMenuBar();
Gui::MenuItem* item = root->findItem("&Windows");
Gui::MenuItem* spreadsheet = new Gui::MenuItem;
root->insertItem(item, spreadsheet);
// utilities
Gui::MenuItem* alignments = new Gui::MenuItem;
alignments->setCommand("&Alignment");
*alignments
<< "Spreadsheet_AlignLeft"
<< "Spreadsheet_AlignCenter"
<< "Spreadsheet_AlignRight"
<< "Spreadsheet_AlignTop"
<< "Spreadsheet_AlignVCenter"
<< "Spreadsheet_AlignBottom"
;
Gui::MenuItem* styles = new Gui::MenuItem;
styles->setCommand("&Styles");
*styles
<< "Spreadsheet_StyleBold"
<< "Spreadsheet_StyleItalic"
<< "Spreadsheet_StyleUnderline"
;
spreadsheet->setCommand("&Spreadsheet");
*spreadsheet << "Spreadsheet_CreateSheet"
<< "Separator"
<< "Spreadsheet_Import"
<< "Spreadsheet_Export"
<< "Separator"
<< "Spreadsheet_MergeCells"
<< "Spreadsheet_SplitCell"
<< "Separator"
<< alignments
<< styles
;
return root;
}
Gui::ToolBarItem* Workbench::setupToolBars() const
{
Gui::ToolBarItem* root = StdWorkbench::setupToolBars();
Gui::ToolBarItem* part = new Gui::ToolBarItem(root);
part->setCommand("Spreadsheet");
*part << "Spreadsheet_CreateSheet"
<< "Separator"
<< "Spreadsheet_Import"
<< "Spreadsheet_Export"
<< "Separator"
<< "Spreadsheet_MergeCells"
<< "Spreadsheet_SplitCell"
<< "Separator"
<< "Spreadsheet_AlignLeft"
<< "Spreadsheet_AlignCenter"
<< "Spreadsheet_AlignRight"
<< "Spreadsheet_AlignTop"
<< "Spreadsheet_AlignVCenter"
<< "Spreadsheet_AlignBottom"
<< "Separator"
<< "Spreadsheet_StyleBold"
<< "Spreadsheet_StyleItalic"
<< "Spreadsheet_StyleUnderline"
<< "Separator"
;
return root;
}
Gui::ToolBarItem* Workbench::setupCommandBars() const
{
Gui::ToolBarItem* root = new Gui::ToolBarItem;
Gui::ToolBarItem* ss = new Gui::ToolBarItem(root);
ss->setCommand("Spreadsheet");
*ss << "Spreadsheet_Open";
return root;
}
#include "moc_Workbench.cpp"

View File

@@ -0,0 +1,68 @@
/***************************************************************************
* Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net> *
* Copyright (c) 2015 Eivind Kvedalen (eivind@kvedalen.name) *
* *
* 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_WORKBENCH_H
#define SPREADSHEET_WORKBENCH_H
#include <Gui/Workbench.h>
class QtColorPicker;
namespace SpreadsheetGui {
/**
* @author Eivind Kvedalen
*/
class SpreadsheetGuiExport WorkbenchHelper : public QObject
{
Q_OBJECT
protected Q_SLOTS:
void setForegroundColor(const QColor &color);
void setBackgroundColor(const QColor &color);
};
class SpreadsheetGuiExport Workbench : public Gui::StdWorkbench
{
TYPESYSTEM_HEADER();
public:
Workbench();
virtual ~Workbench();
void activated();
private:
bool initialized;
std::auto_ptr<WorkbenchHelper> workbenchHelper;
protected:
Gui::MenuItem *setupMenuBar() const;
Gui::ToolBarItem* setupToolBars() const;
Gui::ToolBarItem* setupCommandBars() const;
};
} // namespace SpreadsheetModGui
#endif // SPREADSHEET_WORKBENCH_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,122 @@
/****************************************************************************
**
** This file is part of a Qt Solutions component.
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Solutions Commercial License Agreement provided
** with the Software or, alternatively, in accordance with the terms
** contained in a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** Please note Third Party Software included with Qt Solutions may impose
** additional restrictions and it is the user's responsibility to ensure
** that they have met the licensing requirements of the GPL, LGPL, or Qt
** Solutions Commercial license and the relevant license of the Third
** Party Software they are using.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
****************************************************************************/
#ifndef QTCOLORPICKER_H
#define QTCOLORPICKER_H
#include <QtGui/QPushButton>
#include <QtCore/QString>
#include <QtGui/QColor>
#include <QtGui/QLabel>
#include <QtCore/QEvent>
#include <QtGui/QFocusEvent>
#if defined(Q_WS_WIN)
# if !defined(QT_QTCOLORPICKER_EXPORT) && !defined(QT_QTCOLORPICKER_IMPORT)
# define QT_QTCOLORPICKER_EXPORT
# elif defined(QT_QTCOLORPICKER_IMPORT)
# if defined(QT_QTCOLORPICKER_EXPORT)
# undef QT_QTCOLORPICKER_EXPORT
# endif
# define QT_QTCOLORPICKER_EXPORT __declspec(dllimport)
# elif defined(QT_QTCOLORPICKER_EXPORT)
# undef QT_QTCOLORPICKER_EXPORT
# define QT_QTCOLORPICKER_EXPORT __declspec(dllexport)
# endif
#else
# define QT_QTCOLORPICKER_EXPORT
#endif
class ColorPickerPopup;
class QT_QTCOLORPICKER_EXPORT QtColorPicker : public QPushButton
{
Q_OBJECT
Q_PROPERTY(bool colorDialog READ colorDialogEnabled WRITE setColorDialogEnabled)
public:
QtColorPicker(QWidget *parent = 0,
int columns = -1, bool enableColorDialog = true);
~QtColorPicker();
void insertColor(const QColor &color, const QString &text = QString::null, int index = -1);
QColor currentColor() const;
QColor color(int index) const;
void setColorDialogEnabled(bool enabled);
bool colorDialogEnabled() const;
void setStandardColors();
static QColor getColor(const QPoint &pos, bool allowCustomColors = true);
public Q_SLOTS:
void setCurrentColor(const QColor &col);
Q_SIGNALS:
void colorChanged(const QColor &);
void colorSet(const QColor &);
protected:
void paintEvent(QPaintEvent *e);
private Q_SLOTS:
void buttonPressed(bool toggled);
void popupClosed();
private:
ColorPickerPopup *popup;
QColor col;
bool withColorDialog;
bool dirty;
bool firstInserted;
};
#endif

View File

@@ -1,26 +1,41 @@
#***************************************************************************
#* *
#* Copyright (c) 2013 - Yorik van Havre <yorik@uncreated.net> *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* 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 Library General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with this program; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
# Supported file types
FreeCAD.addImportType("Spreadsheet (*.csv)","Spreadsheet")
FreeCAD.addExportType("Spreadsheet (*.csv)","Spreadsheet")
# FreeCAD init script of the Spreadsheet module
# (c) 2001 Juergen Riegel
#***************************************************************************
#* (c) Juergen Riegel (juergen.riegel@web.de) 2002 *
#* Copyright (c) 2013 - Yorik van Havre <yorik@uncreated.net> *
#* Copyright (c) 2013 Eivind Kvedalen (eivind@kvedalen.name) *
#* *
#* This file is part of the FreeCAD CAx development system. *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* FreeCAD 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 Lesser General Public License for more details. *
#* *
#* You should have received a copy of the GNU Library General Public *
#* License along with FreeCAD; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#* Juergen Riegel 2002 *
#***************************************************************************/
# Get the Parameter Group of this module
ParGrp = App.ParamGet("System parameter:Modules").GetGroup("Spreadsheet")
# Set the needed information
ParGrp.SetString("HelpIndex", "Spreadsheet/Help/index.html")
ParGrp.SetString("WorkBenchName", "Spreadsheet")
ParGrp.SetString("WorkBenchModule", "SpreadsheetWorkbench.py")

View File

@@ -1,76 +1,74 @@
# Spreadsheet gui init module
# (c) 2003 Juergen Riegel
#
# Gathering all the information to start FreeCAD
# This is the second one of three init scripts, the third one
# runs when the gui is up
#***************************************************************************
#* (c) Juergen Riegel (juergen.riegel@web.de) 2002 *
#* Copyright (c) 2013 Eivind Kvedalen (eivind@kvedalen.name) *
#* *
#* Copyright (c) 2013 - Yorik van Havre <yorik@uncreated.net> *
#* This file is part of the FreeCAD CAx development system. *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* it under the terms of the GNU Lesser General Public License (LGPL) *
#* it under the terms of the GNU General Public License (GPL) *
#* as published by the Free Software Foundation; either version 2 of *
#* the License, or (at your option) any later version. *
#* for detail see the LICENCE text file. *
#* *
#* This program is distributed in the hope that it will be useful, *
#* FreeCAD 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 program; if not, write to the Free Software *
#* License along with FreeCAD; if not, write to the Free Software *
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
#* USA *
#* *
#***************************************************************************
class SpreadsheetWorkbench(Workbench):
"Spreadsheet workbench object"
Icon = """
/* XPM */
static char * Spreadsheet_xpm[] = {
"16 16 5 1",
" c None",
". c #151614",
"+ c #575956",
"@ c #969895",
"# c #F7F9F6",
" ",
" ",
" ...............",
".@##@+########@.",
".+@@+.@@@@@@@@+.",
"..+++.+++++++++.",
".@##@+########@.",
".+@@+.@@@@@@@@+.",
"..+++.+++++++++.",
".@##@+########@.",
".+@@+.@@@@@@@@+.",
"..+++.+++++++++.",
".@##@+########@.",
"..+++.+++++++++.",
" ",
" "};"""
MenuText = "Spreadsheet"
ToolTip = "Spreadsheet workbench"
def Initialize(self):
def QT_TRANSLATE_NOOP(scope, text): return text
import Spreadsheet,Spreadsheet_rc
from DraftTools import translate
commands = ["Spreadsheet_Create","Spreadsheet_Controller","Spreadsheet_PropertyController"]
self.appendToolbar(QT_TRANSLATE_NOOP("Workbench","Spreadsheet tools"),commands)
self.appendMenu(str(translate("Spreadsheet","&Spreadsheet")),commands)
FreeCADGui.addIconPath(":/icons")
FreeCADGui.addLanguagePath(":/translations")
Log ('Loading Spreadsheet module... done\n')
def Activated(self):
Msg("Spreadsheet workbench activated\n")
def Deactivated(self):
Msg("Spreadsheet workbench deactivated\n")
def GetClassName(self):
return "Gui::PythonWorkbench"
FreeCADGui.addWorkbench(SpreadsheetWorkbench)
#* Juergen Riegel 2002 *
#***************************************************************************/
class SpreadsheetWorkbench ( Workbench ):
"Spreadsheet workbench object"
Icon = """
/* XPM */
static char * Spreadsheet_xpm[] = {
"16 16 5 1",
" c None",
". c #151614",
"+ c #575956",
"@ c #969895",
"# c #F7F9F6",
" ",
" ",
" ...............",
".@##@+########@.",
".+@@+.@@@@@@@@+.",
"..+++.+++++++++.",
".@##@+########@.",
".+@@+.@@@@@@@@+.",
"..+++.+++++++++.",
".@##@+########@.",
".+@@+.@@@@@@@@+.",
"..+++.+++++++++.",
".@##@+########@.",
"..+++.+++++++++.",
" ",
" "};"""
MenuText = "Spreadsheet"
ToolTip = "Spreadsheet workbench"
def Initialize(self):
# load the module
import SpreadsheetGui
def GetClassName(self):
return "SpreadsheetGui::Workbench"
Gui.addWorkbench(SpreadsheetWorkbench())
# Append the open handler
FreeCAD.EndingAdd("Spreadsheet formats (*.csv)","SpreadsheetGui")

View File

@@ -1,7 +0,0 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>icons/Spreadsheet.svg</file>
<file>icons/SpreadsheetController.svg</file>
<file>icons/SpreadsheetPropertyController.svg</file>
</qresource>
</RCC>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
/** \defgroup IMAGE Image
* \ingroup WORKBENCHES */