diff --git a/src/App/DynamicProperty.cpp b/src/App/DynamicProperty.cpp index 16b88739f9..325fc8af68 100644 --- a/src/App/DynamicProperty.cpp +++ b/src/App/DynamicProperty.cpp @@ -65,6 +65,12 @@ void DynamicProperty::getPropertyList(std::vector &List) const List.push_back(v.property); } +void DynamicProperty::getPropertyNamedList(std::vector > &List) const +{ + for (auto &v : props.get<0>()) + List.emplace_back(v.getName(),v.property); +} + void DynamicProperty::getPropertyMap(std::map &Map) const { for (auto &v : props.get<0>()) diff --git a/src/App/DynamicProperty.h b/src/App/DynamicProperty.h index ba09a48568..91317db545 100644 --- a/src/App/DynamicProperty.h +++ b/src/App/DynamicProperty.h @@ -75,6 +75,8 @@ public: //@{ /// Get all properties of the class (including parent) void getPropertyList(std::vector &List) const; + /// get all properties with their names + void getPropertyNamedList(std::vector > &List) const; /// Get all properties of the class (including parent) void getPropertyMap(std::map &Map) const; /// Find a dynamic property by its name diff --git a/src/App/PropertyContainer.cpp b/src/App/PropertyContainer.cpp index a7438cea2f..9f63d52b11 100644 --- a/src/App/PropertyContainer.cpp +++ b/src/App/PropertyContainer.cpp @@ -101,6 +101,12 @@ void PropertyContainer::getPropertyList(std::vector &List) const getPropertyData().getPropertyList(this,List); } +void PropertyContainer::getPropertyNamedList(std::vector > &List) const +{ + dynamicProps.getPropertyNamedList(List); + getPropertyData().getPropertyNamedList(this,List); +} + void PropertyContainer::setPropertyStatus(unsigned char bit,bool value) { std::vector List; @@ -586,6 +592,18 @@ void PropertyData::getPropertyList(OffsetBase offsetBase,std::vector List.push_back((Property *) (spec.Offset + offsetBase.getOffset())); } +void PropertyData::getPropertyNamedList(OffsetBase offsetBase, + std::vector > &List) const +{ + merge(); + size_t base = List.size(); + List.reserve(base+propertyData.size()); + for (auto &spec : propertyData.get<0>()) { + auto prop = (Property *) (spec.Offset + offsetBase.getOffset()); + List.emplace_back(prop->getName(),prop); + } +} + /** \defgroup PropFrame Property framework diff --git a/src/App/PropertyContainer.h b/src/App/PropertyContainer.h index b9763de970..20dec41614 100644 --- a/src/App/PropertyContainer.h +++ b/src/App/PropertyContainer.h @@ -130,6 +130,7 @@ struct AppExport PropertyData Property *getPropertyByName(OffsetBase offsetBase,const char* name) const; void getPropertyMap(OffsetBase offsetBase,std::map &Map) const; void getPropertyList(OffsetBase offsetBase,std::vector &List) const; + void getPropertyNamedList(OffsetBase offsetBase, std::vector > &List) const; void merge(PropertyData *other=0) const; void split(PropertyData *other); @@ -168,6 +169,8 @@ public: virtual void getPropertyMap(std::map &Map) const; /// get all properties of the class (including properties of the parent) virtual void getPropertyList(std::vector &List) const; + /// get all properties with their names + virtual void getPropertyNamedList(std::vector > &List) const; /// set the Status bit of all properties at once void setPropertyStatus(unsigned char bit,bool value); diff --git a/src/Gui/ExpressionCompleter.cpp b/src/Gui/ExpressionCompleter.cpp index 697ff6aad5..b509e22cd7 100644 --- a/src/Gui/ExpressionCompleter.cpp +++ b/src/Gui/ExpressionCompleter.cpp @@ -159,10 +159,10 @@ public: int docSize = (int)docs.size()*2; int objSize = 0; int propSize = 0; - std::vector props; + std::vector > props; App::Document *doc = 0; App::DocumentObject *obj = 0; - App::Property *prop = 0; + const char *propName = nullptr; if(idx>=0 && idxgetPropertyList(props); + cobj->getPropertyNamedList(props); propSize = (int)props.size(); if(idx >= propSize) return; if(idx>=0) { obj = cobj; - prop = props[idx]; + propName = props[idx].first; } } } @@ -200,8 +200,8 @@ public: *count = docSize + objSize + propSize; if(idx>=0 && v) { QString res; - if(prop) - res = QString::fromLatin1(prop->getName()); + if(propName) + res = QString::fromLatin1(propName); else if(obj) { if(idx & 1) res = QString::fromUtf8(quote(obj->Label.getStrValue()).c_str()); @@ -248,18 +248,18 @@ public: if(noProperty) return; - if(!prop) { + if(!propName) { idx = row; - obj->getPropertyList(props); + obj->getPropertyNamedList(props); propSize = (int)props.size(); if(idx<0 || idx>=propSize) return; - prop = props[idx]; + propName = props[idx].first; if(count) *count = propSize; } - if(v) - *v = QString::fromLatin1(prop->getName()); + if(v) + *v = QString::fromLatin1(propName); return; } diff --git a/src/Mod/Spreadsheet/App/Cell.cpp b/src/Mod/Spreadsheet/App/Cell.cpp index 0b23d6eb83..f4414866a1 100644 --- a/src/Mod/Spreadsheet/App/Cell.cpp +++ b/src/Mod/Spreadsheet/App/Cell.cpp @@ -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(); } diff --git a/src/Mod/Spreadsheet/App/PropertySheet.cpp b/src/Mod/Spreadsheet/App/PropertySheet.cpp index 5a2b434b17..ef8929bc2d 100644 --- a/src/Mod/Spreadsheet/App/PropertySheet.cpp +++ b/src/Mod/Spreadsheet/App/PropertySheet.cpp @@ -120,6 +120,17 @@ const Cell * PropertySheet::getValueFromAlias(const std::string &alias) const return 0; } +Cell * PropertySheet::getValueFromAlias(const std::string &alias) +{ + std::map::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 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) diff --git a/src/Mod/Spreadsheet/App/PropertySheet.h b/src/Mod/Spreadsheet/App/PropertySheet.h index 5a9041c364..51a7073c4d 100644 --- a/src/Mod/Spreadsheet/App/PropertySheet.h +++ b/src/Mod/Spreadsheet/App/PropertySheet.h @@ -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 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; diff --git a/src/Mod/Spreadsheet/App/Sheet.cpp b/src/Mod/Spreadsheet/App/Sheet.cpp index 9f576d8faa..1c66083759 100644 --- a/src/Mod/Spreadsheet/App/Sheet.cpp +++ b/src/Mod/Spreadsheet/App/Sheet.cpp @@ -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 Sheet::getRowHeights() const } -/** - * @brief Remove all aliases. - * - */ - -void Sheet::removeAliases() -{ - std::map::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 > &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 diff --git a/src/Mod/Spreadsheet/App/Sheet.h b/src/Mod/Spreadsheet/App/Sheet.h index fe5096121e..34a202772f 100644 --- a/src/Mod/Spreadsheet/App/Sheet.h +++ b/src/Mod/Spreadsheet/App/Sheet.h @@ -175,12 +175,20 @@ public: App::Property *getPropertyByName(const char *name) const; + App::Property *getDynamicPropertyByName(const char* name) const; + + virtual void getPropertyNamedList(std::vector > &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 getColumnWidths() const; std::map 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 propAddress; - /* Removed (unprocessed) aliases */ - std::map removedAliases; - /* Set of cells with errors */ std::set cellErrors;