Macro.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2004 Jürgen Riegel <juergen.riegel@web.de>              *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
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     // Attach to the Parametergroup regarding macros
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     // check 
00079     assert(!this->openMacro);
00080     assert(eType == File);
00081 
00082     // Convert from Utf-8
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         // sort import lines and avoid duplicates
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         // write the data to the text file
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; // ignore Gui commands
00168         }
00169 
00170         this->macroInProgress += QString::fromAscii(sLine);
00171         this->macroInProgress += QLatin1Char('\n');
00172     }
00173 
00174     if (this->scriptToPyConsole) {
00175         // search for the Python console
00176         if (!this->pyConsole)
00177             this->pyConsole = Gui::getMainWindow()->findChild<Gui::PythonConsole*>();
00178         // Python console found?
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         //The given path name is expected to be Utf-8
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 }

Generated on Wed Nov 23 19:00:21 2011 for FreeCAD by  doxygen 1.6.1