Fix StartCell/EndCell handling

- multi-character Columns and multi-digit Rows
  were not being interpreted correctly.
This commit is contained in:
wandererfan
2018-12-21 19:34:47 -05:00
committed by Yorik van Havre
parent 754dd89d42
commit 49c6a679af
2 changed files with 93 additions and 59 deletions

View File

@@ -69,7 +69,6 @@ DrawViewSpreadsheet::DrawViewSpreadsheet(void)
ADD_PROPERTY_TYPE(TextColor,(0.0f,0.0f,0.0f),vgroup,App::Prop_None,"The default color of the text and lines");
ADD_PROPERTY_TYPE(TextSize,(12.0),vgroup,App::Prop_None,"The size of the text");
ADD_PROPERTY_TYPE(LineWidth,(0.35),vgroup,App::Prop_None,"The thickness of the cell lines");
//ADD_PROPERTY_TYPE(Symbol,(""),vgroup,App::Prop_Hidden,"The SVG image of this spreadsheet");
EditableTexts.setStatus(App::Property::Hidden,true);
@@ -79,24 +78,26 @@ DrawViewSpreadsheet::~DrawViewSpreadsheet()
{
}
short DrawViewSpreadsheet::mustExecute() const
{
short result = 0;
if (!isRestoring()) {
result = (Source.isTouched() ||
CellStart.isTouched() ||
CellEnd.isTouched() ||
Font.isTouched() ||
TextSize.isTouched() ||
TextColor.isTouched() ||
LineWidth.isTouched() );
}
if (result) {
return result;
}
return TechDraw::DrawView::mustExecute();
}
void DrawViewSpreadsheet::onChanged(const App::Property* prop)
{
if (!isRestoring()) {
if (prop == &Source ||
prop == &CellStart ||
prop == &CellEnd ||
prop == &Font ||
prop == &TextSize ||
prop == &TextColor ||
prop == &LineWidth) {
try {
App::DocumentObjectExecReturn *ret = recompute();
delete ret;
}
catch (...) {
}
}
}
TechDraw::DrawView::onChanged(prop);
}
@@ -114,7 +115,6 @@ App::DocumentObjectExecReturn *DrawViewSpreadsheet::execute(void)
Symbol.setValue(getSheetImage());
requestPaint();
return TechDraw::DrawView::execute();
}
@@ -123,13 +123,13 @@ std::vector<std::string> DrawViewSpreadsheet::getAvailColumns(void)
// build a list of available columns: A, B, C, ... AA, AB, ... ZY, ZZ.
std::string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::vector<std::string> availcolumns;
for (int i=0; i<26; ++i) {
for (int i=0; i<26; ++i) { //A:Z
std::stringstream s;
s << alphabet[i];
availcolumns.push_back(s.str());
}
for (int i=0; i<26; ++i) {
for (int j=0; i<26; ++i) {
for (int i=0; i<26; ++i) { //AA:ZZ
for (int j=0; j<26; ++j) {
std::stringstream s;
s << alphabet[i] << alphabet[j];
availcolumns.push_back(s.str());
@@ -138,7 +138,6 @@ std::vector<std::string> DrawViewSpreadsheet::getAvailColumns(void)
return availcolumns;
}
//note: newlines need to be double escaped for python, but single for C++
std::string DrawViewSpreadsheet::getSVGHead(void)
{
std::string head = std::string("<svg\n") +
@@ -166,49 +165,68 @@ std::string DrawViewSpreadsheet::getSheetImage(void)
// build rows range and columns range
std::vector<std::string> columns;
std::vector<int> rows;
try {
for (unsigned int i=0; i<scellstart.length(); ++i) {
if (isdigit(scellstart[i])) {
columns.push_back(scellstart.substr(0,i));
rows.push_back(std::atoi(scellstart.substr(i,scellstart.length()-1).c_str()));
}
//break startcell into row & column parts
//Note: could do this with regex ([A-Z]*)([0-9]*)
std::string startCol;
int startRow = -1;
for (unsigned int i=0; i<scellstart.length(); ++i) {
if (isdigit(scellstart[i])) {
startCol = scellstart.substr(0,i);
startRow = std::atoi(scellstart.substr(i,scellstart.length()-1).c_str());
break; //first digit is enough
}
for (unsigned int i=0; i<scellend.length(); ++i) {
if (isdigit(scellend[i])) {
std::string startcol = columns.back();
std::string endcol = scellend.substr(0,i);
bool valid = false;
for (std::vector<std::string>::const_iterator j = availcolumns.begin(); j != availcolumns.end(); ++j) {
if ( (*j) == startcol) {
if ( (*j) != endcol) {
valid = true;
}
} else {
if (valid) {
if ( (*j) == endcol) {
columns.push_back((*j));
valid = false;
} else {
columns.push_back((*j));
}
}
}
}
int endrow = std::atoi(scellend.substr(i,scellend.length()-1).c_str());
for (int j=rows.back()+1; j<=endrow; ++j) {
rows.push_back(j);
}
}
// after the first digit there will be no letter any more
break;
}
//validate startCol in A:ZZ
int iStart = colInList(availcolumns,startCol);
if (iStart >= 0) {
columns.push_back(startCol);
rows.push_back(startRow);
} else {
Base::Console().Error("DVS - %s - start Column (%s) is invalid\n",getNameInDocument(),startCol.c_str());
return result.str();
}
//startCol is valid
//break endcell contents into row & col parts
std::string endCol;
int endRow = -1;
for (unsigned int i=0; i<scellend.length(); ++i) {
if (isdigit(scellend[i])) {
endCol = scellend.substr(0,i);
endRow = std::atoi(scellend.substr(i,scellend.length()-1).c_str());
break;
}
} catch (std::exception&) {
Base::Console().Error("Invalid cell range for %s\n",getNameInDocument());
}
//validate endCol in A:ZZ
int iEnd = colInList(availcolumns,endCol);
if (iEnd < 0) {
Base::Console().Error("DVS - %s - end Column (%s) is invalid\n",getNameInDocument(),endCol.c_str());
return result.str();
}
//endCol is valid
if ( (startCol > endCol) ||
(startRow > endRow) ) {
Base::Console().Error("DVS - %s - cell range is invalid\n",getNameInDocument());
return result.str();
}
// create the containing group
//fill the col/row name vectors
if (startCol != endCol) {
int i = iStart + 1;
for ( ; i < iEnd; i++) {
columns.push_back(availcolumns.at(i));
}
columns.push_back(endCol);
}
int i = startRow + 1;
for (; i < endRow; i ++) {
rows.push_back(i);
}
rows.push_back(endRow);
// create the Svg code
std::string ViewName = Label.getValue();
result << getSVGHead();
@@ -224,6 +242,7 @@ std::string DrawViewSpreadsheet::getSheetImage(void)
std::string celltext;
Spreadsheet::Sheet* sheet = static_cast<Spreadsheet::Sheet*>(link);
std::vector<std::string> skiplist;
for (std::vector<std::string>::const_iterator col = columns.begin(); col != columns.end(); ++col) {
// create a group for each column
result << " <g id=\"" << ViewName << "_col" << (*col) << "\">" << endl;
@@ -321,6 +340,18 @@ std::string DrawViewSpreadsheet::getSheetImage(void)
result << getSVGTail();
return result.str();
}
int DrawViewSpreadsheet::colInList(const std::vector<std::string>& list,
const std::string& toFind)
{
int result = -1;
auto match = std::find(std::begin(list), std::end(list), toFind);
if (match != std::end(list)) {
result = match - std::begin(list);
}
return result;
}
// Python Drawing feature ---------------------------------------------------------