/
PropertyLinks.h
1374 lines (1116 loc) · 50 KB
/
PropertyLinks.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/***************************************************************************
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
* *
* 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 APP_PROPERTYLINKS_H
#define APP_PROPERTYLINKS_H
#include <list>
#include <map>
#include <string>
#include <vector>
#include "Property.h"
namespace Base {
class Writer;
}
namespace App
{
class DocumentObject;
class Document;
class DocInfo;
using DocInfoPtr = std::shared_ptr<DocInfo>;
class PropertyXLink;
/**
* @brief Defines different scopes for which a link can be valid
* The scopes defined in this enum describe the different possibilities of where a link can point to.
* Local: links are valid only within the same GeoFeatureGroup as the linkowner is in or in none.
* Child: links are valid within the same or any sub GeoFeatureGroup
* Global: all possible links are valid
* Hidden: links are not included in dependency calculation
*/
enum class LinkScope {
Local,
Child,
Global,
Hidden,
};
/**
* @brief Enables scope handling for links
* This class is a base for all link properties and enables them to handle scopes of the linked objects.
* The possible scopes are defined by LinkScope enum class. The default value is Local.
* The scope of a property is not saved in the document. It is a value that needs to be fixed when
* the object holding the property is loaded. That is possible with two methods:
* 1. Set the scope value in the constructor of the link property
* 2. Use setScope to change the scope in the constructor of the link property
*
* The second option is only available in c++, not in python, as setscope is not exposed. It would
* not make sense to expose it there, as restoring python objects does not call the constructor again.
* Hence in python the only way to create a LinkProperty with different scope than local is to use a
* specialized property for that. In c++ existing properties can simply be changed via setScope in the
* objects constructor.
*/
class AppExport ScopedLink {
public:
/**
* @brief Set the links scope
* Allows to define what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and
* all Childs or to all objects within the Glocal scope.
*/
void setScope(LinkScope scope) {_pcScope = scope;};
/**
* @brief Get the links scope
* Retrieve what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and
* all Childs or to all objects within the Glocal scope.
*/
LinkScope getScope() const {return _pcScope;};
protected:
LinkScope _pcScope = LinkScope::Local;
};
/// Parent class of all link type properties
class AppExport PropertyLinkBase : public Property, public ScopedLink
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
using ShadowSub = std::pair<std::string,std::string>;
PropertyLinkBase();
~PropertyLinkBase() override;
friend class DocInfo;
/** Link type property interface APIs
* These APIs are moved here so that any type of property can have the
* property link behavior, e.g. the PropertyExpressionEngine
*/
//@{
/** Called to update the element reference of this link property
*
* @sa _updateElementReference()
*/
virtual void updateElementReference(App::DocumentObject *feature,
bool reverse=false, bool notify=false)
{
(void)feature;
(void)reverse;
(void)notify;
}
/// Clear internal element reference registration
void unregisterElementReference();
/** Register label reference for future object relabel update
*
* @param labels: labels to be registered
* @param reset: if true, then calls unregisterLabelReference() before
* registering
*/
void registerLabelReferences(std::vector<std::string> &&labels, bool reset=true);
/** Check subnames for label registration
*
* @param subs: subname references
* @param reset: if true, then calls unregisterLabelReference() before
* registering
*
* Check the give subname references and extract any label reference
* inside (by calling getLabelReferences()), and register them.
*/
void checkLabelReferences(const std::vector<std::string> &subs, bool reset=true);
/// Clear internal label references registration
void unregisterLabelReferences();
/// Test if the element reference has changed after restore
virtual bool referenceChanged() const {
return false;
}
/** Test if the link is restored unchanged
*
* @param msg: optional error message
*
* @return For external linked object, return 2 in case the link is
* missing, and 1 if the time stamp has changed.
*/
virtual int checkRestore(std::string *msg=nullptr) const {
(void)msg;
return 0;
}
/** Obtain the linked objects
*
* @param objs: hold the returned linked objects on output
* @param all: if true, then return all the linked object regardless of
* this LinkScope. If false, then return only if the LinkScope
* is not hidden.
* @param sub: if given, then return subname references.
* @param newStyle: whether to return new or old style subname reference
*/
virtual void getLinks(std::vector<App::DocumentObject *> &objs,
bool all=false, std::vector<std::string> *subs=nullptr, bool newStyle=true) const = 0;
/** Called to reset this link property
*
* @param obj: reset link property if it is linked to this object
* @param clear: if true, then also reset property if the owner of this property is \a obj
*
* @sa breakLinks()
*/
virtual void breakLink(App::DocumentObject *obj, bool clear) = 0;
/** Called to adjust the link to avoid potential cyclic dependency
*
* @param inList: recursive in-list of the would-be parent
*
* @return Return whether the link has been adjusted
*
* This function tries to correct the link to avoid any (sub)object inside
* in-list. If the adjustment is impossible, exception will be raised
*/
virtual bool adjustLink(const std::set<App::DocumentObject *> &inList) = 0;
/** Return a copy of the property if the link replacement affects this property
*
* @param owner: the parent object whose link property is to be replace.
* Note that The parent may not be the container of this
* property. Link sub property can use this opportunity to
* adjust its relative links.
* @param oldObj: object to be replaced
* @param newObj: object to replace with
*
* @return Return a copy of the property that is adjusted for the link
* replacement operation.
*/
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent,
App::DocumentObject *oldObj, App::DocumentObject *newObj) const = 0;
/** Return a copy of the property if any changes caused by importing external linked object
*
* @param nameMap: a map from the original external object name to the
* imported new object name
*
* @return Returns a copy of the property with the updated link reference if
* affected. The copy will later be assgiend to this property by calling its
* Paste().
*/
virtual Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const {
(void)nameMap;
return nullptr;
}
/** Update object label reference in this property
*
* @param obj: the object owner of the changing label
* @param ref: subname reference to old label
* @param newLabel: the future new label
*
* @return Returns a copy of the property if its link reference is affected.
* The copy will later be assgiend to this property by calling its Paste().
*/
virtual Property *CopyOnLabelChange(App::DocumentObject *obj,
const std::string &ref, const char *newLabel) const
{
(void)obj;
(void)ref;
(void)newLabel;
return nullptr;
}
/// Helper function to return all linked objects of this property
std::vector<App::DocumentObject *> linkedObjects(bool all=false) const {
std::vector<App::DocumentObject*> ret;
getLinks(ret,all);
return ret;
}
/// Helper function to return linked objects using an std::inserter
template<class T>
void getLinkedObjects(T &inserter, bool all=false) const {
std::vector<App::DocumentObject*> ret;
getLinks(ret,all);
std::copy(ret.begin(),ret.end(),inserter);
}
/// Helper function to return a map of linked object and its subname references
void getLinkedElements(std::map<App::DocumentObject*, std::vector<std::string> > &elements,
bool newStyle=true, bool all=true) const
{
std::vector<App::DocumentObject*> ret;
std::vector<std::string> subs;
getLinks(ret,all,&subs,newStyle);
assert(ret.size()==subs.size());
int i=0;
for(auto obj : ret)
elements[obj].push_back(subs[i++]);
}
/// Helper function to return a map of linked object and its subname references
std::map<App::DocumentObject*, std::vector<std::string> >
linkedElements(bool newStyle=true, bool all=true) const
{
std::map<App::DocumentObject*, std::vector<std::string> > ret;
getLinkedElements(ret,newStyle,all);
return ret;
}
//@}
bool isSame(const Property &other) const override;
/** Enable/disable temporary holding external object without throwing exception
*
* Warning, non-PropertyXLink related property does not have internal
* tracking of external objects, therefore the link will not by auto broken
* when external document is closed. Only use this for temporary case, or
* if you handle signalDeleteDocument yourself, or use one of the
* PropertyXLink related property.
*/
void setAllowExternal(bool allow);
/// Helper functions
//@{
/** Helper function to check and replace a link
*
* @param owner: the owner of the current property
* @param obj: the current linked object
* @param parent: the parent of the changing link property, may or may not
* be equal to \c owner
* @param oldObj: the object to be replaced
* @param newObj: the object to replace with
* @param sub: optional the current subname reference
*
* @return Returns a pair(obj,subname). If no replacement is found,
* pair.first will be NULL
*
* Say a group has one of its child object replaced with another. Any
* existing link sub reference that refer to the original child object
* through the group will be broken. This helper function is used to check
* and correct any link sub reference.
*/
static std::pair<App::DocumentObject*,std::string> tryReplaceLink(
const App::PropertyContainer *owner, App::DocumentObject *obj,
const App::DocumentObject *parent, App::DocumentObject *oldObj,
App::DocumentObject *newObj, const char *sub=nullptr);
/** Helper function to check and replace a link with multiple subname references
*
* @param owner: the owner of the current property
* @param obj: the current linked object
* @param parent: the parent of the changing link property, may or may not
* be equal to \c owner
* @param oldObj: the object to be replaced
* @param newObj: the object to replace with
* @param subs: the current subname references
*
* @return Returns the a pair(obj,subs). If no replacement is found,
* pair.first will be NULL
* @sa tryReplaceLink()
*/
static std::pair<App::DocumentObject*, std::vector<std::string> >
tryReplaceLinkSubs( const App::PropertyContainer *owner,
App::DocumentObject *obj,
const App::DocumentObject *parent,
App::DocumentObject *oldObj,
App::DocumentObject *newObj,
const std::vector<std::string> &subs);
/// Update all element references in all link properties of \a feature
static void updateElementReferences(DocumentObject *feature, bool reverse=false);
/** Helper function for update individual element reference
*
* @param feature: if given, than only update element reference belonging
* to this feature. If not, then update geometry element
* references.
* @param sub: the subname reference to be updated.
* @param shadow: a pair of new and old style element references to be updated.
* @param reverse: if true, then use the old style, i.e. non-mapped element
* reference to query for the new style, i.e. mapped
* element reference when update. If false, then the other
* way around.
* @param notify: if true, call aboutToSetValue() before change
*
* This helper function is to be called by each link property in the event of
* geometry element reference change due to geometry model changes.
*/
bool _updateElementReference(App::DocumentObject *feature,
App::DocumentObject *obj, std::string &sub, ShadowSub &shadow,
bool reverse, bool notify=false);
/** Helper function to register geometry element reference
*
* @param obj: the linked object
* @param sub: the subname reference
* @param shadow: a pair of new and old style element references to be updated.
*
* Search for any geometry element reference inside the subname, and
* register for future update in case of geometry model update.
*/
void _registerElementReference(App::DocumentObject *obj, std::string &sub, ShadowSub &shadow);
/** Helper function for breaking link properties
*
* @param link: reset link property if it is linked to this object
* @param objs: the objects to check for the link properties
* @param clear: if true, then also reset property if the owner of the link property is \a link
*
* App::Document::breakDependency() calls this function to break the link property
*/
static void breakLinks(App::DocumentObject *link, const std::vector<App::DocumentObject*> &objs, bool clear);
/** Helper function for link import operation
*
* @param obj: the linked object
* @param sub: subname reference
* @param doc: importing document
* @param nameMap: a name map from source object to its imported counter part
*
* @return Return a changed subname reference, or empty string if no change.
*
* Link import operation will go through all link property and imports all
* externally linked object. After import, the link property must be
* changed to point to the newly imported objects, which should happen inside
* the API CopyOnImportExternal(). This function helps to rewrite subname
* reference to point to the correct sub objects that are imported.
*/
static std::string tryImportSubName(const App::DocumentObject *obj, const char *sub,
const App::Document *doc, const std::map<std::string,std::string> &nameMap);
/** Helper function for link import operation
*
* @param doc: owner document of the imported objects
* @param obj: the linked object
* @param nameMap: a name map from source object to its imported counter part
*
* @return Return the imported object if found, or the input \c obj if no change.
* @sa tryImportSubNames
*
* This function searches for the name map and tries to find the imported
* object from the given source object.
*/
static App::DocumentObject *tryImport(const App::Document *doc, const App::DocumentObject *obj,
const std::map<std::string,std::string> &nameMap);
/** Helper function to export a subname reference
*
* @param output: output subname if the subname is modified
* @param obj: linked object
* @param sub: input subname reference
* @param first_obj: if true, then the first object referenced in subname
* is obtained by searching the owner document of obj,
* otherwise the subname search among obj's sub-objects.
*
* @return Return output.c_str() if the subname is modified for exporting
* otherwise, return the input subname
*
* @sa importSubName(), restoreLabelReference()
*
* The function go through the input subname reference and changes any sub
* object references inside for exporting. If the sub object is referenced
* by its internal object name, then the reference is changed from
* 'objName' to 'objName@docName'. If referenced by label, then it will be
* changed to 'objName@docName@' instead. importSubName() and
* restoreLabelReference() can be used together to restore the reference
* during import.
*/
static const char *exportSubName(std::string &output,
const App::DocumentObject *obj, const char *subname, bool first_obj=false);
/** Helper function to import a subname reference
*
* @param reader: the import reader
* @param sub: input subname reference
* @param restoreLabel: output indicate whether post process is required
* after restore.
*
* @sa exportSubName(), restoreLabelReference()
*
* @return return either an updated subname reference or the input
* reference if no change. If restoreLabel is set to true on output, it
* means there are some label reference changes that must be corrected
* after restore, by calling restoreLabelReference() in property's
* afterRestore().
*/
static std::string importSubName(Base::XMLReader &reader, const char *sub, bool &restoreLabel);
/** Helper function to restore label references during import
*
* @param obj: linked object
* @param sub: subname reference
* @param shadow: optional shadow subname reference
*
* @sa exportSubName(), importSubName()
*
* When exporting and importing (i.e. copy and paste) objects into the same
* document, the new object must be renamed, both the internal name and the
* label. Therefore, the link reference of the new objects must be
* corrected accordingly. The basic idea is that when exporting object, all
* object name references are changed to 'objName@docName', and label
* references are changed to 'objName@docName@'. During import,
* MergeDocument will maintain a map from objName@docName to object's new
* name. Object name reference can be restored on spot by consulting the
* map, while label reference will be restored later in property's
* afterRestore() function, which calls this function to do the string
* parsing.
*/
static void restoreLabelReference(const App::DocumentObject *obj, std::string &sub, ShadowSub *shadow=nullptr);
/** Helper function to extract labels from a subname reference
*
* @param labels: output vector of extracted labels
* @param subname: subname reference
*
* @sa registerLabelReferences()
*
* This function is used to extract label from subname reference for
* registering of label changes.
*/
static void getLabelReferences(std::vector<std::string> &labels, const char *subname);
/** Helper function to collect changed property when an object re-label
*
* @param obj: the object that owns the label
* @param newLabel: the new label
*
* @return return a map from the affected property to a copy of it with
* updated subname references
*/
static std::vector<std::pair<Property*, std::unique_ptr<Property> > > updateLabelReferences(
App::DocumentObject *obj, const char *newLabel);
/** Helper function to update subname reference on label change
*
* @param linked: linked object
* @param subname: subname reference
* @param obj: the object that owns the label
* @param ref: label reference in the format of '$<old_label>.', which is
* the format used in subname reference for label reference.
* This parameter is provided for easy search of label
* reference.
* @param newLabel: new label
*
* @return Returns an updated subname reference, or empty string if no change.
*
* This function helps to update subname reference on label change. It is
* usually called inside CopyOnLabelChange(), the API for handling label
* change, which is called just before label change. In other word, when
* called, the sub object can still be reached using the original label
* references, but not the new labels.
*/
static std::string updateLabelReference(const App::DocumentObject *linked, const char *subname,
App::DocumentObject *obj, const std::string &ref, const char *newLabel);
//@}
enum LinkFlags {
LinkAllowExternal,
LinkDetached,
LinkRestoring,
LinkAllowPartial,
LinkRestoreLabel,
LinkSyncSubObject, // used by DlgPropertyLink
};
inline bool testFlag(int flag) const {
return _Flags.test((std::size_t)flag);
}
virtual void setAllowPartial(bool enable) { (void)enable; }
protected:
void hasSetValue() override;
protected:
std::bitset<32> _Flags;
inline void setFlag(int flag, bool value=true) {
_Flags.set((std::size_t)flag,value);
}
private:
std::set<std::string> _LabelRefs;
std::set<App::DocumentObject*> _ElementRefs;
};
/** The general Link Property
* Main Purpose of this property is to Link Objects and Features in a document. Like all links this
* property is scope aware, meaning it does define which objects are allowed to be linked depending
* of the GeoFeatureGroup where it is in. Default is Local.
*
* @note Links that are invalid in respect to the scope of this property is set to are not rejected.
* They are only detected to be invalid and prevent the feature from recomputing.
*/
class AppExport PropertyLink : public PropertyLinkBase
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
/**
* A constructor.
* A more elaborate description of the constructor.
*/
PropertyLink();
/**
* A destructor.
* A more elaborate description of the destructor.
*/
~PropertyLink() override;
void resetLink();
/** Sets the property
*/
virtual void setValue(App::DocumentObject *);
/** This method returns the linked DocumentObject
*/
App::DocumentObject * getValue() const;
/** Returns the link type checked
*/
App::DocumentObject * getValue(Base::Type t) const;
/** Returns the link type checked
*/
template <typename _type>
inline _type getValue() const {
return _pcLink ? dynamic_cast<_type>(_pcLink) : 0;
}
PyObject *getPyObject() override;
void setPyObject(PyObject *) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
unsigned int getMemSize () const override {
return sizeof(App::DocumentObject *);
}
const char* getEditorName() const override
{ return "Gui::PropertyEditor::PropertyLinkItem"; }
void getLinks(std::vector<App::DocumentObject *> &objs,
bool all=false, std::vector<std::string> *subs=nullptr, bool newStyle=true) const override;
void breakLink(App::DocumentObject *obj, bool clear) override;
bool adjustLink(const std::set<App::DocumentObject *> &inList) override;
Property *CopyOnLinkReplace(const App::DocumentObject *parent,
App::DocumentObject *oldObj, App::DocumentObject *newObj) const override;
protected:
App::DocumentObject *_pcLink;
};
/** The general Link Property with Child scope
*/
class AppExport PropertyLinkChild : public PropertyLink
{
TYPESYSTEM_HEADER();
public:
PropertyLinkChild() {_pcScope = LinkScope::Child;}
};
/** The general Link Property with Global scope
*/
class AppExport PropertyLinkGlobal : public PropertyLink
{
TYPESYSTEM_HEADER();
public:
PropertyLinkGlobal() {_pcScope = LinkScope::Global;}
};
/** The general Link Property that are hidden from dependency checking
*/
class AppExport PropertyLinkHidden : public PropertyLink
{
TYPESYSTEM_HEADER();
public:
PropertyLinkHidden() {_pcScope = LinkScope::Hidden;}
};
class AppExport PropertyLinkListBase: public PropertyLinkBase, public PropertyListsBase
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
void setPyObject(PyObject *obj) override {
_setPyObject(obj);
}
};
class AppExport PropertyLinkList :
public PropertyListsT<DocumentObject*,std::vector<DocumentObject*>, PropertyLinkListBase>
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
using inherited = PropertyListsT<DocumentObject*,std::vector<DocumentObject*>,PropertyLinkListBase>;
public:
/**
* A constructor.
* A more elaborate description of the constructor.
*/
PropertyLinkList();
/**
* A destructor.
* A more elaborate description of the destructor.
*/
~PropertyLinkList() override;
void setSize(int newSize) override;
void setSize(int newSize, const_reference def) override;
/** Sets the property
*/
void setValues(const std::vector<DocumentObject*>&) override;
void set1Value(int idx, DocumentObject * const &value) override;
PyObject *getPyObject() override;
void Save(Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
unsigned int getMemSize() const override;
const char* getEditorName() const override
{ return "Gui::PropertyEditor::PropertyLinkListItem"; }
void getLinks(std::vector<App::DocumentObject *> &objs,
bool all=false, std::vector<std::string> *subs=nullptr, bool newStyle=true) const override;
void breakLink(App::DocumentObject *obj, bool clear) override;
bool adjustLink(const std::set<App::DocumentObject *> &inList) override;
Property *CopyOnLinkReplace(const App::DocumentObject *parent,
App::DocumentObject *oldObj, App::DocumentObject *newObj) const override;
DocumentObject *find(const std::string &, int *pindex=nullptr) const;
DocumentObject *find(const char *sub, int *pindex=nullptr) const {
if(!sub) return nullptr;
return find(std::string(sub),pindex);
}
protected:
DocumentObject *getPyValue(PyObject *item) const override;
protected:
mutable std::map<std::string, int> _nameMap;
};
/** The general Link Property with Child scope
*/
class AppExport PropertyLinkListChild : public PropertyLinkList
{
TYPESYSTEM_HEADER();
public:
PropertyLinkListChild() {_pcScope = LinkScope::Child;}
};
/** The general Link Property with Global scope
*/
class AppExport PropertyLinkListGlobal : public PropertyLinkList
{
TYPESYSTEM_HEADER();
public:
PropertyLinkListGlobal() {_pcScope = LinkScope::Global;}
};
/** The general Link Property that are hidden from dependency checking
*/
class AppExport PropertyLinkListHidden : public PropertyLinkList
{
TYPESYSTEM_HEADER();
public:
PropertyLinkListHidden() {_pcScope = LinkScope::Hidden;}
};
/** the Link Property with sub elements
* This property links an object and a defined sequence of
* sub elements. These subelements (like Edges of a Shape)
* are stored as names, which can be resolved by the
* ComplexGeoDataType interface to concrete sub objects.
*/
class AppExport PropertyLinkSub : public PropertyLinkBase
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
/**
* A constructor.
* A more elaborate description of the constructor.
*/
PropertyLinkSub();
/**
* A destructor.
* A more elaborate description of the destructor.
*/
~PropertyLinkSub() override;
void afterRestore() override;
void onContainerRestored() override;
/** Sets the property
*/
void setValue(App::DocumentObject *,const std::vector<std::string> &SubList,
std::vector<ShadowSub> &&ShadowSubList={});
void setValue(App::DocumentObject *,std::vector<std::string> &&SubList={},
std::vector<ShadowSub> &&ShadowSubList={});
/** This method returns the linked DocumentObject
*/
App::DocumentObject * getValue() const;
/// return the list of sub elements
const std::vector<std::string>& getSubValues() const;
/// return the list of sub elements with mapped names
const std::vector<ShadowSub> &getShadowSubs() const {
return _ShadowSubList;
}
std::vector<std::string> getSubValues(bool newStyle) const;
/// return the list of sub elements starts with a special string
std::vector<std::string> getSubValuesStartsWith(const char*, bool newStyle=false) const;
/** Returns the link type checked
*/
App::DocumentObject * getValue(Base::Type t) const;
/** Returns the link type checked
*/
template <typename _type>
inline _type getValue() const {
return _pcLinkSub ? dynamic_cast<_type>(_pcLinkSub) : 0;
}
PyObject *getPyObject() override;
void setPyObject(PyObject *) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
Property *Copy() const override;
void Paste(const Property &from) override;
const char* getEditorName() const override
{ return "Gui::PropertyEditor::PropertyLinkItem"; }
/// Return a copy of the property if any changes caused by importing external object
Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const override;
Property *CopyOnLabelChange(App::DocumentObject *obj,
const std::string &ref, const char *newLabel) const override;
Property *CopyOnLinkReplace(const App::DocumentObject *parent,
App::DocumentObject *oldObj, App::DocumentObject *newObj) const override;
unsigned int getMemSize () const override {
return sizeof(App::DocumentObject *);
}
void updateElementReference(
DocumentObject *feature,bool reverse=false, bool notify=false) override;
bool referenceChanged() const override;
void getLinks(std::vector<App::DocumentObject *> &objs,
bool all=false, std::vector<std::string> *subs=nullptr, bool newStyle=true) const override;
void breakLink(App::DocumentObject *obj, bool clear) override;
bool adjustLink(const std::set<App::DocumentObject *> &inList) override;
void setSyncSubObject(bool enable);
protected:
App::DocumentObject* _pcLinkSub;
std::vector<std::string> _cSubList;
std::vector<ShadowSub> _ShadowSubList;
std::vector<int> _mapped;
bool _restoreLabel;
};
/** The general Link Property with Child scope
*/
class AppExport PropertyLinkSubChild : public PropertyLinkSub
{
TYPESYSTEM_HEADER();
public:
PropertyLinkSubChild() {_pcScope = LinkScope::Child;}
};
/** The general Link Property with Global scope
*/
class AppExport PropertyLinkSubGlobal : public PropertyLinkSub
{
TYPESYSTEM_HEADER();
public:
PropertyLinkSubGlobal() {_pcScope = LinkScope::Global;}
};
/** The general Link Property that are hidden from dependency checking
*/
class AppExport PropertyLinkSubHidden : public PropertyLinkSub
{
TYPESYSTEM_HEADER();
public:
PropertyLinkSubHidden() {_pcScope = LinkScope::Hidden;}
};
class AppExport PropertyLinkSubList : public PropertyLinkBase
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
public:
using SubSet = std::pair<DocumentObject*, std::vector<std::string> >;
/**
* A constructor.
* A more elaborate description of the constructor.
*/
PropertyLinkSubList();
/**
* A destructor.
* A more elaborate description of the destructor.
*/
~PropertyLinkSubList() override;
void afterRestore() override;
void onContainerRestored() override;
int getSize() const;
void setSize(int newSize);
/** Sets the property.
* setValue(0, whatever) clears the property
*/
void setValue(DocumentObject*,const char*);
void setValues(const std::vector<DocumentObject*>&,const std::vector<const char*>&);
void setValues(const std::vector<DocumentObject*>&,const std::vector<std::string>&,
std::vector<ShadowSub> &&ShadowSubList={});
void setValues(std::vector<DocumentObject*>&&, std::vector<std::string> &&subs,
std::vector<ShadowSub> &&ShadowSubList={});
/**
* @brief setValue: PropertyLinkSub-compatible overload
* @param SubList
*/
void setValue(App::DocumentObject *lValue, const std::vector<std::string> &SubList=std::vector<std::string>());
void addValue(App::DocumentObject *obj, const std::vector<std::string> &SubList={}, bool reset = false);
const std::vector<DocumentObject*> &getValues() const {
return _lValueList;
}
const std::string getPyReprString() const;
/**
* @brief getValue emulates the action of a single-object link.
* @return reference to object, if the link is to only one object. NULL if
* the link is empty, or links to subelements of more than one document
* object.
*/
DocumentObject* getValue() const;
const std::vector<std::string> &getSubValues() const {
return _lSubList;
}
std::vector<std::string> getSubValues(bool newStyle) const;
const std::vector<ShadowSub> &getShadowSubs() const {
return _ShadowSubList;
}
/**
* @brief Removes all occurrences of \a lValue in the property
* together with its sub-elements and returns the number of entries removed.
*/
int removeValue(App::DocumentObject *lValue);
void setSubListValues(const std::vector<SubSet>&);
std::vector<SubSet> getSubListValues(bool newStyle=false) const;
PyObject *getPyObject() override;
void setPyObject(PyObject *) override;
void Save (Base::Writer &writer) const override;
void Restore(Base::XMLReader &reader) override;
bool upgrade(Base::XMLReader &reader, const char *typeName);
Property *Copy() const override;
void Paste(const Property &from) override;
const char* getEditorName() const override
{ return "Gui::PropertyEditor::PropertyLinkListItem"; }
/// Return a copy of the property if any changes caused by importing external object
Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const override;
Property *CopyOnLabelChange(App::DocumentObject *obj,
const std::string &ref, const char *newLabel) const override;
Property *CopyOnLinkReplace(const App::DocumentObject *parent,
App::DocumentObject *oldObj, App::DocumentObject *newObj) const override;
unsigned int getMemSize () const override;
void updateElementReference(
DocumentObject *feature,bool reverse=false, bool notify=false) override;
bool referenceChanged() const override;