diff --git a/src/Doc/freecad.qch b/src/Doc/freecad.qch index 65c745075..2ae58e688 100644 Binary files a/src/Doc/freecad.qch and b/src/Doc/freecad.qch differ diff --git a/src/Doc/freecad.qhc b/src/Doc/freecad.qhc index ad7a7c3c4..972b2d07e 100644 Binary files a/src/Doc/freecad.qhc and b/src/Doc/freecad.qhc differ diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 53dec5681..ccdc09180 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -727,31 +727,35 @@ void Application::setActiveDocument(Gui::Document* pcDocument) return; } d->activeDocument = pcDocument; - std::string name; + std::string nameApp, nameGui; // This adds just a line to the macro file but does not set the active document + // Macro recording of this is problematic, thus it's written out as comment. if (pcDocument){ - name += "App.setActiveDocument(\""; - name += pcDocument->getDocument()->getName(); - name += "\")\n"; - name += "App.ActiveDocument=App.getDocument(\""; - name += pcDocument->getDocument()->getName(); - name += "\")\n"; - name += "Gui.ActiveDocument=Gui.getDocument(\""; - name += pcDocument->getDocument()->getName(); - name += "\")"; - macroManager()->addLine(MacroManager::Gui,name.c_str()); + nameApp += "App.setActiveDocument(\""; + nameApp += pcDocument->getDocument()->getName(); + nameApp += "\")\n"; + nameApp += "App.ActiveDocument=App.getDocument(\""; + nameApp += pcDocument->getDocument()->getName(); + nameApp += "\")"; + macroManager()->addLine(MacroManager::Cmt,nameApp.c_str()); + nameGui += "Gui.ActiveDocument=Gui.getDocument(\""; + nameGui += pcDocument->getDocument()->getName(); + nameGui += "\")"; + macroManager()->addLine(MacroManager::Cmt,nameGui.c_str()); } else { - name += "App.setActiveDocument(\"\")\n"; - name += "App.ActiveDocument=None\n"; - name += "Gui.ActiveDocument=None"; - macroManager()->addLine(MacroManager::Gui,name.c_str()); + nameApp += "App.setActiveDocument(\"\")\n"; + nameApp += "App.ActiveDocument=None"; + macroManager()->addLine(MacroManager::Cmt,nameApp.c_str()); + nameGui += "Gui.ActiveDocument=None"; + macroManager()->addLine(MacroManager::Cmt,nameGui.c_str()); } // Sets the currently active document try { - Base::Interpreter().runString(name.c_str()); + Base::Interpreter().runString(nameApp.c_str()); + Base::Interpreter().runString(nameGui.c_str()); } catch (const Base::Exception& e) { Base::Console().Warning(e.what()); @@ -1267,7 +1271,7 @@ void Application::runCommand(bool bForce, const char* sCmd,...) va_end(namelessVars); if (bForce) - d->macroMngr->addLine(MacroManager::Base,format); + d->macroMngr->addLine(MacroManager::App,format); else d->macroMngr->addLine(MacroManager::Gui,format); @@ -1288,7 +1292,7 @@ bool Application::runPythonCode(const char* cmd, bool gui, bool pyexc) if (gui) d->macroMngr->addLine(MacroManager::Gui,cmd); else - d->macroMngr->addLine(MacroManager::Base,cmd); + d->macroMngr->addLine(MacroManager::App,cmd); try { Base::Interpreter().runString(cmd); diff --git a/src/Gui/Assistant.cpp b/src/Gui/Assistant.cpp index 1b08ff593..e2c8a6ae2 100644 --- a/src/Gui/Assistant.cpp +++ b/src/Gui/Assistant.cpp @@ -76,7 +76,7 @@ bool Assistant::startAssistant() if (proc->state() != QProcess::Running) { #ifdef Q_OS_WIN QString app; - app = QDir::convertSeparators(QString::fromUtf8 + app = QDir::toNativeSeparators(QString::fromUtf8 (App::GetApplication().GetHomePath()) + QLatin1String("bin/")); #else QString app = QLibraryInfo::location(QLibraryInfo::BinariesPath) + QDir::separator(); diff --git a/src/Gui/Command.cpp b/src/Gui/Command.cpp index 2e1082ca2..3412dd1f1 100644 --- a/src/Gui/Command.cpp +++ b/src/Gui/Command.cpp @@ -416,7 +416,7 @@ void Command::doCommand(DoCmd_Type eType,const char* sCmd,...) if (eType == Gui) Gui::Application::Instance->macroManager()->addLine(MacroManager::Gui,format); else - Gui::Application::Instance->macroManager()->addLine(MacroManager::Base,format); + Gui::Application::Instance->macroManager()->addLine(MacroManager::App,format); try { Base::Interpreter().runString(format); @@ -439,7 +439,7 @@ void Command::runCommand(DoCmd_Type eType,const char* sCmd) if (eType == Gui) Gui::Application::Instance->macroManager()->addLine(MacroManager::Gui,sCmd); else - Gui::Application::Instance->macroManager()->addLine(MacroManager::Base,sCmd); + Gui::Application::Instance->macroManager()->addLine(MacroManager::App,sCmd); Base::Interpreter().runString(sCmd); } @@ -476,7 +476,7 @@ const std::string Command::strToPython(const char* Str) void Command::updateActive(void) { WaitCursor wc; - doCommand(Gui,"App.ActiveDocument.recompute()"); + doCommand(App,"App.ActiveDocument.recompute()"); } bool Command::isActiveObjectValid(void) diff --git a/src/Gui/DlgMacroRecordImp.cpp b/src/Gui/DlgMacroRecordImp.cpp index c8f3e4f55..d0b1571cc 100644 --- a/src/Gui/DlgMacroRecordImp.cpp +++ b/src/Gui/DlgMacroRecordImp.cpp @@ -25,6 +25,8 @@ #ifndef _PreComp_ # include # include +# include +# include #endif #include "Macro.h" @@ -53,9 +55,7 @@ DlgMacroRecordImp::DlgMacroRecordImp( QWidget* parent, Qt::WFlags fl ) // get the macro home path this->macroPath = QString::fromUtf8(getWindowParameter()->GetASCII("MacroPath", App::Application::getUserAppDataDir().c_str()).c_str()); - // check on PATHSEP at the end - if (this->macroPath.at(this->macroPath.length()-1) != QLatin1Char(PATHSEP)) - this->macroPath += QLatin1Char(PATHSEP); + this->macroPath = QDir::toNativeSeparators(QDir(this->macroPath).path() + QDir::separator()); // set the edit fields this->lineEditMacroPath->setText(macroPath); @@ -96,10 +96,9 @@ void DlgMacroRecordImp::on_buttonStart_clicked() // search in the macro path first for an already existing macro QString fn = this->macroPath + lineEditPath->text(); - if (!fn.endsWith(QLatin1String(".FCMacro")) ) fn += QLatin1String(".FCMacro"); + if (!fn.endsWith(QLatin1String(".FCMacro"))) fn += QLatin1String(".FCMacro"); QFileInfo fi(fn); - if ( fi.isFile() && fi.exists() ) - { + if (fi.isFile() && fi.exists()) { if (QMessageBox::question(this, tr("Existing macro"), tr("The macro '%1' already exists. Do you want to overwrite?").arg(fn), QMessageBox::Yes, @@ -109,6 +108,14 @@ void DlgMacroRecordImp::on_buttonStart_clicked() return; } + QFile file(fn); + if (!file.open(QFile::WriteOnly)) { + QMessageBox::information(getMainWindow(), tr("Macro recorder"), + tr("You have no write permission for the directory. Please, choose another one.")); + return; + } + file.close(); + // open the macro recording this->macroManager->open(MacroManager::File, fn.toUtf8().constData()); accept(); @@ -143,7 +150,7 @@ void DlgMacroRecordImp::on_pushButtonChooseDir_clicked() { QString newDir = QFileDialog::getExistingDirectory(0,tr("Choose macro directory"),macroPath); if (!newDir.isEmpty()) { - macroPath = QDir::convertSeparators(newDir + QDir::separator()); + macroPath = QDir::toNativeSeparators(newDir + QDir::separator()); this->lineEditMacroPath->setText(macroPath); getWindowParameter()->SetASCII("MacroPath",macroPath.toUtf8()); } diff --git a/src/Gui/Macro.cpp b/src/Gui/Macro.cpp index 20a7f49c4..47a82ea20 100644 --- a/src/Gui/Macro.cpp +++ b/src/Gui/Macro.cpp @@ -99,22 +99,22 @@ void MacroManager::commit(void) { // sort import lines and avoid duplicates QTextStream str(&file); - QStringList lines = this->macroInProgress.split(QLatin1Char('\n')); - QStringList import; import << QString::fromAscii("import FreeCAD\n"); + QStringList import; + import << QString::fromAscii("import FreeCAD"); QStringList body; QStringList::Iterator it; - for ( it = lines.begin(); it != lines.end(); ++it ) + for (it = this->macroInProgress.begin(); it != this->macroInProgress.end(); ++it ) { if ((*it).startsWith(QLatin1String("import ")) || (*it).startsWith(QLatin1String("#import "))) { - if (import.indexOf(*it + QLatin1Char('\n')) == -1) - import.push_back(*it + QLatin1Char('\n')); + if (import.indexOf(*it) == -1) + import.push_back(*it); } else { - body.push_back(*it + QLatin1Char('\n')); + body.push_back(*it); } } @@ -128,11 +128,11 @@ void MacroManager::commit(void) // write the data to the text file str << header; - for ( it = import.begin(); it != import.end(); ++it ) - str << (*it); + for (it = import.begin(); it != import.end(); ++it) + str << (*it) << QLatin1Char('\n'); str << QLatin1Char('\n'); - for ( it = body.begin(); it != body.end(); ++it ) - str << (*it); + for (it = body.begin(); it != body.end(); ++it) + str << (*it) << QLatin1Char('\n'); str << footer; Base::Console().Log("Commit macro: %s\n",(const char*)this->macroName.toUtf8()); @@ -159,18 +159,24 @@ void MacroManager::cancel(void) void MacroManager::addLine(LineType Type, const char* sLine) { - if (this->openMacro) - { - if(Type == Gui) - { + if (this->openMacro) { + bool comment = false; + if (Type == Gui) { if (this->recordGui && this->guiAsComment) - this->macroInProgress += QLatin1Char('#'); + comment = true; else if (!this->recordGui) return; // ignore Gui commands } + else if (Type == Cmt) { + comment = true; + } - this->macroInProgress += QString::fromAscii(sLine); - this->macroInProgress += QLatin1Char('\n'); + QStringList lines = QString::fromAscii(sLine).split(QLatin1String("\n")); + if (comment) { + for (QStringList::iterator it = lines.begin(); it != lines.end(); ++it) + it->prepend(QLatin1String("#")); + } + this->macroInProgress.append(lines); } if (this->scriptToPyConsole) { @@ -187,9 +193,7 @@ void MacroManager::setModule(const char* sModule) { if (this->openMacro && sModule && *sModule != '\0') { - this->macroInProgress += QString::fromAscii("import "); - this->macroInProgress += QString::fromAscii(sModule); - this->macroInProgress += QLatin1Char('\n'); + this->macroInProgress.append(QString::fromAscii("import %1").arg(QString::fromAscii(sModule))); } } diff --git a/src/Gui/Macro.h b/src/Gui/Macro.h index bbd4266b1..ba7667d25 100644 --- a/src/Gui/Macro.h +++ b/src/Gui/Macro.h @@ -26,6 +26,7 @@ // Std. configurations #include +#include #include #include @@ -51,14 +52,15 @@ public: /** Macro type enumeration */ enum MacroType { File, /**< The macro will be saved in a file */ - App, /**< The macro belongs to the Application and will be saved in the UserParameter */ - Doc /**< Teh macro belongs to the Document and will be saved and restored with the Document */ + User, /**< The macro belongs to the Application and will be saved in the UserParameter */ + Doc /**< The macro belongs to the Document and will be saved and restored with the Document */ }; /** Line type enumeration */ enum LineType { - Base, /**< The line effects only the document and Application (FreeCAD) */ - Gui, /**< The line effects the Gui (FreeCADGui) */ + App, /**< The line effects only the document and Application (FreeCAD) */ + Gui, /**< The line effects the Gui (FreeCADGui) */ + Cmt /**< The line is handled as a comment */ }; /** Opens a new Macro recording session @@ -92,7 +94,7 @@ public: void OnChange(Base::Subject &rCaller, const char * sReason); protected: - QString macroInProgress; /**< Container for the macro */ + QStringList macroInProgress; /**< Container for the macro */ QString macroName; /**< name of the macro */ bool openMacro; bool recordGui; diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 6e17e1d72..6a0b733c5 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -104,6 +104,7 @@ #include "SoFCVectorizeU3DAction.h" #include "SoFCVectorizeSVGAction.h" #include "SoFCDB.h" +#include "Application.h" #include "MainWindow.h" #include "NavigationStyle.h" #include "ViewProvider.h" @@ -1447,6 +1448,7 @@ void View3DInventorViewer::viewAll(float factor) void View3DInventorViewer::viewSelection() { +#if 0 // Search for all SoFCSelection nodes SoSearchAction searchAction; searchAction.setType(SoFCSelection::getClassTypeId()); @@ -1472,6 +1474,18 @@ void View3DInventorViewer::viewSelection() root->addChild(select); } } +#else + SoGroup* root = new SoGroup(); + root->ref(); + + std::vector selection = Selection().getObjectsOfType(App::DocumentObject::getClassTypeId()); + for (std::vector::iterator it = selection.begin(); it != selection.end(); ++it) { + ViewProvider* vp = Application::Instance->getViewProvider(*it); + if (vp) { + root->addChild(vp->getRoot()); + } + } +#endif SoCamera* cam = this->getCamera(); if (cam) cam->viewAll(root, this->getViewportRegion()); diff --git a/src/Mod/Part/App/Part2DObject.cpp b/src/Mod/Part/App/Part2DObject.cpp index 50023a26b..662f0d872 100644 --- a/src/Mod/Part/App/Part2DObject.cpp +++ b/src/Mod/Part/App/Part2DObject.cpp @@ -82,7 +82,13 @@ void Part2DObject::positionBySupport(void) const Part::TopoShape &shape = part->Shape.getShape(); if (shape._Shape.IsNull()) throw Base::Exception("Support shape is empty!"); - TopoDS_Shape sh = shape.getSubShape(sub[0].c_str()); + TopoDS_Shape sh; + try { + sh = shape.getSubShape(sub[0].c_str()); + } + catch (Standard_Failure) { + throw Base::Exception("Face in support shape doesn't exist!"); + } const TopoDS_Face &face = TopoDS::Face(sh); if (face.IsNull()) throw Base::Exception("Null face in Part2DObject::positionBySupport()!"); diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.cpp b/src/Mod/PartDesign/App/FeatureSketchBased.cpp index 9b01368fb..64694c44a 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.cpp +++ b/src/Mod/PartDesign/App/FeatureSketchBased.cpp @@ -618,10 +618,14 @@ const bool SketchBased::checkLineCrossesFace(const gp_Lin &line, const TopoDS_Fa p_eps2 = adapt2.Value(adapt2.LastParameter() - 2*Precision::Confusion()); // now check if we get a change in the sign of the distances - Standard_Real dist_p_eps1_pnt = gp_Dir(gp_Vec(p_eps1, pnt)).Dot(dir); - Standard_Real dist_p_eps2_pnt = gp_Dir(gp_Vec(p_eps2, pnt)).Dot(dir); - if (dist_p_eps1_pnt * dist_p_eps2_pnt < 0) - return true; + Standard_Real dist_p_eps1_pnt = gp_Vec(p_eps1, pnt).Dot(gp_Vec(dir)); + Standard_Real dist_p_eps2_pnt = gp_Vec(p_eps2, pnt).Dot(gp_Vec(dir)); + // distance to the plane must be noticable + if (fabs(dist_p_eps1_pnt) > Precision::Confusion() && + fabs(dist_p_eps2_pnt) > Precision::Confusion()) { + if (dist_p_eps1_pnt * dist_p_eps2_pnt < 0) + return true; + } } } } @@ -727,7 +731,15 @@ void SketchBased::remapSupportShape(const TopoDS_Shape& newShape) } bool success = false; - TopoDS_Shape element = shape.getSubShape(it->c_str()); + TopoDS_Shape element; + try { + element = shape.getSubShape(it->c_str()); + } + catch (Standard_Failure) { + // This shape doesn't even exist, so no chance to do some tests + newSubValues.push_back(*it); + continue; + } try { // as very first test check if old face and new face are parallel planes TopoDS_Shape newElement = Part::TopoShape(newShape).getSubShape(it->c_str());