diff --git a/src/Mod/Part/BasicShapes/ShapeContent.py b/src/Mod/Part/BasicShapes/ShapeContent.py index 0e49c38808..f413808848 100644 --- a/src/Mod/Part/BasicShapes/ShapeContent.py +++ b/src/Mod/Part/BasicShapes/ShapeContent.py @@ -25,7 +25,7 @@ def buildShapeContent(objArg, decimals=2, advancedShapeContent=True): obj = objArg shp = Part.getShape(objArg) typeStr = str(shp.ShapeType) - lbl = "" if obj.Name == obj.Label else "(" + obj.Label + ")" + lbl = "" if obj.Name == obj.Label else " (" + obj.Label + ")" result = linkName + obj.Name + lbl + "\n" result += ( translate("TaskCheckGeometryResults", "Shape type") + ": " + typeStr + "\n" diff --git a/src/Mod/Part/Gui/TaskCheckGeometry.cpp b/src/Mod/Part/Gui/TaskCheckGeometry.cpp index 7197d11fc6..e7e98a73ee 100644 --- a/src/Mod/Part/Gui/TaskCheckGeometry.cpp +++ b/src/Mod/Part/Gui/TaskCheckGeometry.cpp @@ -391,6 +391,10 @@ TaskCheckGeometryResults::~TaskCheckGeometryResults() void TaskCheckGeometryResults::setupInterface() { message = new QLabel(this); + message->setTextFormat(Qt::RichText); + message->setTextInteractionFlags(Qt::TextBrowserInteraction); + message->setOpenExternalLinks(false); + connect(message, &QLabel::linkActivated, this, &TaskCheckGeometryResults::generateReport); message->setText(tr("Check is running...")); model = new ResultModel(this); treeView = new QTreeView(this); @@ -413,6 +417,8 @@ void TaskCheckGeometryResults::goCheck() int selectedCount(0), checkedCount(0), invalidShapes(0); ResultEntry *theRoot = new ResultEntry(); + reportViewStrings.clear(); + reportViewStrings << QLatin1String("\n"); std::string scopeName {tr("Boolean operation check...").toStdString()}; #if OCC_VERSION_HEX < 0x070500 @@ -432,21 +438,44 @@ void TaskCheckGeometryResults::goCheck() for(const auto &sel : selection) { selectedCount++; + int localInvalidShapeCount(0); + QString baseName; + QTextStream baseStream(&baseName); + baseStream << sel.DocName; + baseStream << "." << sel.FeatName; + std::string label = sel.pObject->Label.getValue(); + if (sel.FeatName != label) { + baseStream << " (" << label.c_str() << ")"; + } + TopoDS_Shape shape = Part::Feature::getShape(sel.pObject,sel.SubName,true); if (shape.IsNull()) { + ResultEntry *entry = new ResultEntry(); + entry->parent = theRoot; + entry->name = baseName; + entry->type = tr("Null shape"); + entry->error = tr("Skipped"); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); + theRoot->children.push_back(entry); continue; } if (shape.Infinite()) { + ResultEntry *entry = new ResultEntry(); + entry->parent = theRoot; + entry->name = baseName; + entry->type = tr("Infinite shape"); + entry->error = tr("Skipped"); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); + theRoot->children.push_back(entry); continue; } currentSeparator = Gui::Application::Instance->getViewProvider(sel.pObject)->getRoot(); if (!currentSeparator) { continue; } - QString baseName; - QTextStream baseStream(&baseName); - baseStream << sel.DocName; - baseStream << "." << sel.FeatName; + checkedCount++; checkedMap.Clear(); @@ -456,12 +485,15 @@ void TaskCheckGeometryResults::goCheck() if (!shapeCheck.IsValid()) { invalidShapes++; + localInvalidShapeCount++; ResultEntry *entry = new ResultEntry(); entry->parent = theRoot; entry->shape = shape; entry->name = baseName; entry->type = shapeEnumToString(shape.ShapeType()); entry->error = tr("Invalid"); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); entry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); goSetupResultBoundingBox(entry); @@ -485,29 +517,52 @@ void TaskCheckGeometryResults::goCheck() label += "..."; #if OCC_VERSION_HEX < 0x070500 theProgress->NewScope(label.c_str()); - invalidShapes += goBOPSingleCheck(shape, theRoot, baseName, theProgress); + localInvalidShapeCount += goBOPSingleCheck(shape, theRoot, baseName, theProgress); + invalidShapes += localInvalidShapeCount; theProgress->EndScope(); if (theProgress->UserBreak()) break; #else Message_ProgressScope theInnerScope(theScope.Next(), TCollection_AsciiString(label.c_str()), 1); theInnerScope.Show(); - invalidShapes += goBOPSingleCheck(shape, theRoot, baseName, theInnerScope); + localInvalidShapeCount += goBOPSingleCheck(shape, theRoot, baseName, theInnerScope); + invalidShapes += localInvalidShapeCount; theInnerScope.Close(); if (theScope.UserBreak()) break; #endif } } + // create an entry for shapes without errors + if (localInvalidShapeCount == 0) { + ResultEntry *entry = new ResultEntry(); + entry->parent = theRoot; + entry->name = baseName; + entry->type = shapeEnumToString(shape.ShapeType()); + entry->error = tr("No errors"); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); + entry->viewProviderRoot = currentSeparator; + entry->viewProviderRoot->ref(); + theRoot->children.push_back(entry); + } } model->setResults(theRoot); treeView->expandAll(); treeView->header()->resizeSections(QHeaderView::ResizeToContents); QString aMessage {tr("%1 processed out of %2 selected").arg(checkedCount).arg(selectedCount)}; - aMessage += QLatin1String("\n ") + tr("%n invalid shapes.", "", invalidShapes); + aMessage += QLatin1String("
") + tr("%n invalid shapes.", "", invalidShapes); + aMessage += QLatin1String(" ") + tr("To Report view.") + QLatin1String(""); message->setText(aMessage); } +void TaskCheckGeometryResults::generateReport() +{ + QString reportString = reportViewStrings.join(QLatin1String("\n")); + Base::Console().Message(reportString.toStdString().c_str()); +} + + void TaskCheckGeometryResults::recursiveCheck(const BRepCheck_Analyzer &shapeCheck, const TopoDS_Shape &shape, ResultEntry *parent) { @@ -524,6 +579,8 @@ void TaskCheckGeometryResults::recursiveCheck(const BRepCheck_Analyzer &shapeChe entry->buildEntryName(); entry->type = shapeEnumToString(shape.ShapeType()); entry->error = checkStatusToString(listIt.Value()); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); entry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); dispatchError(entry, listIt.Value()); @@ -572,6 +629,8 @@ void TaskCheckGeometryResults::checkSub(const BRepCheck_Analyzer &shapeCheck, co entry->buildEntryName(); entry->type = shapeEnumToString(sub.ShapeType()); entry->error = checkStatusToString(itl.Value()); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); entry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); dispatchError(entry, itl.Value()); @@ -724,6 +783,8 @@ int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, Resu entry->name = baseName; entry->type = shapeEnumToString(shapeIn.ShapeType()); entry->error = QObject::tr("Invalid"); + reportViewStrings.append(entry->name + QLatin1String(" | ") + + entry->type + QLatin1String(" | ") + entry->error); entry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); goSetupResultBoundingBox(entry); @@ -746,6 +807,8 @@ int TaskCheckGeometryResults::goBOPSingleCheck(const TopoDS_Shape& shapeIn, Resu faultyEntry->buildEntryName(); faultyEntry->type = shapeEnumToString(faultyShape.ShapeType()); faultyEntry->error = getBOPCheckString(current.GetCheckStatus()); + reportViewStrings.append(QLatin1String(" ") + faultyEntry->name + + QLatin1String(" | ") + faultyEntry->error); faultyEntry->viewProviderRoot = currentSeparator; entry->viewProviderRoot->ref(); goSetupResultBoundingBox(faultyEntry); @@ -841,7 +904,10 @@ void TaskCheckGeometryResults::currentRowChanged (const QModelIndex ¤t, co QString doc, object, sub; if (!this->split((*stringIt), doc, object, sub)) continue; - Gui::Selection().addSelection(doc.toLatin1(), object.toLatin1(), sub.toLatin1()); + // object might be "name (label)", so trim if necessary + int idx = object.indexOf(QLatin1String(" (")); + QString trimmed = (idx != -1) ? object.left(idx) : object; + Gui::Selection().addSelection(doc.toLatin1(), trimmed.toLatin1(), sub.toLatin1()); } } } diff --git a/src/Mod/Part/Gui/TaskCheckGeometry.h b/src/Mod/Part/Gui/TaskCheckGeometry.h index 562dfafd5f..1a8343b825 100644 --- a/src/Mod/Part/Gui/TaskCheckGeometry.h +++ b/src/Mod/Part/Gui/TaskCheckGeometry.h @@ -114,6 +114,8 @@ private Q_SLOTS: private: void setupInterface(); + QStringList reportViewStrings; + void generateReport(); void recursiveCheck(const BRepCheck_Analyzer &shapeCheck, const TopoDS_Shape &shape, ResultEntry *parent); void checkSub(const BRepCheck_Analyzer &shapeCheck, const TopoDS_Shape &shape,