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
This commit is contained in:
Benjamin Nauck
2024-12-16 14:30:49 +01:00
committed by Yorik van Havre
parent 844d88fb7a
commit a2c980f7d6
28 changed files with 430 additions and 716 deletions

View File

@@ -450,16 +450,41 @@ void Application::renameDocument(const char *OldName, const char *NewName)
throw Base::RuntimeError("Renaming document internal name is no longer allowed!");
}
Document* Application::newDocument(const char * proposedName, const char * proposedLabel, bool createView, bool tempDoc)
Document* Application::newDocument(const char * Name, const char * UserName, bool createView, bool tempDoc)
{
std::string name;
bool useDefaultName = (!proposedName || proposedName[0] == '\0');
// get a valid name anyway!
if (useDefaultName) {
proposedName = "Unnamed";
}
auto getNameAndLabel = [this](const char * Name, const char * UserName) -> std::tuple<std::string, std::string> {
bool defaultName = (!Name || Name[0] == '\0');
name = getUniqueDocumentName(proposedName, tempDoc);
// get a valid name anyway!
if (defaultName) {
Name = "Unnamed";
}
std::string userName;
if (UserName && UserName[0] != '\0') {
userName = UserName;
}
else {
userName = defaultName ? QObject::tr("Unnamed").toStdString() : Name;
std::vector<std::string> names;
names.reserve(DocMap.size());
for (const auto& pos : DocMap) {
names.emplace_back(pos.second->Label.getValue());
}
if (!names.empty()) {
userName = Base::Tools::getUniqueName(userName, names);
}
}
return std::make_tuple(std::string(Name), userName);
};
auto tuple = getNameAndLabel(Name, UserName);
std::string name = std::get<0>(tuple);
std::string userName = std::get<1>(tuple);
name = getUniqueDocumentName(name.c_str(), tempDoc);
// return the temporary document if it exists
if (tempDoc) {
@@ -468,65 +493,53 @@ Document* Application::newDocument(const char * proposedName, const char * propo
return it->second;
}
// Determine the document's Label
std::string label;
if (proposedLabel && proposedLabel[0] != '\0') {
label = proposedLabel;
}
else {
label = useDefaultName ? QObject::tr("Unnamed").toStdString() : proposedName;
if (!DocMap.empty()) {
// The assumption here is that there are not many documents and
// documents are rarely created so the cost
// of building this manager each time is inconsequential
Base::UniqueNameManager names;
for (const auto& pos : DocMap) {
names.addExactName(pos.second->Label.getValue());
}
label = names.makeUniqueName(label);
}
}
// create the FreeCAD document
Document* doc = new Document(name.c_str());
doc->setStatus(Document::TempDoc, tempDoc);
std::unique_ptr<Document> newDoc(new Document(name.c_str()));
newDoc->setStatus(Document::TempDoc, tempDoc);
auto oldActiveDoc = _pActiveDoc;
auto doc = newDoc.release(); // now owned by the Application
// add the document to the internal list
DocMap[name] = doc;
_pActiveDoc = doc;
//NOLINTBEGIN
// clang-format off
// connect the signals to the application for the new document
doc->signalBeforeChange.connect(std::bind(&App::Application::slotBeforeChangeDocument, this, sp::_1, sp::_2));
doc->signalChanged.connect(std::bind(&App::Application::slotChangedDocument, this, sp::_1, sp::_2));
doc->signalNewObject.connect(std::bind(&App::Application::slotNewObject, this, sp::_1));
doc->signalDeletedObject.connect(std::bind(&App::Application::slotDeletedObject, this, sp::_1));
doc->signalBeforeChangeObject.connect(std::bind(&App::Application::slotBeforeChangeObject, this, sp::_1, sp::_2));
doc->signalChangedObject.connect(std::bind(&App::Application::slotChangedObject, this, sp::_1, sp::_2));
doc->signalRelabelObject.connect(std::bind(&App::Application::slotRelabelObject, this, sp::_1));
doc->signalActivatedObject.connect(std::bind(&App::Application::slotActivatedObject, this, sp::_1));
doc->signalUndo.connect(std::bind(&App::Application::slotUndoDocument, this, sp::_1));
doc->signalRedo.connect(std::bind(&App::Application::slotRedoDocument, this, sp::_1));
doc->signalRecomputedObject.connect(std::bind(&App::Application::slotRecomputedObject, this, sp::_1));
doc->signalRecomputed.connect(std::bind(&App::Application::slotRecomputed, this, sp::_1));
doc->signalBeforeRecompute.connect(std::bind(&App::Application::slotBeforeRecompute, this, sp::_1));
doc->signalOpenTransaction.connect(std::bind(&App::Application::slotOpenTransaction, this, sp::_1, sp::_2));
doc->signalCommitTransaction.connect(std::bind(&App::Application::slotCommitTransaction, this, sp::_1));
doc->signalAbortTransaction.connect(std::bind(&App::Application::slotAbortTransaction, this, sp::_1));
doc->signalStartSave.connect(std::bind(&App::Application::slotStartSaveDocument, this, sp::_1, sp::_2));
doc->signalFinishSave.connect(std::bind(&App::Application::slotFinishSaveDocument, this, sp::_1, sp::_2));
doc->signalChangePropertyEditor.connect(std::bind(&App::Application::slotChangePropertyEditor, this, sp::_1, sp::_2));
_pActiveDoc->signalBeforeChange.connect(std::bind(&App::Application::slotBeforeChangeDocument, this, sp::_1, sp::_2));
_pActiveDoc->signalChanged.connect(std::bind(&App::Application::slotChangedDocument, this, sp::_1, sp::_2));
_pActiveDoc->signalNewObject.connect(std::bind(&App::Application::slotNewObject, this, sp::_1));
_pActiveDoc->signalDeletedObject.connect(std::bind(&App::Application::slotDeletedObject, this, sp::_1));
_pActiveDoc->signalBeforeChangeObject.connect(std::bind(&App::Application::slotBeforeChangeObject, this, sp::_1, sp::_2));
_pActiveDoc->signalChangedObject.connect(std::bind(&App::Application::slotChangedObject, this, sp::_1, sp::_2));
_pActiveDoc->signalRelabelObject.connect(std::bind(&App::Application::slotRelabelObject, this, sp::_1));
_pActiveDoc->signalActivatedObject.connect(std::bind(&App::Application::slotActivatedObject, this, sp::_1));
_pActiveDoc->signalUndo.connect(std::bind(&App::Application::slotUndoDocument, this, sp::_1));
_pActiveDoc->signalRedo.connect(std::bind(&App::Application::slotRedoDocument, this, sp::_1));
_pActiveDoc->signalRecomputedObject.connect(std::bind(&App::Application::slotRecomputedObject, this, sp::_1));
_pActiveDoc->signalRecomputed.connect(std::bind(&App::Application::slotRecomputed, this, sp::_1));
_pActiveDoc->signalBeforeRecompute.connect(std::bind(&App::Application::slotBeforeRecompute, this, sp::_1));
_pActiveDoc->signalOpenTransaction.connect(std::bind(&App::Application::slotOpenTransaction, this, sp::_1, sp::_2));
_pActiveDoc->signalCommitTransaction.connect(std::bind(&App::Application::slotCommitTransaction, this, sp::_1));
_pActiveDoc->signalAbortTransaction.connect(std::bind(&App::Application::slotAbortTransaction, this, sp::_1));
_pActiveDoc->signalStartSave.connect(std::bind(&App::Application::slotStartSaveDocument, this, sp::_1, sp::_2));
_pActiveDoc->signalFinishSave.connect(std::bind(&App::Application::slotFinishSaveDocument, this, sp::_1, sp::_2));
_pActiveDoc->signalChangePropertyEditor.connect(std::bind(&App::Application::slotChangePropertyEditor, this, sp::_1, sp::_2));
// clang-format on
//NOLINTEND
// (temporarily) make this the active document for the upcoming notifications.
// Signal NewDocument rather than ActiveDocument
auto oldActiveDoc = _pActiveDoc;
setActiveDocumentNoSignal(doc);
signalNewDocument(*doc, createView);
// make sure that the active document is set in case no GUI is up
{
Base::PyGILStateLocker lock;
Py::Object active(_pActiveDoc->getPyObject(), true);
Py::Module("FreeCAD").setAttr(std::string("ActiveDocument"), active);
}
doc->Label.setValue(label);
signalNewDocument(*_pActiveDoc, createView);
// set the UserName after notifying all observers
_pActiveDoc->Label.setValue(userName);
// set the old document active again if the new is temporary
if (tempDoc && oldActiveDoc)
@@ -616,17 +629,13 @@ std::string Application::getUniqueDocumentName(const char *Name, bool tempDoc) c
return CleanName;
}
else {
// The assumption here is that there are not many documents and
// documents are rarely created so the cost
// of building this manager each time is inconsequential
Base::UniqueNameManager names;
for (const auto& pos : DocMap) {
if (!tempDoc || !pos.second->testStatus(Document::TempDoc)) {
names.addExactName(pos.first);
}
std::vector<std::string> names;
names.reserve(DocMap.size());
for (pos = DocMap.begin(); pos != DocMap.end(); ++pos) {
if (!tempDoc || !pos->second->testStatus(Document::TempDoc))
names.push_back(pos->first);
}
return names.makeUniqueName(CleanName);
return Base::Tools::getUniqueName(CleanName, names);
}
}
@@ -1044,14 +1053,6 @@ Document* Application::getActiveDocument() const
}
void Application::setActiveDocument(Document* pDoc)
{
setActiveDocumentNoSignal(pDoc);
if (pDoc)
signalActiveDocument(*pDoc);
}
void Application::setActiveDocumentNoSignal(Document* pDoc)
{
_pActiveDoc = pDoc;
@@ -1059,15 +1060,18 @@ void Application::setActiveDocumentNoSignal(Document* pDoc)
if (pDoc) {
Base::PyGILStateLocker lock;
Py::Object active(pDoc->getPyObject(), true);
Py::Module("FreeCAD").setAttr(std::string("ActiveDocument"), active);
Py::Module("FreeCAD").setAttr(std::string("ActiveDocument"),active);
}
else {
Base::PyGILStateLocker lock;
Py::Module("FreeCAD").setAttr(std::string("ActiveDocument"), Py::None());
Py::Module("FreeCAD").setAttr(std::string("ActiveDocument"),Py::None());
}
if (pDoc)
signalActiveDocument(*pDoc);
}
void Application::setActiveDocument(const char* Name)
void Application::setActiveDocument(const char *Name)
{
// If no active document is set, resort to a default.
if (*Name == '\0') {