Spreadsheet: change alias handling
No longer add dynamic property for alias, simply rely on get(Dynamic)PropertyByName() to check for aliases. Add new API PropertyContainer::getPropertyNamedList() so that ExpressionCompleter can discover properties with aliases.
This commit is contained in:
@@ -131,12 +131,12 @@ Cell::Cell(PropertySheet *_owner, const Cell &other)
|
||||
, foregroundColor(other.foregroundColor)
|
||||
, backgroundColor(other.backgroundColor)
|
||||
, displayUnit(other.displayUnit)
|
||||
, alias(other.alias)
|
||||
, computedUnit(other.computedUnit)
|
||||
, rowSpan(other.rowSpan)
|
||||
, colSpan(other.colSpan)
|
||||
{
|
||||
setUsed(MARK_SET, false);
|
||||
setAlias(other.alias);
|
||||
setDirty();
|
||||
}
|
||||
|
||||
|
||||
@@ -120,6 +120,17 @@ const Cell * PropertySheet::getValueFromAlias(const std::string &alias) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
Cell * PropertySheet::getValueFromAlias(const std::string &alias)
|
||||
{
|
||||
std::map<std::string, CellAddress>::const_iterator it = revAliasProp.find(alias);
|
||||
|
||||
if (it != revAliasProp.end())
|
||||
return getValue(it->second);
|
||||
else
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
bool PropertySheet::isValidAlias(const std::string &candidate)
|
||||
{
|
||||
static const boost::regex gen("^[A-Za-z][_A-Za-z0-9]*$");
|
||||
@@ -615,9 +626,14 @@ void PropertySheet::setAlias(CellAddress address, const std::string &alias)
|
||||
Cell * cell = nonNullCellAt(address);
|
||||
assert(cell != 0);
|
||||
|
||||
if (aliasedCell != 0 && cell != aliasedCell)
|
||||
if(aliasedCell == cell)
|
||||
return;
|
||||
|
||||
if (aliasedCell)
|
||||
throw Base::ValueError("Alias already defined.");
|
||||
|
||||
AtomicPropertyChange signaller(*this);
|
||||
|
||||
/* Mark cells depending on this cell dirty; they need to be resolved when an alias changes or disappears */
|
||||
std::string fullName = owner->getFullName() + "." + address.toString();
|
||||
|
||||
@@ -632,23 +648,21 @@ void PropertySheet::setAlias(CellAddress address, const std::string &alias)
|
||||
}
|
||||
|
||||
std::string oldAlias;
|
||||
|
||||
if (cell->getAlias(oldAlias))
|
||||
owner->aliasRemoved(address, oldAlias);
|
||||
|
||||
cell->getAlias(oldAlias);
|
||||
cell->setAlias(alias);
|
||||
|
||||
if (oldAlias.size() > 0 && alias.size() > 0) {
|
||||
if (oldAlias.size() > 0) {
|
||||
std::map<App::ObjectIdentifier, App::ObjectIdentifier> m;
|
||||
|
||||
App::ObjectIdentifier key(owner, oldAlias);
|
||||
App::ObjectIdentifier value(owner, alias);
|
||||
App::ObjectIdentifier value(owner, alias.empty()?address.toString():alias);
|
||||
|
||||
m[key] = value;
|
||||
|
||||
owner->getDocument()->renameObjectIdentifiers(m);
|
||||
}
|
||||
|
||||
signaller.tryInvoke();
|
||||
}
|
||||
|
||||
void PropertySheet::setComputedUnit(CellAddress address, const Base::Unit &unit)
|
||||
|
||||
@@ -112,6 +112,8 @@ public:
|
||||
|
||||
const Cell * getValueFromAlias(const std::string &alias) const;
|
||||
|
||||
Cell * getValueFromAlias(const std::string &alias);
|
||||
|
||||
bool isValidAlias(const std::string &candidate);
|
||||
|
||||
std::set<App::CellAddress> getUsedCells() const;
|
||||
@@ -178,6 +180,9 @@ public:
|
||||
|
||||
void documentSet();
|
||||
|
||||
App::CellAddress getCellAddress(const char *addr, bool silent=false) const;
|
||||
App::Range getRange(const char *range, bool silent=false) const;
|
||||
|
||||
std::string getRow(int offset=0) const;
|
||||
|
||||
std::string getColumn(int offset=0) const;
|
||||
|
||||
@@ -120,7 +120,6 @@ void Sheet::clearAll()
|
||||
cellErrors.clear();
|
||||
columnWidths.clear();
|
||||
rowHeights.clear();
|
||||
removedAliases.clear();
|
||||
|
||||
for (ObserverMap::iterator i = observers.begin(); i != observers.end(); ++i)
|
||||
delete i->second;
|
||||
@@ -464,6 +463,14 @@ bool Sheet::getCellAddress(const Property *prop, CellAddress & address)
|
||||
return false;
|
||||
}
|
||||
|
||||
App::CellAddress Sheet::getCellAddress(const char *name, bool silent) const {
|
||||
return cells.getCellAddress(name,silent);
|
||||
}
|
||||
|
||||
App::Range Sheet::getRange(const char *name, bool silent) const {
|
||||
return cells.getRange(name,silent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a map with column indices and widths.
|
||||
* @return Map with results.
|
||||
@@ -485,22 +492,6 @@ std::map<int, int> Sheet::getRowHeights() const
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Remove all aliases.
|
||||
*
|
||||
*/
|
||||
|
||||
void Sheet::removeAliases()
|
||||
{
|
||||
std::map<CellAddress, std::string>::iterator i = removedAliases.begin();
|
||||
|
||||
while (i != removedAliases.end()) {
|
||||
this->removeDynamicProperty(i->second.c_str());
|
||||
++i;
|
||||
}
|
||||
removedAliases.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update internal structure when document is set for this property.
|
||||
*/
|
||||
@@ -646,42 +637,6 @@ Property * Sheet::setObjectProperty(CellAddress key, Py::Object object)
|
||||
return pyProp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the alias for the cell at \a key.
|
||||
* @param key Cell to update.
|
||||
*/
|
||||
|
||||
void Sheet::updateAlias(CellAddress key)
|
||||
{
|
||||
std::string alias;
|
||||
Property * prop = props.getDynamicPropertyByName(key.toString().c_str());
|
||||
|
||||
if (!prop)
|
||||
return;
|
||||
|
||||
Cell * cell = getCell(key);
|
||||
|
||||
if (cell && cell->getAlias(alias)) {
|
||||
Property * aliasProp = props.getDynamicPropertyByName(alias.c_str());
|
||||
|
||||
/* Update or create alias? */
|
||||
if (aliasProp) {
|
||||
// Type of alias and property must always be the same
|
||||
if (aliasProp->getTypeId() != prop->getTypeId()) {
|
||||
this->removeDynamicProperty(alias.c_str());
|
||||
aliasProp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aliasProp) {
|
||||
aliasProp = addDynamicProperty(prop->getTypeId().getName(), alias.c_str(), 0, 0, Prop_ReadOnly | Prop_NoPersist);
|
||||
aliasProp->setStatus(App::Property::Hidden,true);
|
||||
}
|
||||
|
||||
aliasProp->Paste(*prop);
|
||||
}
|
||||
}
|
||||
|
||||
struct CurrentAddressLock {
|
||||
CurrentAddressLock(int &r, int &c, const CellAddress &addr)
|
||||
:row(r),col(c)
|
||||
@@ -772,20 +727,37 @@ void Sheet::updateProperty(CellAddress key)
|
||||
|
||||
Property *Sheet::getPropertyByName(const char* name) const
|
||||
{
|
||||
std::string _name;
|
||||
CellAddress addr;
|
||||
if(addr.parseAbsoluteAddress(name)) {
|
||||
_name = addr.toString(true);
|
||||
name = _name.c_str();
|
||||
}
|
||||
Property * prop = getProperty(name);
|
||||
|
||||
CellAddress addr = getCellAddress(name,true);
|
||||
Property *prop = 0;
|
||||
if(addr.isValid())
|
||||
prop = getProperty(addr);
|
||||
if (prop)
|
||||
return prop;
|
||||
else
|
||||
return DocumentObject::getPropertyByName(name);
|
||||
}
|
||||
|
||||
Property *Sheet::getDynamicPropertyByName(const char* name) const {
|
||||
CellAddress addr = getCellAddress(name,true);
|
||||
Property *prop = 0;
|
||||
if(addr.isValid())
|
||||
prop = getProperty(addr);
|
||||
if (prop)
|
||||
return prop;
|
||||
else
|
||||
return DocumentObject::getDynamicPropertyByName(name);
|
||||
}
|
||||
|
||||
void Sheet::getPropertyNamedList(std::vector<std::pair<const char*,Property*> > &List) const {
|
||||
DocumentObject::getPropertyNamedList(List);
|
||||
List.reserve(List.size()+cells.aliasProp.size());
|
||||
for(auto &v : cells.aliasProp) {
|
||||
auto prop = getProperty(v.first);
|
||||
if(prop)
|
||||
List.emplace_back(v.second.c_str(),prop);
|
||||
}
|
||||
}
|
||||
|
||||
void Sheet::touchCells(Range range) {
|
||||
do {
|
||||
cells.setDirty(*range);
|
||||
@@ -838,8 +810,6 @@ void Sheet::recomputeCell(CellAddress p)
|
||||
throw;
|
||||
}
|
||||
|
||||
updateAlias(p);
|
||||
|
||||
if (!cell || cell->spansChanged())
|
||||
cellSpanChanged(p);
|
||||
}
|
||||
@@ -897,8 +867,6 @@ unsigned Sheet::getCellBindingBorder(App::CellAddress address) const {
|
||||
|
||||
DocumentObjectExecReturn *Sheet::execute(void)
|
||||
{
|
||||
// Remove all aliases first
|
||||
removeAliases();
|
||||
boundRanges.clear();
|
||||
for(auto &v : ExpressionEngine.getExpressions()) {
|
||||
CellAddress from,to;
|
||||
@@ -1443,17 +1411,6 @@ void Sheet::setSpans(CellAddress address, int rows, int columns)
|
||||
cells.setSpans(address, rows, columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when alias \a alias at \a address is removed.
|
||||
* @param address Address of alias.
|
||||
* @param alias Removed alias.
|
||||
*/
|
||||
|
||||
void Sheet::aliasRemoved(CellAddress address, const std::string & alias)
|
||||
{
|
||||
removedAliases[address] = alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return a set of dependencies links for cell at \a address.
|
||||
* @param address Address of cell
|
||||
|
||||
@@ -175,12 +175,20 @@ public:
|
||||
|
||||
App::Property *getPropertyByName(const char *name) const;
|
||||
|
||||
App::Property *getDynamicPropertyByName(const char* name) const;
|
||||
|
||||
virtual void getPropertyNamedList(std::vector<std::pair<const char*,App::Property*> > &List) const;
|
||||
|
||||
virtual short mustExecute(void) const;
|
||||
|
||||
App::DocumentObjectExecReturn *execute(void);
|
||||
|
||||
bool getCellAddress(const App::Property *prop, App::CellAddress &address);
|
||||
|
||||
App::CellAddress getCellAddress(const char *name, bool silent=false) const;
|
||||
|
||||
App::Range getRange(const char *name, bool silent=false) const;
|
||||
|
||||
std::map<int, int> getColumnWidths() const;
|
||||
|
||||
std::map<int, int> getRowHeights() const;
|
||||
@@ -223,8 +231,6 @@ protected:
|
||||
|
||||
App::Property *getProperty(const char * addr) const;
|
||||
|
||||
void updateAlias(App::CellAddress key);
|
||||
|
||||
void updateProperty(App::CellAddress key);
|
||||
|
||||
App::Property *setStringProperty(App::CellAddress key, const std::string & value) ;
|
||||
@@ -237,10 +243,6 @@ protected:
|
||||
|
||||
App::Property *setQuantityProperty(App::CellAddress key, double value, const Base::Unit &unit);
|
||||
|
||||
void aliasRemoved(App::CellAddress address, const std::string &alias);
|
||||
|
||||
void removeAliases();
|
||||
|
||||
virtual void onSettingDocument();
|
||||
|
||||
/* Properties for used cells */
|
||||
@@ -249,9 +251,6 @@ protected:
|
||||
/* Mapping of properties to cell position */
|
||||
std::map<const App::Property*, App::CellAddress > propAddress;
|
||||
|
||||
/* Removed (unprocessed) aliases */
|
||||
std::map<App::CellAddress, std::string> removedAliases;
|
||||
|
||||
/* Set of cells with errors */
|
||||
std::set<App::CellAddress> cellErrors;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user