PropertyFile.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   (c) Jürgen Riegel (juergen.riegel@web.de) 2008                        *
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 <sstream>
00028 #endif
00029 
00031 
00032 #include <Base/Exception.h>
00033 #include <Base/Reader.h>
00034 #include <Base/Writer.h>
00035 #include <Base/Stream.h>
00036 #include <Base/Console.h>
00037 #include <Base/PyObjectBase.h>
00038 
00039 #include "PropertyFile.h"
00040 #include "Document.h"
00041 #include "PropertyContainer.h"
00042 #include "DocumentObject.h"
00043 #define new DEBUG_CLIENTBLOCK
00044 using namespace App;
00045 using namespace Base;
00046 using namespace std;
00047 
00048 
00049 
00050 //**************************************************************************
00051 // PropertyFileIncluded
00052 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00053 
00054 TYPESYSTEM_SOURCE(App::PropertyFileIncluded , App::Property);
00055 
00056 PropertyFileIncluded::PropertyFileIncluded()
00057 {
00058 
00059 }
00060 
00061 PropertyFileIncluded::~PropertyFileIncluded()
00062 {
00063     // clean up
00064     if (!_cValue.empty()) {
00065         Base::FileInfo file(_cValue.c_str());
00066         file.deleteFile();
00067     }
00068 }
00069 
00070 std::string PropertyFileIncluded::getDocTransientPath(void) const
00071 {
00072     PropertyContainer *co = getContainer();
00073     if (co->isDerivedFrom(DocumentObject::getClassTypeId()))
00074         return dynamic_cast<DocumentObject*>(co)->getDocument()->TransientDir.getValue();
00075 
00076     return std::string();
00077 }
00078 
00079 std::string PropertyFileIncluded::getExchangeTempFile(void) const
00080 {
00081     return Base::FileInfo::getTempFileName(Base::FileInfo
00082         (getValue()).fileName().c_str(), getDocTransientPath().c_str());
00083 }
00084 
00085 void PropertyFileIncluded::setValue(const char* sFile, const char* sName)
00086 {
00087     if (sFile) {
00088         if (_cValue == sFile)
00089             throw Base::Exception("Not possible to set the same file!");
00090 
00091         std::string pathTrans = getDocTransientPath();
00092         Base::FileInfo file(sFile);
00093         std::string path = file.dirPath();
00094         if (!file.exists()) {
00095             std::stringstream str;
00096             str << "File " << file.filePath() << " does not exist.";
00097             throw Base::Exception(str.str());
00098         }
00099 
00100         aboutToSetValue(); // undo redo by move the file away with temp name
00101 
00102         // remove old file (if not moved by undo)
00103         Base::FileInfo value(_cValue);
00104         std::string pathAct = value.dirPath();
00105         if (value.exists())
00106             value.deleteFile();
00107 
00108         // if a special name given, use this instead
00109         if (sName) {
00110             Base::FileInfo ExtraName(path + "/" + sName);
00111             if (ExtraName.exists() ) {
00112                 // if a file with this name already exists search for a new one
00113                 int i=0;
00114                 
00115                 do {
00116                     i++;
00117                     std::stringstream str;
00118                     str << path << "/" << sName << i;
00119                     ExtraName.setFile(str.str());
00120                 }
00121                 while (ExtraName.exists());
00122                 _cValue = ExtraName.filePath();
00123                 _BaseFileName = ExtraName.fileName();
00124 
00125             }
00126             else {
00127                 _cValue = path + "/" + sName;
00128                 _BaseFileName = sName;
00129             }
00130         }
00131         else if (value.fileName().empty()) {
00132             _cValue = pathTrans + "/" + file.fileName();
00133             _BaseFileName = file.fileName();
00134         }
00135 
00136         // if the files is already in transient dir of the document, just use it
00137         if (path == pathTrans) {
00138             bool done = file.renameFile(_cValue.c_str());
00139             //assert(done);
00140             if (!done) {
00141                 std::stringstream str;
00142                 str << "Cannot rename file " << file.filePath() << " to " << _cValue;
00143                 throw Base::Exception(str.str());
00144             }
00145         }
00146         // otherwise copy from origin location 
00147         else {
00148             // if file already exists in transient dir make a new unique name
00149             Base::FileInfo fi(_cValue);
00150             if (fi.exists()) {
00151                 Base::FileInfo fi2(Base::FileInfo::getTempFileName());
00152                 std::stringstream str;
00153                 str << fi.dirPath() << "/" << fi2.fileNamePure();
00154                 std::string ext = fi.extension(false);
00155                 if (!ext.empty())
00156                     str << "." << ext;
00157                 Base::FileInfo fi3(str.str());
00158                 _cValue = fi3.filePath();
00159                 _BaseFileName = fi3.fileName();
00160             }
00161 
00162             bool done = file.copyTo(_cValue.c_str());
00163             //assert(done); 
00164             if (!done) {
00165                 std::stringstream str;
00166                 str << "Cannot copy file from " << file.filePath() << " to " << _cValue;
00167                 throw Base::Exception(str.str());
00168             }
00169         }
00170 
00171         hasSetValue();
00172     }
00173 }
00174 
00175 const char* PropertyFileIncluded::getValue(void) const
00176 {
00177      return _cValue.c_str();
00178 }
00179 
00180 PyObject *PropertyFileIncluded::getPyObject(void)
00181 {
00182     PyObject *p = PyUnicode_DecodeUTF8(_cValue.c_str(),_cValue.size(),0);
00183     if (!p) throw Base::Exception("UTF8 conversion failure at PropertyString::getPyObject()");
00184     return p;
00185 }
00186 
00187 void PropertyFileIncluded::setPyObject(PyObject *value)
00188 {
00189     std::string string;
00190     if (PyUnicode_Check(value)) {
00191         PyObject* unicode = PyUnicode_AsUTF8String(value);
00192         string = PyString_AsString(unicode);
00193         Py_DECREF(unicode);
00194     }
00195     else if (PyString_Check(value)) {
00196         string = PyString_AsString(value);
00197     }
00198     else if (PyFile_Check(value)) {
00199         PyObject* FileName = PyFile_Name(value);
00200         string = PyString_AsString(FileName);
00201     }
00202     else if (PyTuple_Check(value)) {
00203         if (PyTuple_Size(value) != 2)
00204             throw Py::TypeError("Tuple need size of (filePath,newFileName)"); 
00205         PyObject* file = PyTuple_GetItem(value,0);
00206         PyObject* name = PyTuple_GetItem(value,1);
00207 
00208         // decoding file
00209         std::string fileStr;
00210         if (PyUnicode_Check(file)) {
00211             PyObject* unicode = PyUnicode_AsUTF8String(file);
00212             fileStr = PyString_AsString(unicode);
00213             Py_DECREF(unicode);
00214         }
00215         else if (PyString_Check(file)) {
00216             fileStr = PyString_AsString(file);
00217         }
00218         else if (PyFile_Check(file)) {
00219             PyObject* FileName = PyFile_Name(file);
00220             fileStr = PyString_AsString(FileName);
00221         }
00222         else {
00223             std::string error = std::string("first in tuple must be a file or string");
00224             error += value->ob_type->tp_name;
00225             throw Py::TypeError(error);
00226         }
00227 
00228         // decoding name
00229         std::string nameStr;
00230         if (PyString_Check(name)) {
00231             nameStr = PyString_AsString(name);
00232         }
00233         else if (PyFile_Check(name)) {
00234             PyObject* FileName = PyFile_Name(name);
00235             nameStr = PyString_AsString(FileName);
00236         }
00237         else {
00238             std::string error = std::string("second in tuple must be a string");
00239             error += value->ob_type->tp_name;
00240             throw Py::TypeError(error);
00241         }
00242 
00243         setValue(fileStr.c_str(),nameStr.c_str());
00244         return;
00245 
00246     }
00247     else {
00248         std::string error = std::string("type must be str or file");
00249         error += value->ob_type->tp_name;
00250         throw Py::TypeError(error);
00251     }
00252 
00253     // assign the string
00254     setValue(string.c_str());
00255 }
00256 
00257 void PropertyFileIncluded::Save (Base::Writer &writer) const
00258 {
00259     if (writer.isForceXML()) {
00260         writer.Stream() << writer.ind() << "<FileIncluded file=\"\">" << endl;
00261 
00262         // write the file in the XML stream
00263         if (!_cValue.empty())
00264             writer.insertBinFile(_cValue.c_str());
00265 
00266         writer.Stream() << writer.ind() <<"</FileIncluded>" << endl ;
00267     }
00268     else {
00269         // instead initiate an extra file 
00270         if (!_cValue.empty()) {
00271             Base::FileInfo file(_cValue.c_str());
00272             writer.Stream() << writer.ind() << "<FileIncluded file=\"" << 
00273             writer.addFile(file.fileName().c_str(), this) << "\"/>" << std::endl;
00274         }
00275         else
00276             writer.Stream() << writer.ind() << "<FileIncluded file=\"\"/>" << std::endl;
00277     }
00278 }
00279 
00280 void PropertyFileIncluded::Restore(Base::XMLReader &reader)
00281 {
00282     reader.readElement("FileIncluded");
00283     string file (reader.getAttribute("file") );
00284 
00285     if (!file.empty()) {
00286         // initate a file read
00287         reader.addFile(file.c_str(),this);
00288 
00289         // is in the document transient path
00290         aboutToSetValue();
00291         _cValue = getDocTransientPath() + "/" + file;
00292         _BaseFileName = file;
00293         hasSetValue();
00294     }
00295 }
00296 
00297 void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const
00298 {
00299     std::ifstream from(_cValue.c_str());
00300     if (!from)
00301         throw Base::Exception("PropertyFileIncluded::SaveDocFile() "
00302         "File in document transient dir deleted");
00303 
00304     // copy plain data
00305     unsigned char c;
00306     std::ostream& to = writer.Stream();
00307     while (from.get((char&)c)) {
00308         to.put((const char)c);
00309     }
00310 }
00311 
00312 void PropertyFileIncluded::RestoreDocFile(Base::Reader &reader)
00313 {
00314     std::ofstream to(_cValue.c_str());
00315     if (!to) 
00316         throw Base::Exception("PropertyFileIncluded::RestoreDocFile() "
00317         "File in document transient dir deleted");
00318 
00319     // copy plain data
00320     aboutToSetValue();
00321     unsigned char c;
00322     while (reader.get((char&)c)) {
00323         to.put((const char)c);
00324     }
00325     to.close();
00326     hasSetValue();
00327 }
00328 
00329 Property *PropertyFileIncluded::Copy(void) const
00330 {
00331     PropertyFileIncluded *p= new PropertyFileIncluded();
00332 
00333     // remember the base name
00334     p->_BaseFileName = _BaseFileName;
00335 
00336     if (!_cValue.empty()) {
00337         Base::FileInfo file(_cValue);
00338 
00339         // create a new name in the document transient directory
00340         Base::FileInfo NewName(Base::FileInfo::getTempFileName(file.fileName().c_str(),file.dirPath().c_str()));
00341         NewName.deleteFile();
00342         // move the file 
00343         bool done = file.renameFile(NewName.filePath().c_str());
00344         assert(done);
00345         // remember the new name for the Undo
00346         Base::Console().Log("Copy this=%p Befor=%s After=%s\n",p,p->_cValue.c_str(),NewName.filePath().c_str());
00347         p->_cValue = NewName.filePath().c_str();
00348     }
00349 
00350     return p;
00351 }
00352 
00353 void PropertyFileIncluded::Paste(const Property &from)
00354 {
00355     aboutToSetValue();
00356     Base::FileInfo file(_cValue);
00357     // delete old file (if still there)
00358     file.deleteFile();
00359     const PropertyFileIncluded &fileInc = dynamic_cast<const PropertyFileIncluded&>(from);
00360 
00361     if (!fileInc._cValue.empty()) {
00362         // move the saved files back in place
00363         Base::FileInfo NewFile(fileInc._cValue);
00364         _cValue = NewFile.dirPath() + "/" + fileInc._BaseFileName;
00365         bool done = NewFile.renameFile(_cValue.c_str());
00366         assert(done);
00367     }
00368     else
00369         _cValue.clear();
00370     hasSetValue();
00371 }
00372 
00373 
00374 //**************************************************************************
00375 // PropertyFile
00376 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00377 
00378 TYPESYSTEM_SOURCE(App::PropertyFile , App::PropertyString);
00379 
00380 PropertyFile::PropertyFile()
00381 {
00382 
00383 }
00384 
00385 PropertyFile::~PropertyFile()
00386 {
00387 
00388 }
00389 

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