Commit Graph

56 Commits

Author SHA1 Message Date
Pieter Hijma
ec4ea7f8d3 [Doc] Improve topics within App
- The location of the documentation is improved (not in the cpp file
  anymore but in core-app.dox).  This prevents cluttering source with
  high-level overviews typical of topic documentation.
- The formatting has been made consistent.
2025-03-29 15:11:01 -05:00
Pieter Hijma
aa768e2a90 [Doc] Fix Robot kdl documentation issues 2025-03-24 16:33:54 +01:00
Kevin Martin
41f09db9e1 Address performance of existing unique-name generation (Part 2) (#18676)
As described in Issue 16849, the existing Tools::getUniqueName method
requires calling code to form a vector of existing names to be avoided.

This leads to poor performance both in the O(n) cost of building such a
vector and also getUniqueName's O(n) algorithm for actually generating
the unique name (where 'n' is the number of pre-existing names).

This has  particularly noticeable cost in documents with large numbers
of DocumentObjects because generating both Names and Labels for each new
object incurs this cost. During an operation such as importing this
results in an O(n^2) time spent generating names.

The other major cost is in the saving of the temporary backup file,
which uses name generation for the "files" embedded in the Zip file.
Documents can easily need several such "files" for each object in the
document.

This update includes the following changes to use the newly-added
UniqueNameManager as a replacement for the old Tools::getUniqueName
method and deletes the latter to remove any temptation to use it as
its usage model breeds inefficiency:

Eliminate Tools::getUniqueName, its local functions, and its unit tests.

Make DocumentObject naming use the new UniqueNameManager class.

Make DocumentObject Label naming use the new UniqueNameManager class.
This needs to monitor DocumentObject Labels for changes since this
property is not read-only. The special handling for the Label
property, which includes optionally forcing uniqueness and updating
links in referencing objects, has been mostly moved from
PropertyString to DocumentObject.

Add Document::containsObject(DocumentObject*) for a definitive
test of an object being in a Document. This is needed because
DocumentObjects can be in a sort of limbo (e.g. when they are in the
Undo/Redo lists) where they have a parent linkage to the Document but
should not participate in Label collision checks.

Rename Document.getStandardObjectName to getStandardObjectLabel
to better represent what it does.

Use new UniqueNameManager for Writer internal filenames within the zip
file.

Eliminate unneeded Reader::FileNames collection. The file names
already exist in the FileList collection elements. The only existing
use for the FileNames collection was to determine if there were any
files at all, and with FileList and FileNames being parallel
vectors, they both had the same length so FileList could be used
for this test..

Use UniqueNameManager for document names and labels. This uses ad hoc
UniqueNameManager objects created on the spot on the assumption that
document creation is relatively rare and there are few documents, so
although the cost is O(n), n itself is small.

Use an ad hoc UniqueNameManager to name new DymanicProperty entries.
This is only done if a property of the proposed name already exists,
since such a check is more-or-less O(log(n)), almost never finds a
collision, and avoids the O(n) building of the UniqueNameManager.
If there is a collision an ad-hoc UniqueNameManager is built
and discarded after use.
The property management classes have a bit of a mess of methods
including several to populate various collection types with all
existing properties. Rather than introducing yet another such
collection-specific method to fill a UniqueNameManager, a
visitProperties method was added which calls a passed function for
each property. The existing code (e.g. getPropertyMap) would be
simpler if they all used this but the cost of calling a lambda
for each property must be considered. It would clarify the semantics
of these methods, which have a bit of variance in which properties
populate the passed collection, e.g. when there are duplicate names..
Ideally the PropertyContainer class would keep a central directory of
all properties ("static", Dynamic, and exposed by ExtensionContainer and
other derivations) and a permanent UniqueNameManager. However the
Property management is a bit of a mess making such a change a project
unto itself.
2025-02-24 10:23:53 -06:00
Benjamin Nauck
a2c980f7d6 Revert "Address the poor performance of the existing unique-name generation (#17944)"
This reverts commit 83202d8ad6.

# Conflicts:
#	src/Base/Tools.cpp
#	src/Base/Tools.h
2024-12-16 17:31:43 +01:00
Kevin Martin
83202d8ad6 Address the poor performance of the existing unique-name generation (#17944)
* Address the poor performance of the existing unique-name generation

As described in Issue 16849, the existing Tools::getUniqueName method
requires calling code to form a vector of existing names to be avoided.

This leads to poor performance both in the O(n) cost of building such a
vector and also getUniqueName's O(n) algorithm for actually generating
the unique name (where 'n' is the number of pre-existing names).

This has  particularly noticeable cost in documents with large numbers
of DocumentObjects because generating both Names and Labels for each new
object incurs this cost. During an operation such as importing this
results in an O(n^2) time spent generating names.

The other major cost is in the saving of the temporary backup file,
which uses name generation for the "files" embedded in the Zip file.
Documents can easily need several such "files" for each object in the
document.

This update includes the following changes:

Create UniqueNameManager to keep a list of existing names organized in
a manner that eases unique-name generation. This class essentially acts
as a set of names, with the ability to add and remove names and check if
a name is already there, with the added ability to take a prototype name
and generate a unique form for it which is not already in the set.

Eliminate Tools::getUniqueName

Make DocumentObject naming use the new UniqueNameManager class

Make DocumentObject Label naming use the new UniqueNameManager class.
Labels are not always unique; unique labels are generated if the
settings at the time request it (and other conditions). Because of this
the Label management requires additionally keeping a map of counts
for labels which already exist more than once.
These collections are maintained via notifications of value changes on
the Label properties of the objects in the document.

Add Document::containsObject(DocumentObject*) for a definitive
test of an object being in a Document. This is needed because
DocumentObjects can be in a sort of limbo (e.g. when they are in the
Undo/Redo lists) where they have a parent linkage to the Document but
should not participate in Label collision checks.

Rename Document.getStandardObjectName to getStandardObjectLabel
to better represent what it does.

Use new UniqueNameManager for Writer internal filenames within the zip
file.

Eliminate unneeded Reader::FileNames collection. The file names
already exist in the FileList collection elements. The only existing
use for the FileNames collection was to determine if there were any
files at all, and with FileList and FileNames being parallel
vectors, they both had the same length so FileList could be used
for this test..

Use UniqueNameManager for document names and labels. This uses ad hoc
UniqueNameManager objects created on the spot on the assumption that
document creation is relatively rare and there are few documents, so
although the cost is O(n), n itself is small.

Use an ad hoc UniqueNameManager to name new DymanicProperty entries.
This is only done if a property of the proposed name already exists,
since such a check is more-or-less O(log(n)), almost never finds a
collision, and avoids the O(n) building of the UniqueNameManager.
If there is a collision an ad-hoc UniqueNameManager is built
and discarded after use.
The property management classes have a bit of a mess of methods
including several to populate various collection types with all
existing properties. Rather than introducing yet another such
collection-specific method to fill a UniqueNameManager, a
visitProperties method was added which calls a passed function for
each property. The existing code would be simpler if existing
fill-container methods all used this.
Ideally the PropertyContainer class would keep a central directory of
all properties ("static", Dynamic, and exposed by ExtensionContainer and
other derivations) and a permanent UniqueNameManager. However the
Property management is a bit of a mess making such a change a project
unto itself.

The unit tests for Tools:getUniqueName have been changed to test
UniqueNameManager.makeUniqueName instead.
This revealed a small regression insofar as passing a prototype name
like "xyz1234" to the old code would yield "xyz1235" whether or
not "xyz1234" already existed, while the new code will return the next
name above the currently-highest name on the "xyz" model, which could
be "xyz" or "xyz1".

* Correct wrong case on include path

* Implement suggested code changes
Also change the semantics of visitProperties to not have any short-circuit return

* Remove reference through undefined iterator

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Fix up some comments for DOxygen

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-12-13 10:54:46 -06:00
wmayer
56820718c5 Core: Revert superfluous changes made with PR #9521 2023-10-09 15:06:45 +02:00
AgCaliva
1f9bae0de7 Merge branch 'master' into User/Document/Feature_level_units_selection_#7746 2023-09-25 22:58:23 -03:00
Chris Hennes
b8055fa6f4 App/Toponaming: Minor code cleanup 2023-09-17 13:13:37 -05:00
Chris Hennes
2a386c9f6f App/Toponaming: Add StringHasher to Document 2023-09-17 13:13:37 -05:00
AgCaliva
39dcb1da7b Merge Master 2023-08-30 16:24:16 -03:00
wmayer
26f16f7410 App: modernize C++: use range-based for loop 2023-08-14 16:40:25 +02:00
AgCaliva
816d4077df Implemented DocumentReader for GuiDocument.xml reading. Final 2023-06-30 20:50:36 -03:00
AgCaliva
0751770bc6 Revert "DocumentReader implemented for GuiDocument.xml reading."
This reverts commit 5f101af3e9.
2023-06-30 20:27:12 -03:00
AgCaliva
5f101af3e9 DocumentReader implemented for GuiDocument.xml reading. 2023-06-30 18:41:00 -03:00
AgCaliva
52c55f59a8 Implementing agnostic version of ParameterGrp for reading XML, replacing XMLReader from src/Base/reader.cpp with new class DocumentReader 2023-06-16 15:36:43 -03:00
Abdullah Tahiri
4dea0df06c App: Extension/ExtensionContainer - handle property change
==========================================================

Currently changes of name or type of properties in a property container are handled by:
void PropertyContainer::handleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName)
void PropertyContainer::changedPropertyType(Base::XMLReader &reader, const char * TypeName, Property * prop)

There is no mechanism for handling property changes by extensions. Sometimes the solution is to explicitly call the extension
from the container. However, this is a breach of the SRP, as the container should not be in a position to decide whether the
extension needs or not handle property changes. The handling code of the container changes for two different reasons, for
adapting the container to a property change of its own, and for adapting that of a property of the extension.

Illustrating it with an example, following inheritance, it goes like this:
PropertyContainer => ExtensionContainer => TransactionalObject => ViewProvider
App::Extension => ViewProviderExtension

The extension is currently not notified by the ExtensionContainer that a property needs handling. So a change in a property of
a ViewProviderExtension needs code at the ViewProvider it was added to.

This commit provides a mechanism in ExtensionContainer to call the extensions so that they can handle property changes. This
functions:

  virtual bool extensionHandleChangedPropertyName(Base::XMLReader &reader, const char * TypeName, const char *PropName);
  virtual bool extensionHandleChangedPropertyType(Base::XMLReader &reader, const char * TypeName, Property * prop);

Containers should always call the base class for any unhandled property change. If a sub-class container of ExtensionContainer
handles property changes itself, but not the ones of the extensions, this call to the base class ultimately ensures that if the
property was not handled by the container hierarchy, any extension is given an opportunity to handle it.

Some examples:

* A container handles the extension property change or its own:

void ContainerSubClass::handleChangedPropertyType(...)
{
    if (prop == &PropertyOfExt) {

    }
    else if (prop == &PropertyOfCont) {

    }
    else {
        ContainerBaseClass::handleChangedPropertyType(...);
    }
}

* A container and the extension handle their own:

void ContainerSubClass::handleChangedPropertyType(...)
{
    if (prop == &PropertyOfCont) {

    }
    else {
        // This will call ExtensionContainer::handleChangedPropertyType
        ContainerBaseClass::handleChangedPropertyType(...);
    }
}

bool ExtensionSubClass::extensionHandleChangedPropertyType(...)
{
    if (prop == &PropertyOfCont) {

        return true;
    }
    return false;
}
2023-02-25 23:13:55 +01:00
marioalexis
9ccb9eecb2 App: Replace C cast 2022-09-18 11:06:51 -05:00
berniev
65a356835b App: Modernise ctors dtors defs etc 2022-08-01 00:34:46 +02:00
berniev
b40de7a509 remove redundant void 2022-07-31 10:27:44 +02:00
Zheng, Lei
fe5ac277a0 App: fix property conflict in App::Link restore
The conflict happens if the App::Link has dynamic property having the
same name as the linked object
2022-04-25 00:49:16 +02:00
Chris Hennes
132a1d7e55 App: PR6497 move return statement to new line 2022-03-29 12:33:37 -05:00
wmayer
749361d2f3 App: modernize C++11
* use nullptr
2022-03-23 17:29:23 +01:00
Uwe
c7910825a3 [App] Placement and Property: remove unused includes 2022-02-24 01:09:00 +01:00
Zheng, Lei
d0b7bf1669 App: fix property status restore 2021-12-21 21:41:02 -07:00
Zheng, Lei
2a3951ca32 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.
2021-12-21 21:41:02 -07:00
Zheng, Lei
e3cbc9fcfc App: change PropertyContainer::Restore()
Changes the way PropertyContainer handles existing property while
restoring. Previously it will first ask DynamicProperty to restore
if possible, then fallback to static property if else.

This patch looks up existing property first, and only fallback to
DynamicProperty if not found. This handles situation when an object
changes an originally dynamic property into a static one. With the
original code, it will add an auto renamed dynamic property that no
one knows its existence.
2021-11-21 19:03:53 -06:00
luz.paz
4f308dc03c src/App: [skip ci] fix header uniformity
This PR fixes header uniformity across all `src/App` files
2019-12-25 11:38:43 +01:00
luz.paz
7b7797f4f3 Fix various (doxy) typos and whitespace issues
Found via `codespell -q 3 -L aci,ake,aline,alle,alledges,alocation,als,ang,anid,ba,beginn,behaviour,bloaded,byteorder,calculater,cancelled,cancelling,cas,cascade,centimetre,childs,colour,colours,commen,currenty,dof,doubleclick,dum,eiter,elemente,feld,freez,hist,iff,indicies,initialisation,initialise,initialised,initialises,initialisiert,ist,kilometre,lod,mantatory,methode,metres,millimetre,modell,nd,noe,normale,normaly,nto,numer,oder,orgin,orginx,orginy,ot,pard,pres,programm,que,recurrance,rougly,seperator,serie,sinc,strack,substraction,te,thist,thru,tread,uint,unter,vertexes,wallthickness,whitespaces -S ./.git,*.po,*.ts,./ChangeLog.txt,./src/3rdParty,./src/Mod/Assembly/App/opendcm,./src/CXX,./src/zipios++,./src/Base/swig*,./src/Mod/Robot/App/kdl_cp,./src/Mod/Import/App/SCL,./src/WindowsInstaller,./src/Doc/FreeCAD.uml`
2019-10-03 07:57:13 +02:00
wmayer
b50b21576e core system
force strict ISO C++ (-Wpedantic)
TODO: still a lot of variadic macros are not valid ISO C++
2019-09-18 01:01:14 +02:00
Zheng, Lei
a228f3c11b App: fix xml indentation in PropertyContainer::Save 2019-08-17 15:32:50 +02:00
Zheng, Lei
3fcb3e677a PropertyContainer: skip saving trasient dynamic property 2019-08-17 15:32:49 +02:00
luz.paz
8825c95727 Fix typos in src/App 2019-08-17 15:32:48 +02:00
Zheng, Lei
f4205130ae App: Property related API changes
Property:

* Extended property status bitset. Mirror most of PropertyType and
  allow dynamic change property type.

* Cache property name and type to improve performance

* Centralize property status change signalling

* Change aboutToSetValue()/hasSetValue() to virtual

* Add new API getFullName() to obtain full quanlified name of the property

AtomicPropertyChangeInterface:

* Allow calling aboutToSetValue()/hasSetValue() when actually changed

PropertyLists:

* Refactor implementation by an abstract class PropertyListBase and a
  template class PropertyListsT, to allow better code reuse.
  PropertyListT is derived from AtomicPropertyChangeInterface to allow
  more efficient change on individual elements.

* All list type property now accept setting python value as a dictionary
  with index as key to set individual element of a list.

* Add touch list for more efficient handling of value changes. The list
  contains the index of changed value. And empty touch list should be
  treated as the entire list is changed. PropertyContainerPy expose this
  functionality with getPropertyTouchList().

PropertyPersistentObject:

* New property to allow dynamic creation of any FreeCAD object derived
  from Base::Persistence, and use it as a property.

DynamicProperty:

* Use boost multi_index_container for efficient property lookup while
  keeping order.

* Modify to be allowed to use in PropertyContainer directly

PropertyContainer:

* Use boost multi_index_container for efficient property lookup while
  keeping order.

* Allow adding/removing dynamic property on all property container

* Modify Save/Restore() to persist property status, and better handle
  transient property which can now be dynamically enabled/disabled per
  object.

* Add new API getFullName() to obtain full quanlified name of the property.
  Implemented by Document, DocumentObject, and also
  ViewProviderDocumentObject if future patch

DocumentObject and FeaturePython are modified to accommondate the
dynamic property changes.

Removed get/setCustomAttribute() implementation from DocumentObjectPy,
and rely on PropertyContainerPy for the implementation, because of the
additional dynamic property support in property container.

Gui::ViewProviderDocumentObject, which is derived from
PropertyContainer, is also modified accordingly
2019-08-17 14:52:09 +02:00
wmayer
ddb20468ad some additions to pR 1794:
add a special XMLAttributeError class to indicate an error when accessing a missing attribute
in PropertyContainer::Restore make error handling more flexible
2018-11-19 19:07:56 +01:00
Abdullah Tahiri
b6a37e153f Example implementation 2018-11-19 11:31:10 +01:00
Abdullah Tahiri
1b152ee689 Example code of propagating the result of the partial restore 2018-11-19 11:31:08 +01:00
wmayer
d3ef6905ff + add option to switch off precompiled header 2018-07-25 20:17:11 +02:00
wmayer
833c2c601e add missing newlines 2018-06-09 11:47:12 +02:00
Zheng, Lei
ba3fb75b48 PropertyContainer: fix false hit when searching property
PropertyContainer uses a static member of type PropertyData to register
static properties. PropertyData uses a short variable to record the
offset of the property against its container.

Because of possible 'short' truncation, when searching of property that
in fact is from another container, we must check if the pointer within
boundary. Otherwise, truncation will result in effectively random
number, and possibly causing a false hit.
2018-04-02 14:17:16 +02:00
luz.paz
b45bc4889d Misc. typos: Please merge right before 0.17 release
I'm still finding typos in the source code. I propose that you keep this PR open prior ro relaese and then merge  so that if I find other typos in the meantime they will be part this release.
2018-03-18 15:15:16 +01:00
wmayer
3b957a12b5 various minor changes:
+ whitespace improvement
+ code cleanup
2017-11-21 17:51:22 +01:00
wmayer
20503f3d80 rename handleMissingProperty to handleChangedPropertyName 2017-07-23 22:14:05 +02:00
Eivind Kvedalen
a2cdd52019 Added PropertyContainer::handleMissingProperty(...) and PropertyContainer::handleChangedPropertyType(...).
These are helper functions to simplify migrating older files.
2017-07-23 22:14:05 +02:00
Yorik van Havre
af97583026 Doc: Fixes in doxygen docs for Draft,Arch, FEM 2016-11-17 17:04:09 -02:00
Stefan Tröger
3a51404dd5 Extenions: Drop virtual inheritance
Due to problems onthe windows platform the virtual inheritance approach must be dropped. NExt to the already reimplemented proeprty interface the Type interface is reimplemented too. This change allows to revert some earlier changes.
2016-10-08 12:48:34 +02:00
Stefan Tröger
558e128b39 Extensions: Revert few changes after restructuring 2016-10-08 12:48:34 +02:00
Stefan Tröger
3977ce71c6 Extensions: Add type safety to PropertyData again 2016-10-08 12:48:34 +02:00
Stefan Tröger
22fa3b3922 Extension: Fix order-of-initialisation crash
FreeCADs property system utilises some pointer math to calculate the offset between
property and base class. Due to virtual inheritance of th ePropertyContainer the memory
layout has been changed to rather random, which has lead to crashes dependend on the
order of object initialisation.

The solution is to not make PropertyContaner virtual but a class below, Base::Persitance.
Then the memory layout is random for Persistance, but it is perfectly aligned for the
base class chains from PropertyContainer onwards as well as from Extension onwards.
Hence the proeprty system was changed to take the offset always from those two.
2016-10-08 12:48:34 +02:00
Stefan Tröger
4c42181e34 Extensions: Show up in the python interface 2016-10-08 12:48:34 +02:00
wmayer
53d323b5e0 + make isReadOnly & isHidden of PropertyContainer non-virtual 2015-11-14 02:07:57 +01:00