From 2bbe4652291347dbd39116ff768a47b447926865 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 4 May 2013 03:16:34 +0200 Subject: [PATCH] + Make transient directory of the form ExeName_Doc_{UUID}_{HASH}_{PID} + Set some properties in Document read-only + Implement Document::saveAs + Fix PropertyUUID::setValue() + Add a field for UUID in document information panel --- src/App/Application.cpp | 17 +++ src/App/Document.cpp | 58 ++++++-- src/App/Document.h | 2 + src/App/DocumentPy.xml | 9 +- src/App/DocumentPyImp.cpp | 19 +++ src/App/PropertyStandard.cpp | 11 +- src/Gui/DlgProjectInformation.ui | 205 ++++++++++++++------------- src/Gui/DlgProjectInformationImp.cpp | 1 + src/Gui/Document.cpp | 6 +- 9 files changed, 216 insertions(+), 112 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index e5b27962d..0ddbaa121 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -421,6 +421,23 @@ Document* Application::openDocument(const char * FileName) // read the document newDoc->restore(); + // make sure that the uuid is unique + //FIXME: See Document::saveAs() +#if 0 + std::string uuid = newDoc->Uid.getValueStr(); + for (std::map::iterator it = DocMap.begin(); it != DocMap.end(); ++it) { + if (newDoc != it->second) { + if (uuid == it->second->Uid.getValueStr()) { + Base::Uuid id; + newDoc->Uid.setValue(id); + Base::Console().Warning("Document with the UUID '%s' already exists, change to '%s'\n", + uuid.c_str(), id.getValue().c_str()); + break; + } + } + } +#endif + return newDoc; } diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 5ccde012e..2d09b27fe 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -65,6 +65,9 @@ recompute path. Also enables more complicated dependencies beyond trees. #include #include +#include +#include + #include "Document.h" #include "DocumentPy.h" @@ -525,7 +528,7 @@ Document::Document(void) #endif ADD_PROPERTY_TYPE(Label,("Unnamed"),0,Prop_None,"The name of the document"); - ADD_PROPERTY_TYPE(FileName,(""),0,Prop_None,"The path to the file where the document is saved to"); + ADD_PROPERTY_TYPE(FileName,(""),0,Prop_ReadOnly,"The path to the file where the document is saved to"); ADD_PROPERTY_TYPE(CreatedBy,(""),0,Prop_None,"The creator of the document"); ADD_PROPERTY_TYPE(CreationDate,(Base::TimeInfo::currentDateTimeString()),0,Prop_ReadOnly,"Date of creation"); ADD_PROPERTY_TYPE(LastModifiedBy,(""),0,Prop_None,0); @@ -537,18 +540,17 @@ Document::Document(void) // create the uuid for the document Base::Uuid id; ADD_PROPERTY_TYPE(Id,(""),0,Prop_None,"ID of the document"); - ADD_PROPERTY_TYPE(Uid,(id),0,Prop_None,"UUID of the document"); + ADD_PROPERTY_TYPE(Uid,(id),0,Prop_ReadOnly,"UUID of the document"); // license stuff ADD_PROPERTY_TYPE(License,("CC-BY 3.0"),0,Prop_None,"License string of the Item"); ADD_PROPERTY_TYPE(LicenseURL,("http://creativecommons.org/licenses/by/3.0/"),0,Prop_None,"URL to the license text/contract"); // create transient directory - std::string basePath = Base::FileInfo::getTempPath() + GetApplication().getExecutableName(); - Base::FileInfo TransDir(basePath + "_Doc_" + id.getValue()); + Base::FileInfo TransDir(getTransientDirectoryName(id.getValue(),FileName.getStrValue())); if (!TransDir.exists()) TransDir.createDirectory(); - ADD_PROPERTY_TYPE(TransientDir,(TransDir.filePath().c_str()),0,Prop_Transient, + ADD_PROPERTY_TYPE(TransientDir,(TransDir.filePath().c_str()),0,PropertyType(Prop_Transient|Prop_ReadOnly), "Transient directory, where the files live while the document is open"); } @@ -586,6 +588,19 @@ Document::~Document() delete d; } +std::string Document::getTransientDirectoryName(const std::string& uuid, const std::string& filename) const +{ + // Create a directory name of the form: {ExeName}_Doc_{UUID}_{HASH}_{PID} + std::stringstream s; + QCryptographicHash hash(QCryptographicHash::Sha1); + hash.addData(filename.c_str(), filename.size()); + s << Base::FileInfo::getTempPath() << GetApplication().getExecutableName() + << "_Doc_" << uuid + << "_" << hash.result().toHex().left(6).constData() + << "_" << QCoreApplication::applicationPid(); + return s.str(); +} + //-------------------------------------------------------------------------- // Exported functions //-------------------------------------------------------------------------- @@ -637,9 +652,8 @@ void Document::Restore(Base::XMLReader &reader) Label.setValue(DocLabel.c_str()); // create new transient directory - std::string basePath = Base::FileInfo::getTempPath() + GetApplication().getExecutableName(); - Base::FileInfo TransDirNew(basePath + "_Doc_" + Uid.getValueStr()); - if(!TransDirNew.exists()) + Base::FileInfo TransDirNew(getTransientDirectoryName(Uid.getValueStr(),FileName.getStrValue())); + if (!TransDirNew.exists()) TransDirNew.createDirectory(); TransientDir.setValue(TransDirNew.filePath()); @@ -857,6 +871,34 @@ void Document::exportGraphviz(std::ostream& out) boost::write_graphviz(out, DepList, boost::make_label_writer(&(names[0]))); } +bool Document::saveAs(const char* file) +{ + Base::FileInfo fi(file); + if (this->FileName.getStrValue() != file) { + this->FileName.setValue(file); + this->Label.setValue(fi.fileNamePure()); + + //FIXME: At the moment PropertyFileIncluded doesn't work when renaming this directory. + // PropertyFileIncluded shouldn't store the transient path + //FIXME: Application::openDocument() may assign a new UUID. In order to change the directoy + // name handle this in onChanged() +#if 0 + Base::Uuid id; + Base::FileInfo TransDirNew(getTransientDirectoryName(id.getValue(),this->FileName.getStrValue())); + Base::FileInfo TransDirOld(this->TransientDir.getStrValue()); + // this directory should not exist + if (!TransDirNew.exists()) { + if (TransDirOld.renameFile(TransDirNew.filePath().c_str())) { + this->Uid.setValue(id); + this->TransientDir.setValue(TransDirNew.filePath()); + } + } +#endif + } + + return save(); +} + // Save the document under the name it has been opened bool Document::save (void) { diff --git a/src/App/Document.h b/src/App/Document.h index 5e2eedd89..06a7fbdcb 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -133,6 +133,7 @@ public: //void saveAs (const char* Name); /// Save the document to the file in Property Path bool save (void); + bool saveAs(const char* file); /// Restore the document from the file in Property Path void restore (void); void exportObjects(const std::vector&, std::ostream&); @@ -303,6 +304,7 @@ protected: void _clearRedos(); /// refresh the internal dependency graph void _rebuildDependencyList(void); + std::string getTransientDirectoryName(const std::string& uuid, const std::string& filename) const; private: diff --git a/src/App/DocumentPy.xml b/src/App/DocumentPy.xml index 4a996e111..7aa4b2304 100644 --- a/src/App/DocumentPy.xml +++ b/src/App/DocumentPy.xml @@ -15,12 +15,17 @@ - Save the document to disc + Save the document to disk + + + + + Save the document under a new name to disk - Restore the document from disc + Restore the document from disk diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp index cc9c40e62..c5225ca11 100644 --- a/src/App/DocumentPyImp.cpp +++ b/src/App/DocumentPyImp.cpp @@ -69,6 +69,25 @@ PyObject* DocumentPy::save(PyObject * args) Py_Return; } +PyObject* DocumentPy::saveAs(PyObject * args) +{ + char* fn; + if (!PyArg_ParseTuple(args, "s", &fn)) // convert args: Python->C + return NULL; // NULL triggers exception + if (!getDocumentPtr()->saveAs(fn)) { + PyErr_Format(PyExc_ValueError, "Object attribute 'FileName' is not set"); + return NULL; + } + + Base::FileInfo fi(fn); + if (!fi.isReadable()) { + PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", fn); + return NULL; + } + + Py_Return; +} + PyObject* DocumentPy::restore(PyObject * args) { if (!PyArg_ParseTuple(args, "")) // convert args: Python->C diff --git a/src/App/PropertyStandard.cpp b/src/App/PropertyStandard.cpp index 9f6c37b6c..73b0df99a 100644 --- a/src/App/PropertyStandard.cpp +++ b/src/App/PropertyStandard.cpp @@ -1348,8 +1348,15 @@ void PropertyUUID::setPyObject(PyObject *value) throw Py::TypeError(error); } - // assign the string - setValue(string); + try { + // assign the string + Base::Uuid uid; + uid.setValue(string); + setValue(uid); + } + catch (const std::exception& e) { + throw Py::RuntimeError(e.what()); + } } void PropertyUUID::Save (Base::Writer &writer) const diff --git a/src/Gui/DlgProjectInformation.ui b/src/Gui/DlgProjectInformation.ui index 60b0378d1..f080e6233 100644 --- a/src/Gui/DlgProjectInformation.ui +++ b/src/Gui/DlgProjectInformation.ui @@ -40,9 +40,6 @@ 6 - - - @@ -56,32 +53,16 @@ - - - - Qt::Vertical - - - QSizePolicy::Expanding - - + + + - 91 - 240 + 0 + 25 - - - - - - Commen&t: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - textEditComment + + true @@ -108,40 +89,30 @@ - - - - - 0 - 25 - - - - - - - - - 0 - 25 - - - - - - + + - &Last modified by: + UUID: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - lineEditLastMod + + + + + + + 0 + 25 + + + + true - + Created &by: @@ -154,20 +125,66 @@ - - + + + + + 0 + 25 + + + + + + - Com&pany: + Creation &date: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - lineEditCompany + lineEditDate + + + + + + + + 0 + 25 + + + + true + + + &Last modified by: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + lineEditLastMod + + + + + + + + 0 + 25 + + + + + Last &modification date: @@ -181,29 +198,6 @@ - - - - 0 - 25 - - - - - - - - - 0 - 25 - - - - true - - - - @@ -216,32 +210,61 @@ - - + + - Creation &date: + Com&pany: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - lineEditDate + lineEditCompany - - + + 0 25 - - true + + + + + + Commen&t: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + textEditComment + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 91 + 240 + + + + @@ -304,14 +327,6 @@ - lineEditName - lineEditCreator - lineEditDate - lineEditLastMod - lineEditLastModDate - lineEditCompany - buttonOk - buttonCancel diff --git a/src/Gui/DlgProjectInformationImp.cpp b/src/Gui/DlgProjectInformationImp.cpp index 5e4b115f0..c5f878693 100644 --- a/src/Gui/DlgProjectInformationImp.cpp +++ b/src/Gui/DlgProjectInformationImp.cpp @@ -46,6 +46,7 @@ DlgProjectInformationImp::DlgProjectInformationImp( App::Document* doc, QWidget* this->setupUi(this); lineEditName->setText(QString::fromUtf8(doc->Label.getValue())); lineEditPath->setText(QString::fromUtf8(doc->FileName.getValue())); + lineEditUuid->setText(QString::fromUtf8(doc->Uid.getValueStr().c_str())); lineEditCreator->setText(QString::fromUtf8(doc->CreatedBy.getValue())); lineEditDate->setText(QString::fromUtf8(doc->CreationDate.getValue())); lineEditLastMod->setText(QString::fromUtf8(doc->LastModifiedBy.getValue())); diff --git a/src/Gui/Document.cpp b/src/Gui/Document.cpp index eca63b7d4..6b7fcb884 100644 --- a/src/Gui/Document.cpp +++ b/src/Gui/Document.cpp @@ -602,12 +602,8 @@ bool Document::saveAs(void) // save as new file name Gui::WaitCursor wc; - Command::doCommand(Command::Doc,"App.getDocument(\"%s\").FileName = \"%s\"" + Command::doCommand(Command::Doc,"App.getDocument(\"%s\").saveAs('%s')" , DocName, (const char*)fn.toUtf8()); - Command::doCommand(Command::Doc,"App.getDocument(\"%s\").Label = \"%s\"" - , DocName, (const char*)bn.toUtf8()); - Command::doCommand(Command::Doc,"App.getDocument(\"%s\").save()" - , DocName); setModified(false); getMainWindow()->appendRecentFile(fi.filePath());