Macro.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 # include <assert.h>
00028 # include <stdio.h>
00029 # include <QFile>
00030 # include <QTextStream>
00031 #endif
00032
00034 #include "Macro.h"
00035
00036 #include <Base/Interpreter.h>
00037 #include <Base/Console.h>
00038 #include <Base/Exception.h>
00039 #include <App/Application.h>
00040
00041 #include "MainWindow.h"
00042 #include "PythonConsole.h"
00043 #include "PythonConsolePy.h"
00044 #include "PythonDebugger.h"
00045
00046 using namespace Gui;
00047
00048
00049 MacroManager::MacroManager()
00050 : openMacro(false),
00051 recordGui(true),
00052 guiAsComment(true),
00053 scriptToPyConsole(true),
00054 pyConsole(0),
00055 pyDebugger(new PythonDebugger())
00056 {
00057
00058 this->params = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro");
00059 this->params->Attach(this);
00060 this->params->NotifyAll();
00061 }
00062
00063 MacroManager::~MacroManager()
00064 {
00065 delete pyDebugger;
00066 this->params->Detach(this);
00067 }
00068
00069 void MacroManager::OnChange(Base::Subject<const char*> &rCaller, const char * sReason)
00070 {
00071 this->recordGui = this->params->GetBool("RecordGui", true);
00072 this->guiAsComment = this->params->GetBool("GuiAsComment", true);
00073 this->scriptToPyConsole = this->params->GetBool("ScriptToPyConsole", true);
00074 }
00075
00076 void MacroManager::open(MacroType eType,const char *sName)
00077 {
00078
00079 assert(!this->openMacro);
00080 assert(eType == File);
00081
00082
00083 this->macroName = QString::fromUtf8(sName);
00084 if (!this->macroName.endsWith(QLatin1String(".FCMacro")))
00085 this->macroName += QLatin1String(".FCMacro");
00086
00087 this->macroInProgress.clear();
00088 this->openMacro = true;
00089
00090 Base::Console().Log("CmdM: Open macro: %s\n", sName);
00091 }
00092
00093 void MacroManager::commit(void)
00094 {
00095 QFile file(this->macroName);
00096 if (file.open(QFile::WriteOnly))
00097 {
00098
00099 QTextStream str(&file);
00100 QStringList lines = this->macroInProgress.split(QLatin1Char('\n'));
00101 QStringList import; import << QString::fromAscii("import FreeCAD\n");
00102 QStringList body;
00103
00104 QStringList::Iterator it;
00105 for ( it = lines.begin(); it != lines.end(); ++it )
00106 {
00107 if ((*it).startsWith(QLatin1String("import ")) ||
00108 (*it).startsWith(QLatin1String("#import ")))
00109 {
00110 if (import.indexOf(*it + QLatin1Char('\n')) == -1)
00111 import.push_back(*it + QLatin1Char('\n'));
00112 }
00113 else
00114 {
00115 body.push_back(*it + QLatin1Char('\n'));
00116 }
00117 }
00118
00119 QString header = QString::fromAscii("# Macro Begin: ");
00120 header += this->macroName;
00121 header += QString::fromAscii(" +++++++++++++++++++++++++++++++++++++++++++++++++\n");
00122
00123 QString footer = QString::fromAscii("# Macro End: ");
00124 footer += this->macroName;
00125 footer += QString::fromAscii(" +++++++++++++++++++++++++++++++++++++++++++++++++\n");
00126
00127
00128 str << header;
00129 for ( it = import.begin(); it != import.end(); ++it )
00130 str << (*it);
00131 str << QLatin1Char('\n');
00132 for ( it = body.begin(); it != body.end(); ++it )
00133 str << (*it);
00134 str << footer;
00135
00136 Base::Console().Log("Commit macro: %s\n",(const char*)this->macroName.toUtf8());
00137
00138 this->macroInProgress.clear();
00139 this->macroName.clear();
00140 this->openMacro = false;
00141 }
00142 else {
00143 Base::Console().Error("Cannot open file to write macro: %s\n",
00144 (const char*)this->macroName.toUtf8());
00145 cancel();
00146 }
00147 }
00148
00149 void MacroManager::cancel(void)
00150 {
00151 Base::Console().Log("Cancel macro: %s\n",(const char*)this->macroName.toUtf8());
00152
00153 this->macroInProgress.clear();
00154 this->macroName.clear();
00155 this->openMacro = false;
00156 }
00157
00158 void MacroManager::addLine(LineType Type, const char* sLine)
00159 {
00160 if (this->openMacro)
00161 {
00162 if(Type == Gui)
00163 {
00164 if (this->recordGui && this->guiAsComment)
00165 this->macroInProgress += QLatin1Char('#');
00166 else if (!this->recordGui)
00167 return;
00168 }
00169
00170 this->macroInProgress += QString::fromAscii(sLine);
00171 this->macroInProgress += QLatin1Char('\n');
00172 }
00173
00174 if (this->scriptToPyConsole) {
00175
00176 if (!this->pyConsole)
00177 this->pyConsole = Gui::getMainWindow()->findChild<Gui::PythonConsole*>();
00178
00179 if (this->pyConsole)
00180 this->pyConsole->printStatement(QString::fromUtf8(sLine));
00181 }
00182 }
00183
00184 void MacroManager::setModule(const char* sModule)
00185 {
00186 if (this->openMacro && sModule && *sModule != '\0')
00187 {
00188 this->macroInProgress += QString::fromAscii("import ");
00189 this->macroInProgress += QString::fromAscii(sModule);
00190 this->macroInProgress += QLatin1Char('\n');
00191 }
00192 }
00193
00194 namespace Gui {
00195 class PythonRedirector
00196 {
00197 public:
00198 PythonRedirector(const char* type, PyObject* obj) : std_out(type), out(obj)
00199 {
00200 Base::PyGILStateLocker lock;
00201 old = PySys_GetObject(const_cast<char*>(std_out));
00202 PySys_SetObject(const_cast<char*>(std_out), obj);
00203 }
00204 ~PythonRedirector()
00205 {
00206 Base::PyGILStateLocker lock;
00207 PySys_SetObject(const_cast<char*>(std_out), old);
00208 Py_XDECREF(out);
00209 }
00210 private:
00211 const char* std_out;
00212 PyObject* out;
00213 PyObject* old;
00214 };
00215 }
00216
00217 void MacroManager::run(MacroType eType,const char *sName)
00218 {
00219 try
00220 {
00221 PythonRedirector std_out("stdout",new OutputStdout);
00222 PythonRedirector std_err("stderr",new OutputStderr);
00223
00224 Base::Interpreter().runFile(sName);
00225 }
00226 catch (const Base::Exception& e)
00227 {
00228 qWarning("%s",e.what());
00229 }
00230 }
00231
00232 PythonDebugger* MacroManager::debugger() const
00233 {
00234 return pyDebugger;
00235 }