【全网最完整】Open CASCADE Technology (OCCT) 构建项目,QT可视化操作,添加自定义测试内容
前言
1、项目所需工具下载
2、使用CMake编译源码
3、配置项目运行环境
4、如何自定义测试项目
5、总结
前言
本文为了记录自己在实习的过程中,学习到的有关OCCT开源项目的搭建工作,旨在教会小白从0开始下载开源项目及环境搭配,以及如何添加自定义测试内容,最终结果展示如下:
1、项目所需工具下载
本项目共需要使用四个工具,分别是OCCT开源代码,QT环境,CMake构建工具,VS2019,版本也会介绍。我会把CMake、VS2019、第三方库放到Github链接里https://github.com/shadow0fiend/OCCT-Project,OCCT源码以及QT环境需要自己下载
其中下载链接如下:
OCCT(7.8或7.6或7.5皆可):Download - Open CASCADE Technology
第三方库及VS2019:GitHub - shadow0fiend/OCCT-Project: 构建OCCT项目
QT工具(5.14.2):Index of /archive/qt
CMake(3.29.3):Download CMake
其中安装过程如下:
OCCT:下载64位的压缩包,解压到本地即可。
QT:对于新手,建议在勾选下载内容的时候全部选上(简单粗暴,不会缺少东西)
详情下载过程请参考链接:Qt5.14.2安装、配置及测试(Win10)-CSDN博客
CMake:无脑下一步即可
详情下载过程请参考链接:Windows下Cmake安装步骤详解(图文)_windows终端安装cmake-CSDN博客
安装完以后,本地应该有以下几个内容,注意检查cmake-gui、OCCT源码、编译用的三方库(下图product)、QT环境、VS2019
2、使用CMake编译源码
步骤1:在OCCT源码中建立一个build文件夹,用于存放编译后的文件
步骤2:打开CMake-gui,第一个位置填入OCCT源码文件夹的路径,第二个位置填入刚才创建好的build文件夹的路径
步骤3:点击configure,选择配置vs2019,x64,点击finish
步骤4:
第一步,在3RDPARTY_DIR这一行,填入第三方库文件的路径,也就是product的路径。
第二步,然后勾选上BUILD_SAMPLES_QT这一行。
第三步点击config。
步骤5:
第一步,修改QT路径,这个Qt5.14.2是安装完QT以后的文件夹,自行在里面找对应的文件(如果没有找到,应该是QT安装下载的时候,有的选项没有勾上)
第二步,改完以后点击config,点击generate,点击open project
步骤7:cmake配置完毕,最终配置结果如下所示
3、配置项目运行环境
生成的项目如下所示(如果没有勾选QT,那么编译完成以后的项目是不包含Samples文件的,只有非常简陋的可视化界面):
步骤1:鼠标右击OCCTOverview,设置OCCTOverview为启动项。
步骤2:鼠标右击OCCTOverview,依次找到属性、Debugging、environment,将以下内容粘贴进去,这是配置项目环境变量的。注意:需要将路径修改为自己电脑的路径。
配置解释:
CASROOT需要配置OCCT源码文件夹
CSF_OCCT都是OCCT源码文件夹里面的文件
最后一行是配置QT的bin,QT的platforms,第三方库文件freetype,freeimage
CASROOT=E:\cpp\code\OCCT\OCCT-7_8_0 CSF_FPE=0 CSF_OCCTResourcePath=E:\cpp\code\OCCT\OCCT-7_8_0/src CSF_OCCTDataPath=E:\cpp\code\OCCT\OCCT-7_8_0/data CSF_OCCTSamplesPath=E:\cpp\code\OCCT\OCCT-7_8_0/samples CSF_OCCTTestsPath=E:\cpp\code\OCCT\OCCT-7_8_0/tests CSF_OCCTDocPath=E:\cpp\code\OCCT\OCCT-7_8_0/doc QT_DEBUG_PLUGINS=1 PATH=%PATH%;D:\Qt\Qt5.14.2\5.14.2\msvc2015_64\bin;D:\Qt\Qt5.14.2\5.14.2\msvc2015_64\plugins\platforms;E:\cpp\code\OCCT\products\freetype-2.5.5-vc14-64\bin;E:\cpp\code\OCCT\products\freeimage-3.17.0-vc14-64\bin;
步骤3:复制 D:\Qt\Qt5.14.2\5.14.2\msvc2015_64\plugins 路径下的platforms文件,粘贴到 E:\cpp\code\OCCT\OCCT-7_8_0\build\win64\vc14\bind (生成的build文件里)路径下,如果要在release下运行,则将其粘贴到 E:\cpp\code\OCCT\OCCT-7_8_0\build\win64\vc14\bin路径下。
步骤4:编译运行即可完成。
4、如何自定义测试项目
先看自己修改的结果,在QT窗口自己添加按钮,用于触发函数,然后再在被触发的函数里编写自己的测试代码,就可以完成自定义测试了。
具体来说,需要修改5个地方:
找到OCCT源码里的samples文件(注意,不是build里的samples),进去以后找到OCCTOverview,再找到Code文件夹。我的路径是:E:\cpp\code\OCCT\OCCT-7_8_0\samples\OCCTOverview\code
第一处修改:把自己写的cxx文件和.h文件放在这里(注意:直接在build里右键添加cxx文件是添加不到这里来的,因为那只是在build文件里添加了,而这是OCCT的源码文件,只能在这里添加以后,通过cmake编译进build才行)
具体的cxx和.h文件的写法参考如下,可以仿照源码的 TopologySamples.cxx文件的写法,看我的cxx和TopologySamples.cxx不同的地方即可,按照对应位置改就行。这里我附上我的源码。
#include "PengKaiSamples.h" void PengKaiSamples::ExecuteSample(const TCollection_AsciiString& theSampleName) { Standard_Boolean anIsSamplePresent = Standard_True; FindSourceCode(theSampleName); if (theSampleName == "FirstTest") FirstTest(); else { myResult addWidget(myCodeView); myCodeView->setDocumentTitle("Code"); myCodeView->setLineWrapMode(QTextEdit::NoWrap); myCodeView->setReadOnly(true); myCodeView->setFont(aCodeViewFont); myCodeViewHighlighter = new OcctHighlighter(myCodeView->document()); QGroupBox* aResultFrame = new QGroupBox(tr("Output")); QVBoxLayout* aResultLayout = new QVBoxLayout(aResultFrame); aResultLayout->setContentsMargins(3, 3, 3, 3); myResultView = new QTextEdit(aResultFrame); aResultLayout->addWidget(myResultView); myResultView->setDocumentTitle("Output"); myResultView->setReadOnly(true); myResultView->setFont(aCodeViewFont); QSplitter* aCodeResultSplitter = new QSplitter(Qt::Vertical); aCodeResultSplitter->addWidget(aCodeFrame); aCodeResultSplitter->addWidget(aResultFrame); myDocument3d = createNewDocument(); myDocument2d = createNewDocument(); QFrame* aViewFrame = new QFrame; aViewFrame->setFrameStyle(QFrame::Panel | QFrame::Sunken); aViewFrame->setLineWidth(3); QVBoxLayout* aViewLayout = new QVBoxLayout(aViewFrame); aViewLayout->setContentsMargins(0, 0, 0, 0); myGeomWidget = new GeomWidget(myDocument3d, myDocument2d, aViewFrame); aViewLayout->addWidget(myGeomWidget); myGeomWidget->setContentsMargins(0, 0, 0, 0); QSplitter* aGeomTextSplitter = new QSplitter(Qt::Horizontal); aGeomTextSplitter->addWidget(aViewFrame); aGeomTextSplitter->addWidget(aCodeResultSplitter); aGeomTextSplitter->setStretchFactor(0, 1); aGeomTextSplitter->setStretchFactor(1, 1); QList aSizeList; aSizeList.append(640); aSizeList.append(640); aGeomTextSplitter->setSizes(aSizeList); setCentralWidget(aGeomTextSplitter); #include Q_INIT_RESOURCE(Samples); #include TCollection_AsciiString aSampleSourcePach = getSampleSourceDir(); myGeometrySamples = new GeometrySamples(aSampleSourcePach, myDocument3d->getContext()); myTopologySamples = new TopologySamples(aSampleSourcePach, myDocument3d->getContext()); myTriangulationSamples = new TriangulationSamples(aSampleSourcePach, myDocument3d->getContext()); myDataExchangeSamples = new DataExchangeSamples(aSampleSourcePach, myGeomWidget->Get3dView(), myDocument3d->getContext()); myOcafSamples = new OcafSamples(aSampleSourcePach, myDocument3d->getViewer(), myDocument3d->getContext()); myViewer3dSamples = new Viewer3dSamples(aSampleSourcePach, myGeomWidget->Get3dView(), myDocument3d->getContext()); myViewer2dSamples = new Viewer2dSamples(aSampleSourcePach, myGeomWidget->Get2dView(), myDocument2d->getViewer(), myDocument2d->getContext()); myPengKaiSamples = new PengKaiSamples(aSampleSourcePach, myDocument3d->getContext()); MenuFormXml(":/menus/Geometry.xml", mySampleMapper, myGeometryMenus); MenuFormXml(":/menus/Topology.xml", mySampleMapper, myTopologyMenus); MenuFormXml(":/menus/Triangulation.xml", mySampleMapper, myTriangulationMenus); MenuFormXml(":/menus/DataExchange.xml", myExchangeMapper, myDataExchangeMenus); MenuFormXml(":/menus/Ocaf.xml", myOcafMapper, myOcafMenus); MenuFormXml(":/menus/Viewer3d.xml", myViewer3dMapper, myViewer3dMenus); MenuFormXml(":/menus/Viewer2d.xml", myViewer2dMapper, myViewer2dMenus); MenuFormXml(":/menus/PengKai.xml", mySampleMapper, myPengKaiMenus); onChangeCategory(ALL_CATEGORIES[myAppType]); resize(1280, 560); } void ApplicationCommonWindow::RebuildMenu() { menuBar()->clear(); myStdActions[StdActions_FileQuit] = CreateAction("Quit", "CTRL+Q"); connect(myStdActions[StdActions_FileQuit], SIGNAL(triggered()), this, SLOT(onCloseAllWindows())); myStdActions[StdActions_HelpAbout] = CreateAction("About", "F1", ":/icons/help.png"); connect(myStdActions[StdActions_HelpAbout], SIGNAL(triggered()), this, SLOT(onAbout())); // populate a menu with all actions myFilePopup = new QMenu(this); myFilePopup = menuBar()->addMenu(tr("&File")); myFilePopup->addAction(myStdActions[StdActions_FileQuit]); myCategoryPopup = new QMenu(this); myCategoryPopup = menuBar()->addMenu(tr("&Category")); foreach (ApplicationType aCategory, ALL_CATEGORIES.keys()) { QString aCategoryName = ALL_CATEGORIES.value(aCategory); QAction* anAction = myCategoryPopup->addAction(aCategoryName); anAction->setText(aCategoryName); myCategoryMapper->setMapping(anAction, aCategoryName); connect(anAction, SIGNAL(triggered()), myCategoryMapper, SLOT(map())); myCategoryPopup->addAction(anAction); myCategoryActions.insert(aCategory, anAction); } foreach (QMenu* aSampleMenu, GetCurrentMenus()) { menuBar()->addMenu(aSampleMenu); } // add a help menu QMenu* aHelp = new QMenu(this); menuBar()->addSeparator(); aHelp = menuBar()->addMenu(tr("&Help")); aHelp->addAction(myStdActions[StdActions_HelpAbout]); } Handle(BaseSample) ApplicationCommonWindow::GetCurrentSamples() { switch (myAppType) { case AppType_Geometry: return myGeometrySamples; case AppType_Topology: return myTopologySamples; case AppType_Triangulation: return myTriangulationSamples; case AppType_DataExchange: return myDataExchangeSamples; case AppType_Ocaf: return myOcafSamples; case AppType_Viewer2d: return myViewer2dSamples; case AppType_Viewer3d: return myViewer3dSamples; case AppType_PengKai: return myPengKaiSamples; case AppType_Unknown: break; } throw QString("Unknown Application type"); } const QList& ApplicationCommonWindow::GetCurrentMenus() { switch (myAppType) { case AppType_Geometry: return myGeometryMenus; case AppType_Topology: return myTopologyMenus; case AppType_Triangulation: return myTriangulationMenus; case AppType_DataExchange: return myDataExchangeMenus; case AppType_Ocaf: return myOcafMenus; case AppType_Viewer2d: return myViewer2dMenus; case AppType_Viewer3d: return myViewer3dMenus; case AppType_PengKai: return myPengKaiMenus; case AppType_Unknown: break; } throw QString("Unknown Application type"); } DocumentCommon* ApplicationCommonWindow::createNewDocument() { return new DocumentCommon(this); } void ApplicationCommonWindow::onChangeCategory(const QString& theCategory) { myAppType = ALL_CATEGORIES.key(theCategory); setWindowTitle(ALL_CATEGORIES[myAppType]); myOcafSamples->ClearExtra(); myViewer3dSamples->ClearExtra(); myViewer2dSamples->ClearExtra(); GetCurrentSamples()->Clear(); myDocument3d->Clear(); myDocument2d->Clear(); myCodeView->setPlainText(""); myResultView->setPlainText(""); GetCurrentSamples()->AppendCube(); myDocument3d->SetObjects(GetCurrentSamples()->Get3dObjects()); myGeomWidget->FitAll(); RebuildMenu(); switch (myAppType) { case AppType_DataExchange: { myDataExchangeSamples->AppendBottle(); myDocument3d->SetObjects(GetCurrentSamples()->Get3dObjects()); myGeomWidget->Show3d(); break; } case AppType_Ocaf: { onProcessOcaf("CreateOcafDocument"); myGeomWidget->Show3d(); break; } case AppType_Viewer2d: { myGeomWidget->Show2d(); break; } case AppType_Viewer3d: { myViewer3dSamples->AppendBottle(); myDocument3d->SetObjects(GetCurrentSamples()->Get3dObjects()); myGeomWidget->Show3d(); break; } case AppType_Geometry: case AppType_Topology: case AppType_PengKai: case AppType_Triangulation: case AppType_Unknown: { break; } } } void ApplicationCommonWindow::onAbout() { QMessageBox::information(this, tr("OCCT Overview"), tr("Qt based application to study OpenCASCADE Technology"), tr("Ok"), QString::null, QString::null, 0, 0); } TCollection_AsciiString ApplicationCommonWindow::getSampleSourceDir() { TCollection_AsciiString aSampleSourceDir = OSD_Environment("CSF_OCCTOverviewSampleCodePath").Value(); if (aSampleSourceDir.IsEmpty()) { TCollection_AsciiString aCasRoot = OSD_Environment("CASROOT").Value(); if (!aCasRoot.IsEmpty()) { aSampleSourceDir = aCasRoot + "/samples/OCCTOverview/code"; } } return aSampleSourceDir; } QAction* ApplicationCommonWindow::CreateAction (const QString& theActionName, const QString& theShortcut, const QString& theIconName) { QAction* aAction(NULL); if (theIconName.isEmpty()) { aAction = new QAction(theActionName, this); } else { QPixmap aIcon = QPixmap(theIconName); aAction = new QAction(aIcon, theActionName, this); } aAction->setToolTip(theActionName); aAction->setStatusTip(theActionName); aAction->setShortcut(theShortcut); return aAction; } template QAction* ApplicationCommonWindow::CreateSample (PointerToMemberFunction theHandlerMethod, const char* theActionName) { QAction* anAction = new QAction(QObject::tr(theActionName), this); connect(anAction, SIGNAL(triggered()), this, SLOT(theHandlerMethod())); return anAction; } void ApplicationCommonWindow::resizeEvent(QResizeEvent* e) { QMainWindow::resizeEvent(e); statusBar()->setSizeGripEnabled(!isMaximized()); } void ApplicationCommonWindow::onProcessSample(const QString& theSampleName) { QApplication::setOverrideCursor(Qt::WaitCursor); setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); GetCurrentSamples()->Process(theSampleName.toUtf8().data()); myDocument3d->SetObjects(GetCurrentSamples()->Get3dObjects()); myDocument2d->SetObjects(GetCurrentSamples()->Get2dObjects()); myCodeView->setPlainText(GetCurrentSamples()->GetCode().ToCString()); myResultView->setPlainText(GetCurrentSamples()->GetResult().ToCString()); myGeomWidget->FitAll(); QApplication::restoreOverrideCursor(); } void ApplicationCommonWindow::onProcessExchange(const QString& theSampleName) { setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); int aMode = 0; QString aFileName = selectFileName(theSampleName, getDataExchangeDialog(theSampleName), aMode); if (aFileName.isEmpty()) { return; } QApplication::setOverrideCursor(Qt::WaitCursor); myDataExchangeSamples->SetFileName(aFileName.toUtf8().data()); myDataExchangeSamples->SetStepType(static_cast(aMode)); myDataExchangeSamples->Process(theSampleName.toUtf8().data()); myDocument3d->SetObjects(myDataExchangeSamples->Get3dObjects()); myDocument2d->SetObjects(myDataExchangeSamples->Get2dObjects()); myCodeView->setPlainText(myDataExchangeSamples->GetCode().ToCString()); myResultView->setPlainText(myDataExchangeSamples->GetResult().ToCString()); myGeomWidget->FitAll(); QApplication::restoreOverrideCursor(); } void ApplicationCommonWindow::onProcessOcaf(const QString& theSampleName) { setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); if (theSampleName.indexOf("Dialog") == 0) { int aMode = 0; // not used QString aFileName = selectFileName(theSampleName, getOcafDialog(theSampleName), aMode); if (aFileName.isEmpty()) { return; } myOcafSamples->SetFileName(aFileName.toUtf8().data()); } QApplication::setOverrideCursor(Qt::WaitCursor); myOcafSamples->Process(theSampleName.toUtf8().data()); myDocument2d->SetObjects(myOcafSamples->Get2dObjects()); myCodeView->setPlainText(myOcafSamples->GetCode().ToCString()); myResultView->setPlainText(myOcafSamples->GetResult().ToCString()); QApplication::restoreOverrideCursor(); } void ApplicationCommonWindow::onProcessViewer3d(const QString& theSampleName) { setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); QApplication::setOverrideCursor(Qt::WaitCursor); myViewer3dSamples->Process(theSampleName.toUtf8().data()); myCodeView->setPlainText(myViewer3dSamples->GetCode().ToCString()); myResultView->setPlainText(myViewer3dSamples->GetResult().ToCString()); myGeomWidget->FitAll(); QApplication::restoreOverrideCursor(); } void ApplicationCommonWindow::onProcessViewer2d(const QString& theSampleName) { setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); Standard_Boolean anIsFileSample = Viewer2dSamples::IsFileSample(theSampleName.toUtf8().data()); QString aFileName; if (anIsFileSample) { int aMode = 0; // not used aFileName = selectFileName(theSampleName, getOcafDialog(theSampleName), aMode); if (aFileName.isEmpty()) { return; } myViewer2dSamples->SetFileName(aFileName.toUtf8().data()); } if (!anIsFileSample || (anIsFileSample && !aFileName.isEmpty())) { QApplication::setOverrideCursor(Qt::WaitCursor); myViewer2dSamples->Process(theSampleName.toUtf8().data()); if (!Viewer2dSamples::IsShadedSample(theSampleName.toUtf8().data())) { myDocument2d->SetObjects(myViewer2dSamples->Get2dObjects(), Standard_False); } else { myDocument2d->SetObjects(myViewer2dSamples->Get2dObjects(), Standard_True); } myCodeView->setPlainText(myViewer2dSamples->GetCode().ToCString()); myResultView->setPlainText(myViewer2dSamples->GetResult().ToCString()); myGeomWidget->Show2d(); QApplication::restoreOverrideCursor(); } else { myResultView->setPlainText("No file selected!"); } } QString ApplicationCommonWindow::selectFileName(const QString& theSampleName, TranslateDialog* theDialog, int& theMode) { Q_UNUSED(theSampleName) std::shared_ptr aDialog(theDialog); int ret = aDialog->exec(); theMode = aDialog->getMode(); qApp->processEvents(); QString aFilename; QStringList aFileNameList; if (ret != QDialog::Accepted) { return aFilename; } aFileNameList = aDialog->selectedFiles(); if (!aFileNameList.isEmpty()) { aFilename = aFileNameList[0]; } if (!QFileInfo(aFilename).completeSuffix().length()) { QString selFilter = aDialog->selectedNameFilter(); int idx = selFilter.indexOf("(*."); if (idx != -1) { QString tail = selFilter.mid(idx + 3); idx = tail.indexOf(" "); if (idx == -1) { idx = tail.indexOf(")"); } QString ext = tail.left(idx); if (ext.length()) { aFilename += QString(".") + ext; } } } return aFilename; } TranslateDialog* ApplicationCommonWindow::getDataExchangeDialog(const QString& theSampleName) { TranslateDialog* aTranslateDialog = new TranslateDialog(this, 0, true); TCollection_AsciiString aSampleName(theSampleName.toUtf8().data()); if (DataExchangeSamples::IsExportSample(aSampleName)) { aTranslateDialog->setWindowTitle("Export file"); aTranslateDialog->setFileMode(QFileDialog::AnyFile); aTranslateDialog->setAcceptMode(QFileDialog::AcceptSave); } else if (DataExchangeSamples::IsImportSample(aSampleName)) { aTranslateDialog->setWindowTitle("Import file"); aTranslateDialog->setFileMode(QFileDialog::ExistingFile); aTranslateDialog->setAcceptMode(QFileDialog::AcceptOpen); } QString aFormatFilter; if (DataExchangeSamples::IsBrepSample(aSampleName)) { aFormatFilter = "BREP Files(*.brep *.rle)"; } else if (DataExchangeSamples::IsStepSample(aSampleName)) { aFormatFilter = "STEP Files (*.stp *.step)"; aTranslateDialog->addMode(STEPControl_ManifoldSolidBrep, "Manifold Solid Brep"); aTranslateDialog->addMode(STEPControl_FacetedBrep, "Faceted Brep"); aTranslateDialog->addMode(STEPControl_ShellBasedSurfaceModel, "Shell Based Surface Model"); aTranslateDialog->addMode(STEPControl_GeometricCurveSet, "Geometric Curve Set"); } else if (DataExchangeSamples::IsIgesSample(aSampleName)) { aFormatFilter = "IGES Files (*.igs *.iges)"; } else if (DataExchangeSamples::IsStlSample(aSampleName)) { aFormatFilter = "STL Files (*.stl)"; } else if (DataExchangeSamples::IsVrmlSample(aSampleName)) { aFormatFilter = "VRML Files (*.vrml)"; } else if (DataExchangeSamples::IsImageSample(aSampleName)) { aFormatFilter = "All Image Files (*.bmp *.gif *.jpg *.jpeg *.png *.tga)"; } QStringList aFilters; aFilters.append(aFormatFilter); aFilters.append("All Files(*.*)"); aTranslateDialog->setNameFilters(aFilters); aTranslateDialog->clear(); return aTranslateDialog; } TranslateDialog* ApplicationCommonWindow::getOcafDialog(const QString& theSampleName) { TranslateDialog* aTranslateDialog = new TranslateDialog(this, 0, true); TCollection_AsciiString aSampleName(theSampleName.toUtf8().data()); if (OcafSamples::IsExportSample(aSampleName)) { aTranslateDialog->setWindowTitle("Export file"); aTranslateDialog->setFileMode(QFileDialog::AnyFile); aTranslateDialog->setAcceptMode(QFileDialog::AcceptSave); } else if (OcafSamples::IsImportSample(aSampleName)) { aTranslateDialog->setWindowTitle("Import file"); aTranslateDialog->setFileMode(QFileDialog::ExistingFile); aTranslateDialog->setAcceptMode(QFileDialog::AcceptOpen); } QStringList aFilters; if (OcafSamples::IsBinarySample(aSampleName)) { aFilters.append("Binary OCAF Sample (*.cbf)"); } if (OcafSamples::IsXmlSample(aSampleName)) { aFilters.append("XML OCAF Sample (*.xml)"); } aFilters.append("All Files(*.*)"); aTranslateDialog->setNameFilters(aFilters); aTranslateDialog->clear(); return aTranslateDialog; } QMenu* ApplicationCommonWindow::MenuFromDomNode(QDomElement& theItemElement, QWidget* theParent, QSignalMapper* theMapper) { QString anItemName = theItemElement.attribute("name"); QMenu* aMenu = new QMenu(anItemName, theParent); QDomElement anChildItemElement = theItemElement.firstChildElement("MenuItem"); QDomElement anSampleElement = theItemElement.firstChildElement("Sample"); while(anChildItemElement.isElement()) { aMenu->addMenu(MenuFromDomNode(anChildItemElement, aMenu, theMapper)); anChildItemElement = anChildItemElement.nextSibling().toElement(); } while(anSampleElement.isElement()) { QString aSampleName = anSampleElement.attribute("name"); QString aSampleFunction = anSampleElement.attribute("function"); QAction* anAction = aMenu->addAction(aSampleFunction); anAction->setText(aSampleName); theMapper->setMapping(anAction, aSampleFunction); connect(anAction, SIGNAL(triggered()), theMapper, SLOT(map())); anSampleElement = anSampleElement.nextSibling().toElement(); } return aMenu; } void ApplicationCommonWindow::MenuFormXml(const QString& thePath, QSignalMapper* theMapper, QList& theMunusList) { QDomDocument aDomDocument; theMunusList.clear(); QFile aXmlFile(thePath); QString anErrorMessage; if (aXmlFile.error() != QFile::NoError) { anErrorMessage = aXmlFile.errorString(); Message::SendFail() addWidget(aCodeFrame); aCodeResultSplitter->addWidget(aResultFrame); myDocument3d = createNewDocument(); myDocument2d = createNewDocument(); QFrame* aViewFrame = new QFrame; aViewFrame->setFrameStyle(QFrame::Panel | QFrame::Sunken); aViewFrame->setLineWidth(3); QVBoxLayout* aViewLayout = new QVBoxLayout(aViewFrame); aViewLayout->setContentsMargins(0, 0, 0, 0); myGeomWidget = new GeomWidget(myDocument3d, myDocument2d, aViewFrame); aViewLayout->addWidget(myGeomWidget); myGeomWidget->setContentsMargins(0, 0, 0, 0); QSplitter* aGeomTextSplitter = new QSplitter(Qt::Horizontal); aGeomTextSplitter->addWidget(aViewFrame); aGeomTextSplitter->addWidget(aCodeResultSplitter); aGeomTextSplitter->setStretchFactor(0, 1); aGeomTextSplitter->setStretchFactor(1, 1); QList aSizeList; aSizeList.append(640); aSizeList.append(640); aGeomTextSplitter->setSizes(aSizeList); setCentralWidget(aGeomTextSplitter); #include Q_INIT_RESOURCE(Samples); #include TCollection_AsciiString aSampleSourcePach = getSampleSourceDir(); myGeometrySamples = new GeometrySamples(aSampleSourcePach, myDocument3d->getContext()); myTopologySamples = new TopologySamples(aSampleSourcePach, myDocument3d->getContext()); myTriangulationSamples = new TriangulationSamples(aSampleSourcePach, myDocument3d->getContext()); myDataExchangeSamples = new DataExchangeSamples(aSampleSourcePach, myGeomWidget->Get3dView(), myDocument3d->getContext()); myOcafSamples = new OcafSamples(aSampleSourcePach, myDocument3d->getViewer(), myDocument3d->getContext()); myViewer3dSamples = new Viewer3dSamples(aSampleSourcePach, myGeomWidget->Get3dView(), myDocument3d->getContext()); myViewer2dSamples = new Viewer2dSamples(aSampleSourcePach, myGeomWidget->Get2dView(), myDocument2d->getViewer(), myDocument2d->getContext()); myPengKaiSamples = new PengKaiSamples(aSampleSourcePach, myDocument3d->getContext()); MenuFormXml(":/menus/Geometry.xml", mySampleMapper, myGeometryMenus); MenuFormXml(":/menus/Topology.xml", mySampleMapper, myTopologyMenus); MenuFormXml(":/menus/Triangulation.xml", mySampleMapper, myTriangulationMenus); MenuFormXml(":/menus/DataExchange.xml", myExchangeMapper, myDataExchangeMenus); MenuFormXml(":/menus/Ocaf.xml", myOcafMapper, myOcafMenus); MenuFormXml(":/menus/Viewer3d.xml", myViewer3dMapper, myViewer3dMenus); MenuFormXml(":/menus/Viewer2d.xml", myViewer2dMapper, myViewer2dMenus); MenuFormXml(":/menus/PengKai.xml", mySampleMapper, myPengKaiMenus); onChangeCategory(ALL_CATEGORIES[myAppType]); resize(1280, 560); } void ApplicationCommonWindow::RebuildMenu() { menuBar()->clear(); myStdActions[StdActions_FileQuit] = CreateAction("Quit", "CTRL+Q"); connect(myStdActions[StdActions_FileQuit], SIGNAL(triggered()), this, SLOT(onCloseAllWindows())); myStdActions[StdActions_HelpAbout] = CreateAction("About", "F1", ":/icons/help.png"); connect(myStdActions[StdActions_HelpAbout], SIGNAL(triggered()), this, SLOT(onAbout())); // populate a menu with all actions myFilePopup = new QMenu(this); myFilePopup = menuBar()->addMenu(tr("&File")); myFilePopup->addAction(myStdActions[StdActions_FileQuit]); myCategoryPopup = new QMenu(this); myCategoryPopup = menuBar()->addMenu(tr("&Category")); foreach (ApplicationType aCategory, ALL_CATEGORIES.keys()) { QString aCategoryName = ALL_CATEGORIES.value(aCategory); QAction* anAction = myCategoryPopup->addAction(aCategoryName); anAction->setText(aCategoryName); myCategoryMapper->setMapping(anAction, aCategoryName); connect(anAction, SIGNAL(triggered()), myCategoryMapper, SLOT(map())); myCategoryPopup->addAction(anAction); myCategoryActions.insert(aCategory, anAction); } foreach (QMenu* aSampleMenu, GetCurrentMenus()) { menuBar()->addMenu(aSampleMenu); } // add a help menu QMenu* aHelp = new QMenu(this); menuBar()->addSeparator(); aHelp = menuBar()->addMenu(tr("&Help")); aHelp->addAction(myStdActions[StdActions_HelpAbout]); } Handle(BaseSample) ApplicationCommonWindow::GetCurrentSamples() { switch (myAppType) { case AppType_Geometry: return myGeometrySamples; case AppType_Topology: return myTopologySamples; case AppType_Triangulation: return myTriangulationSamples; case AppType_DataExchange: return myDataExchangeSamples; case AppType_Ocaf: return myOcafSamples; case AppType_Viewer2d: return myViewer2dSamples; case AppType_Viewer3d: return myViewer3dSamples; case AppType_PengKai: return myPengKaiSamples; case AppType_Unknown: break; } throw QString("Unknown Application type"); } const QList& ApplicationCommonWindow::GetCurrentMenus() { switch (myAppType) { case AppType_Geometry: return myGeometryMenus; case AppType_Topology: return myTopologyMenus; case AppType_Triangulation: return myTriangulationMenus; case AppType_DataExchange: return myDataExchangeMenus; case AppType_Ocaf: return myOcafMenus; case AppType_Viewer2d: return myViewer2dMenus; case AppType_Viewer3d: return myViewer3dMenus; case AppType_PengKai: return myPengKaiMenus; case AppType_Unknown: break; } throw QString("Unknown Application type"); } DocumentCommon* ApplicationCommonWindow::createNewDocument() { return new DocumentCommon(this); } void ApplicationCommonWindow::onChangeCategory(const QString& theCategory) { myAppType = ALL_CATEGORIES.key(theCategory); setWindowTitle(ALL_CATEGORIES[myAppType]); myOcafSamples->ClearExtra(); myViewer3dSamples->ClearExtra(); myViewer2dSamples->ClearExtra(); GetCurrentSamples()->Clear(); myDocument3d->Clear(); myDocument2d->Clear(); myCodeView->setPlainText(""); myResultView->setPlainText(""); GetCurrentSamples()->AppendCube(); myDocument3d->SetObjects(GetCurrentSamples()->Get3dObjects()); myGeomWidget->FitAll(); RebuildMenu(); switch (myAppType) { case AppType_DataExchange: { myDataExchangeSamples->AppendBottle(); myDocument3d->SetObjects(GetCurrentSamples()->Get3dObjects()); myGeomWidget->Show3d(); break; } case AppType_Ocaf: { onProcessOcaf("CreateOcafDocument"); myGeomWidget->Show3d(); break; } case AppType_Viewer2d: { myGeomWidget->Show2d(); break; } case AppType_Viewer3d: { myViewer3dSamples->AppendBottle(); myDocument3d->SetObjects(GetCurrentSamples()->Get3dObjects()); myGeomWidget->Show3d(); break; } case AppType_Geometry: case AppType_Topology: case AppType_PengKai: case AppType_Triangulation: case AppType_Unknown: { break; } } } void ApplicationCommonWindow::onAbout() { QMessageBox::information(this, tr("OCCT Overview"), tr("Qt based application to study OpenCASCADE Technology"), tr("Ok"), QString::null, QString::null, 0, 0); } TCollection_AsciiString ApplicationCommonWindow::getSampleSourceDir() { TCollection_AsciiString aSampleSourceDir = OSD_Environment("CSF_OCCTOverviewSampleCodePath").Value(); if (aSampleSourceDir.IsEmpty()) { TCollection_AsciiString aCasRoot = OSD_Environment("CASROOT").Value(); if (!aCasRoot.IsEmpty()) { aSampleSourceDir = aCasRoot + "/samples/OCCTOverview/code"; } } return aSampleSourceDir; } QAction* ApplicationCommonWindow::CreateAction (const QString& theActionName, const QString& theShortcut, const QString& theIconName) { QAction* aAction(NULL); if (theIconName.isEmpty()) { aAction = new QAction(theActionName, this); } else { QPixmap aIcon = QPixmap(theIconName); aAction = new QAction(aIcon, theActionName, this); } aAction->setToolTip(theActionName); aAction->setStatusTip(theActionName); aAction->setShortcut(theShortcut); return aAction; } template QAction* ApplicationCommonWindow::CreateSample (PointerToMemberFunction theHandlerMethod, const char* theActionName) { QAction* anAction = new QAction(QObject::tr(theActionName), this); connect(anAction, SIGNAL(triggered()), this, SLOT(theHandlerMethod())); return anAction; } void ApplicationCommonWindow::resizeEvent(QResizeEvent* e) { QMainWindow::resizeEvent(e); statusBar()->setSizeGripEnabled(!isMaximized()); } void ApplicationCommonWindow::onProcessSample(const QString& theSampleName) { QApplication::setOverrideCursor(Qt::WaitCursor); setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); GetCurrentSamples()->Process(theSampleName.toUtf8().data()); myDocument3d->SetObjects(GetCurrentSamples()->Get3dObjects()); myDocument2d->SetObjects(GetCurrentSamples()->Get2dObjects()); myCodeView->setPlainText(GetCurrentSamples()->GetCode().ToCString()); myResultView->setPlainText(GetCurrentSamples()->GetResult().ToCString()); myGeomWidget->FitAll(); QApplication::restoreOverrideCursor(); } void ApplicationCommonWindow::onProcessExchange(const QString& theSampleName) { setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); int aMode = 0; QString aFileName = selectFileName(theSampleName, getDataExchangeDialog(theSampleName), aMode); if (aFileName.isEmpty()) { return; } QApplication::setOverrideCursor(Qt::WaitCursor); myDataExchangeSamples->SetFileName(aFileName.toUtf8().data()); myDataExchangeSamples->SetStepType(static_cast(aMode)); myDataExchangeSamples->Process(theSampleName.toUtf8().data()); myDocument3d->SetObjects(myDataExchangeSamples->Get3dObjects()); myDocument2d->SetObjects(myDataExchangeSamples->Get2dObjects()); myCodeView->setPlainText(myDataExchangeSamples->GetCode().ToCString()); myResultView->setPlainText(myDataExchangeSamples->GetResult().ToCString()); myGeomWidget->FitAll(); QApplication::restoreOverrideCursor(); } void ApplicationCommonWindow::onProcessOcaf(const QString& theSampleName) { setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); if (theSampleName.indexOf("Dialog") == 0) { int aMode = 0; // not used QString aFileName = selectFileName(theSampleName, getOcafDialog(theSampleName), aMode); if (aFileName.isEmpty()) { return; } myOcafSamples->SetFileName(aFileName.toUtf8().data()); } QApplication::setOverrideCursor(Qt::WaitCursor); myOcafSamples->Process(theSampleName.toUtf8().data()); myDocument2d->SetObjects(myOcafSamples->Get2dObjects()); myCodeView->setPlainText(myOcafSamples->GetCode().ToCString()); myResultView->setPlainText(myOcafSamples->GetResult().ToCString()); QApplication::restoreOverrideCursor(); } void ApplicationCommonWindow::onProcessViewer3d(const QString& theSampleName) { setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); QApplication::setOverrideCursor(Qt::WaitCursor); myViewer3dSamples->Process(theSampleName.toUtf8().data()); myCodeView->setPlainText(myViewer3dSamples->GetCode().ToCString()); myResultView->setPlainText(myViewer3dSamples->GetResult().ToCString()); myGeomWidget->FitAll(); QApplication::restoreOverrideCursor(); } void ApplicationCommonWindow::onProcessViewer2d(const QString& theSampleName) { setWindowTitle(ALL_CATEGORIES[myAppType] + " - " + theSampleName); Standard_Boolean anIsFileSample = Viewer2dSamples::IsFileSample(theSampleName.toUtf8().data()); QString aFileName; if (anIsFileSample) { int aMode = 0; // not used aFileName = selectFileName(theSampleName, getOcafDialog(theSampleName), aMode); if (aFileName.isEmpty()) { return; } myViewer2dSamples->SetFileName(aFileName.toUtf8().data()); } if (!anIsFileSample || (anIsFileSample && !aFileName.isEmpty())) { QApplication::setOverrideCursor(Qt::WaitCursor); myViewer2dSamples->Process(theSampleName.toUtf8().data()); if (!Viewer2dSamples::IsShadedSample(theSampleName.toUtf8().data())) { myDocument2d->SetObjects(myViewer2dSamples->Get2dObjects(), Standard_False); } else { myDocument2d->SetObjects(myViewer2dSamples->Get2dObjects(), Standard_True); } myCodeView->setPlainText(myViewer2dSamples->GetCode().ToCString()); myResultView->setPlainText(myViewer2dSamples->GetResult().ToCString()); myGeomWidget->Show2d(); QApplication::restoreOverrideCursor(); } else { myResultView->setPlainText("No file selected!"); } } QString ApplicationCommonWindow::selectFileName(const QString& theSampleName, TranslateDialog* theDialog, int& theMode) { Q_UNUSED(theSampleName) std::shared_ptr aDialog(theDialog); int ret = aDialog->exec(); theMode = aDialog->getMode(); qApp->processEvents(); QString aFilename; QStringList aFileNameList; if (ret != QDialog::Accepted) { return aFilename; } aFileNameList = aDialog->selectedFiles(); if (!aFileNameList.isEmpty()) { aFilename = aFileNameList[0]; } if (!QFileInfo(aFilename).completeSuffix().length()) { QString selFilter = aDialog->selectedNameFilter(); int idx = selFilter.indexOf("(*."); if (idx != -1) { QString tail = selFilter.mid(idx + 3); idx = tail.indexOf(" "); if (idx == -1) { idx = tail.indexOf(")"); } QString ext = tail.left(idx); if (ext.length()) { aFilename += QString(".") + ext; } } } return aFilename; } TranslateDialog* ApplicationCommonWindow::getDataExchangeDialog(const QString& theSampleName) { TranslateDialog* aTranslateDialog = new TranslateDialog(this, 0, true); TCollection_AsciiString aSampleName(theSampleName.toUtf8().data()); if (DataExchangeSamples::IsExportSample(aSampleName)) { aTranslateDialog->setWindowTitle("Export file"); aTranslateDialog->setFileMode(QFileDialog::AnyFile); aTranslateDialog->setAcceptMode(QFileDialog::AcceptSave); } else if (DataExchangeSamples::IsImportSample(aSampleName)) { aTranslateDialog->setWindowTitle("Import file"); aTranslateDialog->setFileMode(QFileDialog::ExistingFile); aTranslateDialog->setAcceptMode(QFileDialog::AcceptOpen); } QString aFormatFilter; if (DataExchangeSamples::IsBrepSample(aSampleName)) { aFormatFilter = "BREP Files(*.brep *.rle)"; } else if (DataExchangeSamples::IsStepSample(aSampleName)) { aFormatFilter = "STEP Files (*.stp *.step)"; aTranslateDialog->addMode(STEPControl_ManifoldSolidBrep, "Manifold Solid Brep"); aTranslateDialog->addMode(STEPControl_FacetedBrep, "Faceted Brep"); aTranslateDialog->addMode(STEPControl_ShellBasedSurfaceModel, "Shell Based Surface Model"); aTranslateDialog->addMode(STEPControl_GeometricCurveSet, "Geometric Curve Set"); } else if (DataExchangeSamples::IsIgesSample(aSampleName)) { aFormatFilter = "IGES Files (*.igs *.iges)"; } else if (DataExchangeSamples::IsStlSample(aSampleName)) { aFormatFilter = "STL Files (*.stl)"; } else if (DataExchangeSamples::IsVrmlSample(aSampleName)) { aFormatFilter = "VRML Files (*.vrml)"; } else if (DataExchangeSamples::IsImageSample(aSampleName)) { aFormatFilter = "All Image Files (*.bmp *.gif *.jpg *.jpeg *.png *.tga)"; } QStringList aFilters; aFilters.append(aFormatFilter); aFilters.append("All Files(*.*)"); aTranslateDialog->setNameFilters(aFilters); aTranslateDialog->clear(); return aTranslateDialog; } TranslateDialog* ApplicationCommonWindow::getOcafDialog(const QString& theSampleName) { TranslateDialog* aTranslateDialog = new TranslateDialog(this, 0, true); TCollection_AsciiString aSampleName(theSampleName.toUtf8().data()); if (OcafSamples::IsExportSample(aSampleName)) { aTranslateDialog->setWindowTitle("Export file"); aTranslateDialog->setFileMode(QFileDialog::AnyFile); aTranslateDialog->setAcceptMode(QFileDialog::AcceptSave); } else if (OcafSamples::IsImportSample(aSampleName)) { aTranslateDialog->setWindowTitle("Import file"); aTranslateDialog->setFileMode(QFileDialog::ExistingFile); aTranslateDialog->setAcceptMode(QFileDialog::AcceptOpen); } QStringList aFilters; if (OcafSamples::IsBinarySample(aSampleName)) { aFilters.append("Binary OCAF Sample (*.cbf)"); } if (OcafSamples::IsXmlSample(aSampleName)) { aFilters.append("XML OCAF Sample (*.xml)"); } aFilters.append("All Files(*.*)"); aTranslateDialog->setNameFilters(aFilters); aTranslateDialog->clear(); return aTranslateDialog; } QMenu* ApplicationCommonWindow::MenuFromDomNode(QDomElement& theItemElement, QWidget* theParent, QSignalMapper* theMapper) { QString anItemName = theItemElement.attribute("name"); QMenu* aMenu = new QMenu(anItemName, theParent); QDomElement anChildItemElement = theItemElement.firstChildElement("MenuItem"); QDomElement anSampleElement = theItemElement.firstChildElement("Sample"); while(anChildItemElement.isElement()) { aMenu->addMenu(MenuFromDomNode(anChildItemElement, aMenu, theMapper)); anChildItemElement = anChildItemElement.nextSibling().toElement(); } while(anSampleElement.isElement()) { QString aSampleName = anSampleElement.attribute("name"); QString aSampleFunction = anSampleElement.attribute("function"); QAction* anAction = aMenu->addAction(aSampleFunction); anAction->setText(aSampleName); theMapper->setMapping(anAction, aSampleFunction); connect(anAction, SIGNAL(triggered()), theMapper, SLOT(map())); anSampleElement = anSampleElement.nextSibling().toElement(); } return aMenu; } void ApplicationCommonWindow::MenuFormXml(const QString& thePath, QSignalMapper* theMapper, QList& theMunusList) { QDomDocument aDomDocument; theMunusList.clear(); QFile aXmlFile(thePath); QString anErrorMessage; if (aXmlFile.error() != QFile::NoError) { anErrorMessage = aXmlFile.errorString(); Message::SendFail()