Merge branch 'main' into bgbsww-toponamingAddFeatureRefine

This commit is contained in:
bgbsww
2024-09-27 16:26:27 -04:00
committed by GitHub
802 changed files with 43326 additions and 39055 deletions
@@ -78,7 +78,7 @@ jobs:
with:
activate-environment: .conda/freecad
environment-file: conda/conda-env.yaml
channels: conda-forge,defaults
channels: conda-forge
channel-priority: true
miniforge-version: latest
- name: Install FreeCAD dependencies
@@ -78,7 +78,7 @@ jobs:
with:
activate-environment: .conda/freecad
environment-file: conda/conda-env.yaml
channels: conda-forge,defaults
channels: conda-forge
channel-priority: true
miniforge-version: latest
- name: Install FreeCAD dependencies
@@ -76,7 +76,7 @@ jobs:
with:
activate-environment: .conda/freecad
environment-file: conda/conda-env.yaml
channels: conda-forge,defaults
channels: conda-forge
channel-priority: true
miniforge-version: latest
- name: Install FreeCAD dependencies
@@ -76,7 +76,7 @@ jobs:
with:
activate-environment: .conda/freecad
environment-file: conda/conda-env-qt6.yaml
channels: conda-forge,defaults
channels: conda-forge
channel-priority: true
miniforge-version: latest
- name: Install FreeCAD dependencies
+1 -1
View File
@@ -71,7 +71,7 @@ jobs:
with:
activate-environment: .conda/freecad
environment-file: conda/conda-env.yaml
channels: conda-forge,defaults
channels: conda-forge
channel-priority: true
miniforge-version: latest
- name: Install FreeCAD dependencies
+4
View File
@@ -151,6 +151,10 @@
},
"cmakeExecutable": "${sourceDir}/conda/cmake.sh",
"cacheVariables": {
"CMAKE_IGNORE_PREFIX_PATH": {
"type": "STRING",
"value": "/opt/homebrew;/usr/local/homebrew"
},
"CMAKE_INCLUDE_PATH": {
"type": "FILEPATH",
"value": "${sourceDir}/.conda/freecad/include"
@@ -34,6 +34,7 @@ macro(SetGlobalCompilerAndLinkerSettings)
if(FREECAD_RELEASE_PDB)
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
set (CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG")
set (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG")
endif(FREECAD_RELEASE_PDB)
if(FREECAD_RELEASE_SEH)
# remove /EHsc or /EHs flags because they are incompatible with /EHa
+1
View File
@@ -2,6 +2,7 @@ name: freecad
channels:
- conda-forge
dependencies:
- conda-forge/noarch::conda-libmamba-solver==24.7.0
- conda-devenv
- mamba
- python==3.12.*
+1
View File
@@ -2,6 +2,7 @@ name: freecad
channels:
- conda-forge
dependencies:
- conda-forge/noarch::conda-libmamba-solver==24.7.0
- conda-devenv
- mamba
- python==3.11.*
+1
View File
@@ -3,6 +3,7 @@ channels:
- conda-forge
- conda-forge/label/pivy_rc
dependencies:
- conda-forge/noarch::conda-libmamba-solver==24.7.0
- libspnav # [linux]
- kernel-headers_linux-64 # [linux and x86_64]
- libdrm-cos7-x86_64 # [linux and x86_64]
+1
View File
@@ -2,6 +2,7 @@ name: freecad
channels:
- conda-forge
dependencies:
- conda-forge/noarch::conda-libmamba-solver==24.7.0
- libspnav # [linux]
- kernel-headers_linux-64 # [linux and x86_64]
- libdrm-cos6-x86_64 # [linux and x86_64]
+4
View File
@@ -427,6 +427,10 @@ void Application::setupPythonException(PyObject* module)
Base::PyExc_FC_PropertyError = PyErr_NewException("Base.PropertyError", PyExc_AttributeError, nullptr);
Py_INCREF(Base::PyExc_FC_PropertyError);
PyModule_AddObject(module, "PropertyError", Base::PyExc_FC_PropertyError);
Base::PyExc_FC_AbortIOException = PyErr_NewException("Base.PyExc_FC_AbortIOException", PyExc_BaseException, nullptr);
Py_INCREF(Base::PyExc_FC_AbortIOException);
PyModule_AddObject(module, "AbortIOException", Base::PyExc_FC_AbortIOException);
}
// clang-format on
+1
View File
@@ -1475,6 +1475,7 @@ Document::readObjects(Base::XMLReader& reader)
void Document::addRecomputeObject(DocumentObject *obj) {
if(testStatus(Status::Restoring) && obj) {
setStatus(Status::RecomputeOnRestore, true);
d->touchedObjs.insert(obj);
obj->touch();
}
+1
View File
@@ -77,6 +77,7 @@ public:
RestoreError = 10,
LinkStampChanged = 11, // Indicates during restore time if any linked document's time stamp has changed
IgnoreErrorOnRecompute = 12, // Don't report errors if the recompute failed
RecomputeOnRestore = 13, // Mark pending recompute on restore for migration purposes
};
/** @name Properties */
+6
View File
@@ -442,6 +442,12 @@ public:
/* Return true to cause PropertyView to show linked object's property */
virtual bool canLinkProperties() const {return true;}
/* Return whether this object is a link */
virtual bool isLink() const {return false;};
/* Return whether this object is a link group */
virtual bool isLinkGroup() const {return false;};
/* Return true to bypass duplicate label checking */
virtual bool allowDuplicateLabel() const {return false;}
+12
View File
@@ -56,6 +56,18 @@ For a temporary document it returns its transient directory.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="getUniqueObjectName">
<Documentation>
<UserDocu>getUniqueObjectName(objName) -> objName
Return the same name, or the name made unique, for Example Box -> Box002 if there are conflicting name
already in the document.
ObjName : str
Object name.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="mergeProject">
<Documentation>
<UserDocu>Merges this document with another project file</UserDocu>
+12
View File
@@ -217,6 +217,18 @@ PyObject* DocumentPy::getFileName(PyObject* args)
return Py::new_reference_to(Py::String(fn));
}
PyObject* DocumentPy::getUniqueObjectName(PyObject *args)
{
char *sName;
if (!PyArg_ParseTuple(args, "s", &sName))
return nullptr;
PY_TRY {
auto newName = getDocumentPtr()->getUniqueObjectName(sName);
return Py::new_reference_to(Py::String(newName));
}
PY_CATCH;
}
PyObject* DocumentPy::mergeProject(PyObject * args)
{
char* filename;
+63 -1
View File
@@ -25,6 +25,8 @@
#include <App/GeoFeaturePy.h>
#include <Base/Tools.h>
#include "ComplexGeoData.h"
#include "Document.h"
#include "GeoFeature.h"
@@ -157,7 +159,7 @@ DocumentObject *GeoFeature::resolveElement(DocumentObject *obj, const char *subn
}
if(geoFeature)
*geoFeature = geo;
if(!obj || (filter && obj!=filter))
if(filter && geo!=filter)
return nullptr;
if(!element || !element[0]) {
if(append)
@@ -270,3 +272,63 @@ GeoFeature::getHigherElements(const char *element, bool silent) const
return {};
return prop->getComplexData()->getHigherElements(element, silent);
}
Base::Placement GeoFeature::getPlacementFromProp(App::DocumentObject* obj, const char* propName)
{
Base::Placement plc = Base::Placement();
auto* propPlacement = dynamic_cast<App::PropertyPlacement*>(obj->getPropertyByName(propName));
if (propPlacement) {
plc = propPlacement->getValue();
}
return plc;
}
Base::Placement GeoFeature::getGlobalPlacement(App::DocumentObject* targetObj,
App::DocumentObject* rootObj,
const std::string& sub)
{
if (!targetObj || !rootObj || sub.empty()) {
return Base::Placement();
}
std::vector<std::string> names = Base::Tools::splitSubName(sub);
App::Document* doc = rootObj->getDocument();
Base::Placement plc = getPlacementFromProp(rootObj, "Placement");
if (targetObj == rootObj) return plc;
for (auto& name : names) {
App::DocumentObject* obj = doc->getObject(name.c_str());
if (!obj) {
return Base::Placement();
}
plc = plc * getPlacementFromProp(obj, "Placement");
if (obj == targetObj) {
return plc;
}
if (obj->isLink()) {
// Update doc in case its an external link.
doc = obj->getLinkedObject()->getDocument();
}
}
// If targetObj has not been found there's a problem
return Base::Placement();
}
Base::Placement GeoFeature::getGlobalPlacement(App::DocumentObject* targetObj,
App::PropertyXLinkSub* prop)
{
if (!targetObj || !prop) {
return Base::Placement();
}
std::vector<std::string> subs = prop->getSubValues();
if (subs.empty()) {
return Base::Placement();
}
return getGlobalPlacement(targetObj, prop->getValue(), subs[0]);
}
+4
View File
@@ -179,6 +179,10 @@ public:
/// Return the higher level element names of the given element
virtual std::vector<Data::IndexedName> getHigherElements(const char *name, bool silent=false) const;
static Base::Placement getPlacementFromProp(DocumentObject* obj, const char* propName);
static Base::Placement getGlobalPlacement(DocumentObject* targetObj, DocumentObject* rootObj, const std::string& sub);
static Base::Placement getGlobalPlacement(DocumentObject* targetObj, PropertyXLinkSub* prop);
protected:
void onChanged(const Property* prop) override;
// void onDocumentRestored() override;
+15
View File
@@ -2282,6 +2282,16 @@ bool Link::canLinkProperties() const {
return true;
}
bool Link::isLink() const
{
return ElementCount.getValue() == 0;
}
bool Link::isLinkGroup() const
{
return ElementCount.getValue() > 0;
}
//////////////////////////////////////////////////////////////////////////////////////////
namespace App {
@@ -2309,6 +2319,11 @@ bool LinkElement::canDelete() const {
return !owner || !owner->getDocument()->getObjectByID(_LinkOwner.getValue());
}
bool LinkElement::isLink() const
{
return true;
}
App::Link* LinkElement::getLinkGroup() const
{
std::vector<App::DocumentObject*> inList = getInList();
+6
View File
@@ -556,6 +556,10 @@ public:
}
bool canLinkProperties() const override;
bool isLink() const override;
bool isLinkGroup() const override;
};
using LinkPython = App::FeaturePythonT<Link>;
@@ -600,6 +604,8 @@ public:
_handleChangedPropertyName(reader,TypeName,PropName);
}
bool isLink() const override;
App::Link* getLinkGroup() const;
};
+11
View File
@@ -3018,6 +3018,17 @@ void PropertyMaterialList::setTransparency(int index, float val)
hasSetValue();
}
void PropertyMaterialList::setTransparencies(const std::vector<float>& transparencies)
{
aboutToSetValue();
setSize(transparencies.size(), _lValueList[0]);
for (std::size_t i = 0; i < transparencies.size(); i++) {
_lValueList[i].transparency = transparencies[i];
}
hasSetValue();
}
const Color& PropertyMaterialList::getAmbientColor() const
{
return _lValueList[0].ambientColor;
+1
View File
@@ -1156,6 +1156,7 @@ public:
void setTransparency(float);
void setTransparency(int index, float);
void setTransparencies(const std::vector<float>& transparencies);
const Color& getAmbientColor() const;
const Color& getAmbientColor(int index) const;
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation type="unfinished"></translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Без назвы</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Sense nom</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ které odkazují na stejný konfigurovatelný objekt</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Nepojmenovaný</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Unavngivet</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ angewendet werden soll, die das gleiche konfigurierbare Objekt referenzieren</tr
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Unbenannt</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Ανώνυμο</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ que hacen referencia al mismo objeto configurable</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Sin nombre</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Sin nombre</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Izenik gabea</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ that reference the same configurable object</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Nimetön</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Nouveau</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ na sve veze koje referenciraju isti konfigurabilni objekt</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Neimenovano</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ amelyek ugyanarra a konfigurálható tárgyra hivatkoznak</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Névtelen</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ che fanno riferimento allo stesso oggetto configurabile</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Senza nome</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>名称未設定</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>უსახელო</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>이름없음</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Be pavadinimo</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ die verwijzen naar hetzelfde configureerbare object</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Naamloos</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ które odnoszą się do tego samego obiektu konfigurowalnego</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Nienazwany</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ que referenciam o mesmo objeto configurável</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Sem nome</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ that reference the same configurable object</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Sem nome</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ care fac referire la același obiect configurabil</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Nedenumit</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Безымянный</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ za vse povezave, ki se sklicujejo na isti nastavljivi predmet</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Neimenovan</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ that reference the same configurable object</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Bez imena</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Без имена</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ that reference the same configurable object</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Namnlös</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ uygulanmayacağına ilişkin son kullanıcı seçimini saklar</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>İsimsiz</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Без назви</translation>
</message>
+1 -1
View File
@@ -14,7 +14,7 @@ that reference the same configurable object</translation>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>Sense nom</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>未命名</translation>
</message>
+1 -1
View File
@@ -13,7 +13,7 @@ that reference the same configurable object</source>
<context>
<name>QObject</name>
<message>
<location filename="../../Application.cpp" line="459"/>
<location filename="../../Application.cpp" line="463"/>
<source>Unnamed</source>
<translation>未命名</translation>
</message>
+1 -1
View File
@@ -50,7 +50,7 @@
#endif
#include <boost/algorithm/string.hpp>
#include "fmt/printf.h"
#include <fmt/printf.h>
#include "Parameter.h"
#include "Parameter.inl"
+1
View File
@@ -49,6 +49,7 @@ PyObject* Base::PyExc_FC_ExpressionError = nullptr;
PyObject* Base::PyExc_FC_ParserError = nullptr;
PyObject* Base::PyExc_FC_CADKernelError = nullptr;
PyObject* Base::PyExc_FC_PropertyError = nullptr;
PyObject* Base::PyExc_FC_AbortIOException = nullptr;
typedef struct { //NOLINT
PyObject_HEAD
+1
View File
@@ -431,6 +431,7 @@ BaseExport extern PyObject* PyExc_FC_ExpressionError;
BaseExport extern PyObject* PyExc_FC_ParserError;
BaseExport extern PyObject* PyExc_FC_CADKernelError;
BaseExport extern PyObject* PyExc_FC_PropertyError;
BaseExport extern PyObject* PyExc_FC_AbortIOException;
/** Exception handling for python callback functions
* Is a convenience macro to manage the exception handling of python callback
+4
View File
@@ -181,6 +181,8 @@ bool Base::XMLReader::read()
void Base::XMLReader::readElement(const char* ElementName)
{
bool ok {};
endCharStream();
int currentLevel = Level;
std::string currentName = LocalName;
do {
@@ -248,6 +250,8 @@ bool Base::XMLReader::isEndOfDocument() const
void Base::XMLReader::readEndElement(const char* ElementName, int level)
{
endCharStream();
// if we are already at the end of the current element
if ((ReadType == EndElement || ReadType == StartEndElement) && ElementName
&& LocalName == ElementName && (level < 0 || level == Level)) {
+2 -2
View File
@@ -6,12 +6,12 @@
<message>
<location filename="../../UnitsApi.cpp" line="69"/>
<source>Standard (mm, kg, s, °)</source>
<translation type="unfinished">Standard (mm, kg, s, °)</translation>
<translation>Estandarra (mm, kg, s, °)</translation>
</message>
<message>
<location filename="../../UnitsApi.cpp" line="71"/>
<source>MKS (m, kg, s, °)</source>
<translation type="unfinished">MKS (m, kg, s, °)</translation>
<translation>MKS (m, kg, s, °)</translation>
</message>
<message>
<location filename="../../UnitsApi.cpp" line="73"/>
@@ -11,7 +11,7 @@
<message>
<location filename="../../UnitsApi.cpp" line="71"/>
<source>MKS (m, kg, s, °)</source>
<translation type="unfinished">MKS (m, kg, s, °)</translation>
<translation>MKS (m, kg, s, °)</translation>
</message>
<message>
<location filename="../../UnitsApi.cpp" line="73"/>
@@ -36,7 +36,7 @@
<message>
<location filename="../../UnitsApi.cpp" line="81"/>
<source>Metric small parts &amp; CNC (mm, mm/min)</source>
<translation type="unfinished">Metric small parts &amp; CNC (mm, mm/min)</translation>
<translation>公制小零件 &amp; CNC (mm, mm/min)</translation>
</message>
<message>
<location filename="../../UnitsApi.cpp" line="83"/>
@@ -46,7 +46,7 @@
<message>
<location filename="../../UnitsApi.cpp" line="85"/>
<source>FEM (mm, N, s)</source>
<translation type="unfinished">FEM (mm, N, s)</translation>
<translation>FEM (mm, N, s)</translation>
</message>
<message>
<location filename="../../UnitsApi.cpp" line="87"/>
+21
View File
@@ -372,3 +372,24 @@ std::string Base::Tools::currentDateTimeString()
.toString(Qt::ISODate)
.toStdString();
}
std::vector<std::string> Base::Tools::splitSubName(const std::string& subname)
{
// Turns 'Part.Part001.Body.Pad.Edge1'
// Into ['Part', 'Part001', 'Body', 'Pad', 'Edge1']
std::vector<std::string> subNames;
std::string subName;
std::istringstream subNameStream(subname);
while (std::getline(subNameStream, subName, '.')) {
subNames.push_back(subName);
}
// Check if the last character of the input string is the delimiter.
// If so, add an empty string to the subNames vector.
// Because the last subname is the element name and can be empty.
if (!subname.empty() && subname.back() == '.') {
subNames.push_back(""); // Append empty string for trailing dot.
}
return subNames;
}
+2
View File
@@ -325,6 +325,8 @@ struct BaseExport Tools
static std::string joinList(const std::vector<std::string>& vec, const std::string& sep = ", ");
static std::string currentDateTimeString();
static std::vector<std::string> splitSubName(const std::string& subname);
};
+1
View File
@@ -28,6 +28,7 @@ configure_file(__init__.py.template ${NAMESPACE_INIT})
set(EXT_FILES
freecad_doc.py
module_io.py
part.py
partdesign.py
project_utility.py
+13
View File
@@ -0,0 +1,13 @@
def OpenInsertObject(importerModule, objectPath, importMethod, docName = ""):
try:
importArgs = []
importKwargs = {}
if docName:
importArgs.append(docName)
if hasattr(importerModule, "importOptions"):
importKwargs["options"] = importerModule.importOptions(objectPath)
getattr(importerModule, importMethod)(objectPath, *importArgs, **importKwargs)
except PyExc_FC_AbortIOException:
pass
+72 -37
View File
@@ -379,7 +379,6 @@ Application::Application(bool GUIenabled)
App::GetApplication().signalShowHidden.connect(
std::bind(&Gui::Application::slotShowHidden, this, sp::_1));
// NOLINTEND
// install the last active language
ParameterGrp::handle hPGrp = App::GetApplication().GetUserParameter().GetGroup("BaseApp");
hPGrp = hPGrp->GetGroup("Preferences")->GetGroup("General");
@@ -596,6 +595,7 @@ Application::~Application()
// creating std commands
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void Application::open(const char* FileName, const char* Module)
{
WaitCursor wc;
@@ -633,22 +633,25 @@ void Application::open(const char* FileName, const char* Module)
Command::doCommand(Command::App,
"FreeCAD.openDocument('%s')",
unicodepath.c_str());
Gui::Application::checkForRecomputes();
}
}
else {
// issue module loading
Command::doCommand(Command::App, "import %s", Module);
// check for additional import options
std::stringstream str;
str << "if hasattr(" << Module << ", \"importOptions\"):\n"
<< " options = " << Module << ".importOptions(u\"" << unicodepath << "\")\n"
<< " " << Module << ".open(u\"" << unicodepath << "\", options = options)\n"
<< "else:\n"
<< " " << Module << ".open(u\"" << unicodepath << "\")\n";
std::string code = str.str();
Gui::Command::runCommand(Gui::Command::App, code.c_str());
// Load using provided python module
{
Base::PyGILStateLocker locker;
Py::Module moduleIo(PyImport_ImportModule("freecad.module_io"));
const auto dictS = moduleIo.getDict().keys().as_string();
if (!moduleIo.isNull() && moduleIo.hasAttr("OpenInsertObject"))
{
const Py::TupleN args(
Py::Module(PyImport_ImportModule(Module)),
Py::String(unicodepath),
Py::String("open")
);
moduleIo.callMemberFunction("OpenInsertObject", args);
}
}
// ViewFit
if (sendHasMsgToActiveView("ViewFit")) {
@@ -713,30 +716,22 @@ void Application::importFrom(const char* FileName, const char* DocName, const ch
}
}
// check for additional import options
std::stringstream str;
if (DocName) {
str << "if hasattr(" << Module << ", \"importOptions\"):\n"
<< " options = " << Module << ".importOptions(u\"" << unicodepath
<< "\")\n"
<< " " << Module << ".insert(u\"" << unicodepath << "\", \"" << DocName
<< "\", options = options)\n"
<< "else:\n"
<< " " << Module << ".insert(u\"" << unicodepath << "\", \"" << DocName
<< "\")\n";
// Load using provided python module
{
Base::PyGILStateLocker locker;
Py::Module moduleIo(PyImport_ImportModule("freecad.module_io"));
const auto dictS = moduleIo.getDict().keys().as_string();
if (!moduleIo.isNull() && moduleIo.hasAttr("OpenInsertObject"))
{
const Py::TupleN args(
Py::Module(PyImport_ImportModule(Module)),
Py::String(unicodepath),
Py::String("insert"),
Py::String(DocName)
);
moduleIo.callMemberFunction("OpenInsertObject", args);
}
}
else {
str << "if hasattr(" << Module << ", \"importOptions\"):\n"
<< " options = " << Module << ".importOptions(u\"" << unicodepath
<< "\")\n"
<< " " << Module << ".insert(u\"" << unicodepath
<< "\", options = options)\n"
<< "else:\n"
<< " " << Module << ".insert(u\"" << unicodepath << "\")\n";
}
std::string code = str.str();
Gui::Command::runCommand(Gui::Command::App, code.c_str());
// Commit the transaction
if (doc && !pendingCommand) {
@@ -978,6 +973,46 @@ void Application::slotShowHidden(const App::Document& Doc)
signalShowHidden(*doc->second);
}
void Application::checkForRecomputes() {
std::vector<App::Document *> docs;
for (auto doc: App::GetApplication().getDocuments()) {
if (doc->testStatus(App::Document::RecomputeOnRestore)) {
docs.push_back(doc);
doc->setStatus(App::Document::RecomputeOnRestore, false);
}
}
// Certain tests want to use very old .FCStd files. We should not prompt during those tests, so this
// allows them to 'FreeCAD.ConfigSet("SuppressRecomputeRequiredDialog", "True")`
const std::map<std::string, std::string>& Map = App::Application::Config();
auto value = Map.find("SuppressRecomputeRequiredDialog");
bool skip = value != Map.end() && ! value->second.empty(); // Any non empty string is true.
if (docs.empty() || skip )
return;
WaitCursor wc;
wc.restoreCursor();
auto res = QMessageBox::warning(getMainWindow(), QObject::tr("Recomputation required"),
QObject::tr("Some document(s) require recomputation for migration purposes. "
"It is highly recommended to perform a recomputation before "
"any modification to avoid compatibility problems.\n\n"
"Do you want to recompute now?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if (res != QMessageBox::Yes)
return;
bool hasError = false;
for (auto doc: App::Document::getDependentDocuments(docs, true)) {
try {
doc->recompute({}, false, &hasError);
} catch (Base::Exception &e) {
e.ReportException();
hasError = true;
}
}
if (hasError)
QMessageBox::critical(getMainWindow(), QObject::tr("Recompute error"),
QObject::tr("Failed to recompute some document(s).\n"
"Please check report view for more details."));
}
void Application::slotActiveDocument(const App::Document& Doc)
{
std::map<const App::Document*, Gui::Document*>::iterator doc = d->documents.find(&Doc);
+4 -2
View File
@@ -28,8 +28,6 @@
#include <map>
#include <string>
#define putpix()
#include <App/Application.h>
class QCloseEvent;
@@ -74,6 +72,8 @@ public:
void exportTo(const char* FileName, const char* DocName, const char* Module);
/// Reload a partial opened document
App::Document *reopen(App::Document *doc);
/// Prompt about recomputing if needed
static void checkForRecomputes();
//@}
@@ -338,6 +338,8 @@ public:
static PyObject* sDoCommand (PyObject *self,PyObject *args);
static PyObject* sDoCommandGui (PyObject *self,PyObject *args);
static PyObject* sDoCommandEval (PyObject *self,PyObject *args);
static PyObject* sDoCommandSkip (PyObject *self,PyObject *args);
static PyObject* sAddModule (PyObject *self,PyObject *args);
static PyObject* sShowDownloads (PyObject *self,PyObject *args);
+50
View File
@@ -316,6 +316,19 @@ PyMethodDef Application::Methods[] = {
"but doesn't record it in macros.\n"
"\n"
"cmd : str"},
{"doCommandEval", (PyCFunction) Application::sDoCommandEval, METH_VARARGS,
"doCommandEval(cmd) -> PyObject\n"
"\n"
"Runs the given string without showing in the python console or recording in\n"
"macros, and returns the result.\n"
"\n"
"cmd : str"},
{"doCommandSkip", (PyCFunction) Application::sDoCommandSkip, METH_VARARGS,
"doCommandSkip(cmd) -> None\n"
"\n"
"Record the given string in the Macro but comment it out in the console\n"
"\n"
"cmd : str"},
{"addModule", (PyCFunction) Application::sAddModule, METH_VARARGS,
"addModule(mod) -> None\n"
"\n"
@@ -1352,6 +1365,43 @@ PyObject* Application::sDoCommandGui(PyObject * /*self*/, PyObject *args)
return PyRun_String(sCmd, Py_file_input, dict, dict);
}
PyObject* Application::sDoCommandEval(PyObject * /*self*/, PyObject *args)
{
char *sCmd = nullptr;
if (!PyArg_ParseTuple(args, "s", &sCmd))
return nullptr;
Gui::Command::LogDisabler d1;
Gui::SelectionLogDisabler d2;
PyObject *module, *dict;
Base::PyGILStateLocker locker;
module = PyImport_AddModule("__main__");
if (!module)
return nullptr;
dict = PyModule_GetDict(module);
if (!dict)
return nullptr;
return PyRun_String(sCmd, Py_eval_input, dict, dict);
}
PyObject* Application::sDoCommandSkip(PyObject * /*self*/, PyObject *args)
{
char *sCmd = nullptr;
if (!PyArg_ParseTuple(args, "s", &sCmd))
return nullptr;
Gui::Command::LogDisabler d1;
Gui::SelectionLogDisabler d2;
Gui::Command::printPyCaller();
Gui::Application::Instance->macroManager()->addLine(MacroManager::App, sCmd);
return Py::None().ptr();
}
PyObject* Application::sAddModule(PyObject * /*self*/, PyObject *args)
{
char *pstr;
+31
View File
@@ -54,6 +54,8 @@ class BitmapFactoryInstP
public:
QMap<std::string, const char**> xpmMap;
QMap<std::string, QPixmap> xpmCache;
bool useIconTheme;
};
}
@@ -93,7 +95,9 @@ void BitmapFactoryInst::destruct ()
BitmapFactoryInst::BitmapFactoryInst()
{
d = new BitmapFactoryInstP;
restoreCustomPaths();
configureUseIconTheme();
}
BitmapFactoryInst::~BitmapFactoryInst()
@@ -111,6 +115,14 @@ void BitmapFactoryInst::restoreCustomPaths()
}
}
void Gui::BitmapFactoryInst::configureUseIconTheme()
{
Base::Reference<ParameterGrp> group = App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/Bitmaps/Theme");
d->useIconTheme = group->GetBool("UseIconTheme", group->GetBool("ThemeSearchPaths", false));
}
void BitmapFactoryInst::addPath(const QString& path)
{
QDir::addSearchPath(QString::fromLatin1("icons"), path);
@@ -174,6 +186,10 @@ bool BitmapFactoryInst::findPixmapInCache(const char* name, QPixmap& px) const
QIcon BitmapFactoryInst::iconFromTheme(const char* name, const QIcon& fallback)
{
if (!d->useIconTheme) {
return iconFromDefaultTheme(name, fallback);
}
QString iconName = QString::fromUtf8(name);
QIcon icon = QIcon::fromTheme(iconName, fallback);
if (icon.isNull()) {
@@ -206,6 +222,21 @@ bool BitmapFactoryInst::loadPixmap(const QString& filename, QPixmap& icon) const
return !icon.isNull();
}
QIcon Gui::BitmapFactoryInst::iconFromDefaultTheme(const char* name, const QIcon& fallback)
{
QIcon icon;
QPixmap px = pixmap(name);
if (!px.isNull()) {
icon.addPixmap(px);
return icon;
} else {
return fallback;
}
return icon;
}
QPixmap BitmapFactoryInst::pixmap(const char* name) const
{
if (!name || *name == '\0')
+5
View File
@@ -75,6 +75,10 @@ public:
* If no such icon is found in the current theme fallback is returned instead.
*/
QIcon iconFromTheme(const char* name, const QIcon& fallback = QIcon());
/** Returns the QIcon corresponding to name in the default (FreeCAD's) icon theme.
* If no such icon is found in the current theme fallback is returned instead.
*/
QIcon iconFromDefaultTheme(const char* name, const QIcon& fallback = QIcon());
/// Retrieves a pixmap by name
QPixmap pixmap(const char* name) const;
/** Retrieves a pixmap by name and size created by an
@@ -150,6 +154,7 @@ public:
private:
bool loadPixmap(const QString& path, QPixmap&) const;
void restoreCustomPaths();
void configureUseIconTheme();
static BitmapFactoryInst* _pcSingleton;
BitmapFactoryInst();
+4
View File
@@ -1318,7 +1318,11 @@ StdCmdDelete::StdCmdDelete()
sWhatsThis = "Std_Delete";
sStatusTip = QT_TR_NOOP("Deletes the selected objects");
sPixmap = "edit-delete";
#ifdef FC_OS_MACOSX
sAccel = "Backspace";
#else
sAccel = keySequenceToAccel(QKeySequence::Delete);
#endif
eType = ForEdit;
}
+1
View File
@@ -117,6 +117,7 @@ struct DocumentP
Connection connectStartLoadDocument;
Connection connectFinishLoadDocument;
Connection connectShowHidden;
Connection connectFinishRestoreDocument;
Connection connectFinishRestoreObject;
Connection connectExportObjects;
Connection connectImportObjects;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 224 KiB

After

Width:  |  Height:  |  Size: 70 KiB

File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More