Add initial version of the Cloud workbench
This commit is contained in:
committed by
wmayer
parent
90b5f63bc2
commit
a2e21f79f2
@@ -1268,6 +1268,52 @@ bool Document::isTransactionEmpty() const
|
||||
return true;
|
||||
}
|
||||
|
||||
void Document::emptyDocument()
|
||||
{
|
||||
this->d->activeObject = 0;
|
||||
|
||||
if(this->d->objectArray.size()) {
|
||||
GetApplication().signalDeleteDocument(*this);
|
||||
this->d->objectArray.clear();
|
||||
for(auto &v : this->d->objectMap) {
|
||||
v.second->setStatus(ObjectStatus::Destroy, true);
|
||||
delete(v.second);
|
||||
}
|
||||
this->d->objectMap.clear();
|
||||
this->d->objectIdMap.clear();
|
||||
GetApplication().signalNewDocument(*this,false);
|
||||
}
|
||||
|
||||
Base::FlagToggler<> flag(_IsRestoring,false);
|
||||
|
||||
setStatus(Document::PartialDoc,false);
|
||||
|
||||
this->d->clearRecomputeLog();
|
||||
this->d->objectArray.clear();
|
||||
this->d->objectMap.clear();
|
||||
this->d->objectIdMap.clear();
|
||||
this->d->lastObjectId = 0;
|
||||
}
|
||||
|
||||
void Document::resetTouched()
|
||||
{
|
||||
/*
|
||||
for (std::map<std::string,DocumentObject*>::iterator It= this->d->objectMap.begin();It!=this->d->objectMap.end();++It) {
|
||||
It->second->connectRelabelSignals();
|
||||
try {
|
||||
It->second->onDocumentRestored();
|
||||
It->second->ExpressionEngine.onDocumentRestored();
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Base::Console().Error("Error in %s: %s\n", It->second->Label.getValue(), e.what());
|
||||
}
|
||||
It->second->purgeTouched();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Document::clearUndos()
|
||||
{
|
||||
if(isPerformingTransaction() || d->committing) {
|
||||
|
||||
@@ -179,6 +179,10 @@ public:
|
||||
boost::signals2::signal<void (const App::Document&,const App::Property&)> signalChangePropertyEditor;
|
||||
//@}
|
||||
|
||||
|
||||
void resetTouched();
|
||||
void emptyDocument();
|
||||
|
||||
/** @name File handling of the document */
|
||||
//@{
|
||||
/// Save the Document under a new Name
|
||||
|
||||
@@ -335,6 +335,8 @@ void Base::XMLReader::readFiles(zipios::ZipInputStream &zipstream) const
|
||||
try {
|
||||
Base::Reader reader(zipstream, jt->FileName, FileVersion);
|
||||
jt->Object->RestoreDocFile(reader);
|
||||
if ( reader.getLocalReader() != nullptr )
|
||||
reader.getLocalReader()->readFiles(zipstream);
|
||||
}
|
||||
catch(...) {
|
||||
// For any exception we just continue with the next file.
|
||||
@@ -576,3 +578,13 @@ std::istream& Base::Reader::getStream()
|
||||
return this->_str;
|
||||
}
|
||||
|
||||
void Base::Reader::initLocalReader(Base::XMLReader *ptr)
|
||||
{
|
||||
|
||||
this->localreader=ptr;
|
||||
}
|
||||
|
||||
Base::XMLReader *Base::Reader::getLocalReader()
|
||||
{
|
||||
return(this->localreader);
|
||||
}
|
||||
|
||||
@@ -207,6 +207,11 @@ public:
|
||||
bool testStatus(ReaderStatus pos) const;
|
||||
/// set the status bits
|
||||
void setStatus(ReaderStatus pos, bool on);
|
||||
struct FileEntry {
|
||||
std::string FileName;
|
||||
Base::Persistence *Object;
|
||||
};
|
||||
std::vector<FileEntry> FileList;
|
||||
|
||||
protected:
|
||||
/// read the next element
|
||||
@@ -281,11 +286,6 @@ protected:
|
||||
bool _valid;
|
||||
bool _verbose;
|
||||
|
||||
struct FileEntry {
|
||||
std::string FileName;
|
||||
Base::Persistence *Object;
|
||||
};
|
||||
std::vector<FileEntry> FileList;
|
||||
std::vector<std::string> FileNames;
|
||||
|
||||
std::bitset<32> StatusBits;
|
||||
@@ -298,11 +298,14 @@ public:
|
||||
std::istream& getStream();
|
||||
std::string getFileName() const;
|
||||
int getFileVersion() const;
|
||||
void initLocalReader(Base::XMLReader *ptr);
|
||||
Base::XMLReader *getLocalReader();
|
||||
|
||||
private:
|
||||
std::istream& _str;
|
||||
std::string _name;
|
||||
int fileVersion;
|
||||
Base::XMLReader *localreader=nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -1189,20 +1189,21 @@ void Document::Restore(Base::XMLReader &reader)
|
||||
void Document::RestoreDocFile(Base::Reader &reader)
|
||||
{
|
||||
// We must create an XML parser to read from the input stream
|
||||
Base::XMLReader xmlReader("GuiDocument.xml", reader);
|
||||
xmlReader.FileVersion = reader.getFileVersion();
|
||||
Base::XMLReader *localreader;
|
||||
localreader = new Base::XMLReader("GuiDocument.xml", reader);
|
||||
localreader->FileVersion = reader.getFileVersion();
|
||||
|
||||
xmlReader.readElement("Document");
|
||||
long scheme = xmlReader.getAttributeAsInteger("SchemaVersion");
|
||||
xmlReader.DocumentSchema = scheme;
|
||||
localreader->readElement("Document");
|
||||
long scheme = localreader->getAttributeAsInteger("SchemaVersion");
|
||||
localreader->DocumentSchema = scheme;
|
||||
|
||||
bool hasExpansion = xmlReader.hasAttribute("HasExpansion");
|
||||
bool hasExpansion = localreader->hasAttribute("HasExpansion");
|
||||
if(hasExpansion) {
|
||||
auto tree = TreeWidget::instance();
|
||||
if(tree) {
|
||||
auto docItem = tree->getDocumentItem(this);
|
||||
if(docItem)
|
||||
docItem->Restore(xmlReader);
|
||||
docItem->Restore(*localreader);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1212,32 +1213,32 @@ void Document::RestoreDocFile(Base::Reader &reader)
|
||||
// SchemeVersion "1"
|
||||
if (scheme == 1) {
|
||||
// read the viewproviders itself
|
||||
xmlReader.readElement("ViewProviderData");
|
||||
int Cnt = xmlReader.getAttributeAsInteger("Count");
|
||||
localreader->readElement("ViewProviderData");
|
||||
int Cnt = localreader->getAttributeAsInteger("Count");
|
||||
for (int i=0; i<Cnt; i++) {
|
||||
xmlReader.readElement("ViewProvider");
|
||||
std::string name = xmlReader.getAttribute("name");
|
||||
localreader->readElement("ViewProvider");
|
||||
std::string name = localreader->getAttribute("name");
|
||||
bool expanded = false;
|
||||
if (!hasExpansion && xmlReader.hasAttribute("expanded")) {
|
||||
const char* attr = xmlReader.getAttribute("expanded");
|
||||
if (!hasExpansion && localreader->hasAttribute("expanded")) {
|
||||
const char* attr = localreader->getAttribute("expanded");
|
||||
if (strcmp(attr,"1") == 0) {
|
||||
expanded = true;
|
||||
}
|
||||
}
|
||||
ViewProvider* pObj = getViewProviderByName(name.c_str());
|
||||
if (pObj) // check if this feature has been registered
|
||||
pObj->Restore(xmlReader);
|
||||
pObj->Restore(*localreader);
|
||||
if (pObj && expanded) {
|
||||
Gui::ViewProviderDocumentObject* vp = static_cast<Gui::ViewProviderDocumentObject*>(pObj);
|
||||
this->signalExpandObject(*vp, Gui::ExpandItem,0,0);
|
||||
}
|
||||
xmlReader.readEndElement("ViewProvider");
|
||||
localreader->readEndElement("ViewProvider");
|
||||
}
|
||||
xmlReader.readEndElement("ViewProviderData");
|
||||
localreader->readEndElement("ViewProviderData");
|
||||
|
||||
// read camera settings
|
||||
xmlReader.readElement("Camera");
|
||||
const char* ppReturn = xmlReader.getAttribute("settings");
|
||||
localreader->readElement("Camera");
|
||||
const char* ppReturn = localreader->getAttribute("settings");
|
||||
cameraSettings.clear();
|
||||
if(ppReturn && ppReturn[0]) {
|
||||
saveCameraSettings(ppReturn);
|
||||
@@ -1255,13 +1256,10 @@ void Document::RestoreDocFile(Base::Reader &reader)
|
||||
}
|
||||
}
|
||||
|
||||
xmlReader.readEndElement("Document");
|
||||
|
||||
// In the file GuiDocument.xml new data files might be added
|
||||
if (!xmlReader.getFilenames().empty())
|
||||
xmlReader.readFiles(static_cast<zipios::ZipInputStream&>(reader.getStream()));
|
||||
localreader->readEndElement("Document");
|
||||
|
||||
// reset modified flag
|
||||
reader.initLocalReader(localreader);
|
||||
setModified(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -102,6 +102,23 @@ if(BUILD_FEM)
|
||||
add_subdirectory(Fem)
|
||||
endif(BUILD_FEM)
|
||||
|
||||
if(BUILD_CLOUD)
|
||||
#------------------------------ OpenSSL and CURL -------------------------
|
||||
IF (APPLE)
|
||||
set(OPENSSL_ROOT_DIR ${HOMEBREW_PREFIX}/Cellar/openssl/*)
|
||||
ENDIF(APPLE)
|
||||
find_package(OPENSSL REQUIRED)
|
||||
IF(OPENSSL_FOUND)
|
||||
message(STATUS "openssl-${OPENSSL_VERSION} has been found\n")
|
||||
ENDIF(OPENSSL_FOUND)
|
||||
find_package(CURL REQUIRED)
|
||||
IF(CURL_FOUND)
|
||||
message(STATUS "CURL has been found\n")
|
||||
ENDIF(CURL_FOUND)
|
||||
# ------------------------------------------------------------------------
|
||||
add_subdirectory(Cloud)
|
||||
endif(BUILD_CLOUD)
|
||||
|
||||
if(BUILD_SANDBOX)
|
||||
add_subdirectory(Sandbox)
|
||||
endif(BUILD_SANDBOX)
|
||||
|
||||
696
src/Mod/Cloud/App/AppCloud.cpp
Normal file
696
src/Mod/Cloud/App/AppCloud.cpp
Normal file
@@ -0,0 +1,696 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2019 Jean-Marie Verdun jmverdun3@gmail.com *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <Python.h>
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/DocumentPy.h>
|
||||
#include <App/DocumentObserverPython.h>
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/PyObjectBase.h>
|
||||
|
||||
#include <CXX/Extensions.hxx>
|
||||
#include <CXX/Objects.hxx>
|
||||
|
||||
#include "AppCloud.h"
|
||||
|
||||
using namespace App;
|
||||
|
||||
/* Python entry */
|
||||
PyMOD_INIT_FUNC(Cloud)
|
||||
{
|
||||
// ADD YOUR CODE HERE
|
||||
//
|
||||
//
|
||||
PyObject* mod = Cloud::initModule();
|
||||
Base::Console().Log("Loading Cloud module... done\n");
|
||||
PyMOD_Return(mod);
|
||||
}
|
||||
|
||||
Py::Object Cloud::Module::sCloudUrl(const Py::Tuple& args)
|
||||
{
|
||||
char *Url;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "et","utf-8",&Url)) // convert args: Python->C
|
||||
return Py::None();
|
||||
if (this->Url.getStrValue() != Url) {
|
||||
this->Url.setValue(Url);
|
||||
}
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object Cloud::Module::sCloudAccessKey(const Py::Tuple& args)
|
||||
{
|
||||
char *AccessKey;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "et","utf-8", &AccessKey)) // convert args: Python->C
|
||||
return Py::None();
|
||||
if (this->AccessKey.getStrValue() != AccessKey) {
|
||||
this->AccessKey.setValue(AccessKey);
|
||||
}
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object Cloud::Module::sCloudSecretKey(const Py::Tuple& args)
|
||||
{
|
||||
char *SecretKey;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "et","utf-8", &SecretKey)) // convert args: Python->C
|
||||
return Py::None();
|
||||
if (this->SecretKey.getStrValue() != SecretKey) {
|
||||
this->SecretKey.setValue(SecretKey);
|
||||
}
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object Cloud::Module::sCloudTcpPort(const Py::Tuple& args)
|
||||
{
|
||||
char *TcpPort;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "et","utf-8", &TcpPort)) // convert args: Python->C
|
||||
return Py::None();
|
||||
if (this->TcpPort.getStrValue() != TcpPort) {
|
||||
this->TcpPort.setValue(TcpPort);
|
||||
}
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object Cloud::Module::sCloudSave(const Py::Tuple& args)
|
||||
{
|
||||
char *pDoc;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "et","utf-8", &pDoc)) // convert args: Python->C
|
||||
return Py::None();
|
||||
cloudSave(pDoc);
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
|
||||
Py::Object Cloud::Module::sCloudRestore(const Py::Tuple& args)
|
||||
{
|
||||
char *pDoc;
|
||||
if (!PyArg_ParseTuple(args.ptr(), "et", "utf-8", &pDoc)) // convert args: Python->C
|
||||
return Py::None();
|
||||
cloudRestore(pDoc);
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
|
||||
Cloud::CloudWriter::CloudWriter(const char* Url, const char* AccessKey, const char* SecretKey, const char* TcpPort, const char* Bucket)
|
||||
{
|
||||
this->Url=Url;
|
||||
this->AccessKey=AccessKey;
|
||||
this->SecretKey=SecretKey;
|
||||
this->TcpPort=TcpPort;
|
||||
this->Bucket=Bucket;
|
||||
this->FileName="";
|
||||
// Amazon S3 and Swift require the timezone to be define to
|
||||
// GMT. As to simplify the conversion this is performed through the TZ
|
||||
// environment variable and a call to localtime as to convert output of gettimeofday
|
||||
setenv("TZ","GMT",1);
|
||||
}
|
||||
|
||||
Cloud::CloudWriter::~CloudWriter()
|
||||
{
|
||||
}
|
||||
|
||||
size_t CurlWrite_CallbackFunc_StdString(void *contents, size_t size, size_t nmemb, std::string *s)
|
||||
{
|
||||
size_t newLength = size*nmemb;
|
||||
try
|
||||
{
|
||||
s->append((char*)contents, newLength);
|
||||
}
|
||||
catch(std::bad_alloc &e)
|
||||
{
|
||||
//handle memory problem
|
||||
return 0;
|
||||
}
|
||||
return newLength;
|
||||
}
|
||||
|
||||
void Cloud::CloudReader::checkElement(DOMElement* element) {
|
||||
char* name = XMLString::transcode(element->getTagName());
|
||||
if ( strcmp(name, "Key") == 0 )
|
||||
print=1;
|
||||
XMLString::release(&name);
|
||||
|
||||
}
|
||||
|
||||
void Cloud::CloudReader::checkText(DOMText* text) {
|
||||
|
||||
XMLCh* buffer = new XMLCh[XMLString::stringLen(text->getData()) + 1];
|
||||
XMLString::copyString(buffer, text->getData());
|
||||
XMLString::trim(buffer);
|
||||
struct Cloud::CloudReader::FileEntry *new_entry;
|
||||
char* content=XMLString::transcode(buffer);
|
||||
delete[] buffer;
|
||||
if ( print )
|
||||
{
|
||||
new_entry=new Cloud::CloudReader::FileEntry;
|
||||
strcpy(new_entry->FileName,content);
|
||||
Cloud::CloudReader::FileList.push_back(new_entry);
|
||||
}
|
||||
print=0;
|
||||
XMLString::release(&content);
|
||||
}
|
||||
|
||||
void Cloud::CloudReader::addFile(struct Cloud::CloudReader::FileEntry *new_entry)
|
||||
{
|
||||
Cloud::CloudReader::FileList.push_back(new_entry);
|
||||
}
|
||||
|
||||
void Cloud::CloudReader::checkXML(DOMNode* node) {
|
||||
if (node) {
|
||||
switch (node->getNodeType()) {
|
||||
case DOMNode::ELEMENT_NODE:
|
||||
checkElement(static_cast<DOMElement*>(node));
|
||||
break;
|
||||
case DOMNode::TEXT_NODE:
|
||||
checkText(static_cast<DOMText*>(node));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DOMNode* child = node->getFirstChild();
|
||||
while (child) {
|
||||
DOMNode* next = child->getNextSibling();
|
||||
checkXML(child);
|
||||
child = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct data_buffer
|
||||
{
|
||||
const char *ptr;
|
||||
size_t remaining_size;
|
||||
};
|
||||
|
||||
Cloud::CloudReader::~CloudReader()
|
||||
{
|
||||
}
|
||||
|
||||
Cloud::CloudReader::CloudReader(const char* Url, const char* AccessKey, const char* SecretKey, const char* TcpPort, const char* Bucket)
|
||||
{
|
||||
|
||||
struct timeval tv;
|
||||
struct tm *tm;
|
||||
char date_formatted[256];
|
||||
char StringToSign[1024];
|
||||
unsigned char *digest;
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
||||
std::string s;
|
||||
|
||||
|
||||
this->Url=Url;
|
||||
this->AccessKey=AccessKey;
|
||||
this->SecretKey=SecretKey;
|
||||
this->TcpPort=TcpPort;
|
||||
this->Bucket=Bucket;
|
||||
|
||||
// Amazon S3 and Swift require the timezone to be define to
|
||||
// GMT. As to simplify the conversion this is performed through the TZ
|
||||
// environment variable and a call to localtime as to convert output of gettimeofday
|
||||
setenv("TZ","GMT",1);
|
||||
|
||||
// We must get the directory content
|
||||
|
||||
|
||||
gettimeofday(&tv,NULL);
|
||||
tm = localtime(&tv.tv_sec);
|
||||
strftime(date_formatted,256,"%a, %d %b %Y %T %z", tm);
|
||||
|
||||
sprintf(StringToSign,"GET\n\napplication/xml\n%s\n/%s/", date_formatted, this->Bucket);
|
||||
|
||||
// We have to use HMAC encoding and SHA1
|
||||
digest=HMAC(EVP_sha1(),this->SecretKey,strlen(this->SecretKey),
|
||||
(const unsigned char *)&StringToSign,strlen(StringToSign),NULL,NULL);
|
||||
|
||||
// Let's build the Header and call to curl
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curl = curl_easy_init();
|
||||
if ( curl )
|
||||
{
|
||||
struct curl_slist *chunk = NULL;
|
||||
char header_data[1024];
|
||||
// Let's build our own header
|
||||
sprintf(header_data,"Host: %s:%s", strtok((char *)this->Url,"http://"),
|
||||
this->TcpPort);
|
||||
chunk = curl_slist_append(chunk, header_data);
|
||||
sprintf(header_data,"Date: %s", date_formatted);
|
||||
chunk = curl_slist_append(chunk, header_data);
|
||||
chunk = curl_slist_append(chunk, "Content-Type: application/xml");
|
||||
std::string digest_str;
|
||||
digest_str=Base::base64_encode(digest,strlen((const char *)digest));
|
||||
sprintf(header_data,"Authorization: AWS %s:%s", this->AccessKey,
|
||||
digest_str.c_str());
|
||||
chunk = curl_slist_append(chunk, header_data);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||
sprintf(header_data,"%s:%s/%s/", this->Url,this->TcpPort,
|
||||
this->Bucket);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, header_data);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
|
||||
// curl read a file not a memory buffer (it shall be able to do it)
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
if(res != CURLE_OK)
|
||||
fprintf(stderr, "curl_easy_perform() failed: %s\n",
|
||||
curl_easy_strerror(res));
|
||||
curl_easy_cleanup(curl);
|
||||
std::stringstream input(s);
|
||||
|
||||
try { XMLPlatformUtils::Initialize(); }
|
||||
catch (const XMLException& toCatch) {
|
||||
char* message = XMLString::transcode(toCatch.getMessage());
|
||||
cout << "Error during initialization! :\n"
|
||||
<< message << "\n";
|
||||
XMLString::release(&message);
|
||||
return ;
|
||||
}
|
||||
|
||||
XercesDOMParser* parser = new XercesDOMParser();
|
||||
parser->setValidationScheme(XercesDOMParser::Val_Always);
|
||||
parser->setDoNamespaces(true);
|
||||
|
||||
xercesc::MemBufInputSource myxml_buf((const XMLByte *const)s.c_str(), s.size(),
|
||||
"myxml (in memory)");
|
||||
|
||||
parser->parse(myxml_buf);
|
||||
DOMDocument* dom=parser->getDocument();
|
||||
checkXML(dom);
|
||||
// Dumping the filelist name
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Cloud::CloudReader::DownloadFile(Cloud::CloudReader::FileEntry *entry)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct tm *tm;
|
||||
char date_formatted[256];
|
||||
char StringToSign[1024];
|
||||
unsigned char *digest;
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
||||
std::string s;
|
||||
|
||||
// We must get the directory content
|
||||
|
||||
|
||||
gettimeofday(&tv,NULL);
|
||||
tm = localtime(&tv.tv_sec);
|
||||
strftime(date_formatted,256,"%a, %d %b %Y %T %z", tm);
|
||||
|
||||
// CHANGEME
|
||||
sprintf(StringToSign,"GET\n\napplication/octet-stream\n%s\n/%s/%s", date_formatted, this->Bucket, entry->FileName);
|
||||
|
||||
// We have to use HMAC encoding and SHA1
|
||||
digest=HMAC(EVP_sha1(),this->SecretKey,strlen(this->SecretKey),
|
||||
(const unsigned char *)&StringToSign,strlen(StringToSign),NULL,NULL);
|
||||
|
||||
// Let's build the Header and call to curl
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curl = curl_easy_init();
|
||||
if ( curl )
|
||||
{
|
||||
struct curl_slist *chunk = NULL;
|
||||
char header_data[1024];
|
||||
// Let's build our own header
|
||||
sprintf(header_data,"Host: %s:%s", strtok((char *)this->Url,"http://"),
|
||||
this->TcpPort);
|
||||
chunk = curl_slist_append(chunk, header_data);
|
||||
sprintf(header_data,"Date: %s", date_formatted);
|
||||
chunk = curl_slist_append(chunk, header_data);
|
||||
chunk = curl_slist_append(chunk, "Content-Type: application/octet-stream");
|
||||
std::string digest_str;
|
||||
digest_str=Base::base64_encode(digest,strlen((const char *)digest));
|
||||
sprintf(header_data,"Authorization: AWS %s:%s", this->AccessKey,
|
||||
digest_str.c_str());
|
||||
chunk = curl_slist_append(chunk, header_data);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||
sprintf(header_data,"%s:%s/%s/%s", this->Url,this->TcpPort,
|
||||
this->Bucket,entry->FileName);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, header_data);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
|
||||
// curl read a file not a memory buffer (it shall be able to do it)
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
if(res != CURLE_OK)
|
||||
fprintf(stderr, "curl_easy_perform() failed: %s\n",
|
||||
curl_easy_strerror(res));
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
entry->FileStream << s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct Cloud::CloudReader::FileEntry * Cloud::CloudReader::GetEntry(std::string FileName)
|
||||
{
|
||||
struct Cloud::CloudReader::FileEntry *current_entry=NULL;
|
||||
list<FileEntry*>::const_iterator it1;
|
||||
|
||||
for(it1 = FileList.begin(); it1 != FileList.end(); ++it1) {
|
||||
if ( strcmp(FileName.c_str(), (*it1)->FileName) == 0 )
|
||||
{
|
||||
current_entry = (*it1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( current_entry != NULL )
|
||||
{
|
||||
(*it1)->touch=1;
|
||||
DownloadFile(*it1);
|
||||
}
|
||||
|
||||
return(current_entry);
|
||||
}
|
||||
|
||||
int Cloud::CloudReader::isTouched(std::string FileName)
|
||||
{
|
||||
list<FileEntry*>::const_iterator it1;
|
||||
for(it1 = FileList.begin(); it1 != FileList.end(); ++it1) {
|
||||
if ( strcmp(FileName.c_str(), (*it1)->FileName) == 0 )
|
||||
{
|
||||
if ( (*it1)->touch )
|
||||
return(1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Cloud::CloudWriter::putNextEntry(const char* file)
|
||||
{
|
||||
this->FileName = file;
|
||||
this->FileStream.str("");
|
||||
this->FileStream << std::fixed;
|
||||
this->FileStream.precision(std::numeric_limits<double>::digits10 + 1);
|
||||
this->FileStream.setf(ios::fixed,ios::floatfield);
|
||||
this->FileStream.imbue(std::locale::classic());
|
||||
|
||||
}
|
||||
|
||||
bool Cloud::CloudWriter::shouldWrite(const std::string& , const Base::Persistence *) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
|
||||
{
|
||||
|
||||
struct data_buffer *local_ptr = (struct data_buffer *)stream;
|
||||
size_t data_to_transfer = size * nmemb;
|
||||
|
||||
if(local_ptr->remaining_size) {
|
||||
// copy as much as possible from the source to the destination
|
||||
size_t copy_this_much = local_ptr->remaining_size;
|
||||
if(copy_this_much > data_to_transfer)
|
||||
copy_this_much = data_to_transfer;
|
||||
memcpy(ptr, local_ptr->ptr, copy_this_much);
|
||||
|
||||
local_ptr->ptr += copy_this_much;
|
||||
local_ptr->remaining_size -= copy_this_much;
|
||||
return copy_this_much;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Cloud::CloudWriter::pushCloud(const char *FileName, const char *data, long size)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct tm *tm;
|
||||
char date_formatted[256];
|
||||
char StringToSign[1024];
|
||||
unsigned char *digest;
|
||||
// char my_data[1024]="a que coucou";
|
||||
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
||||
struct data_buffer curl_buffer;
|
||||
|
||||
gettimeofday(&tv,NULL);
|
||||
tm = localtime(&tv.tv_sec);
|
||||
strftime(date_formatted,256,"%a, %d %b %Y %T %z", tm);
|
||||
|
||||
// CHANGEME
|
||||
sprintf(StringToSign,"PUT\n\napplication/octet-stream\n%s\n/%s/%s", date_formatted, this->Bucket, FileName);
|
||||
|
||||
// We have to use HMAC encoding and SHA1
|
||||
digest=HMAC(EVP_sha1(),this->SecretKey,strlen(this->SecretKey),
|
||||
(const unsigned char *)&StringToSign,strlen(StringToSign),NULL,NULL);
|
||||
|
||||
// Let's build the Header and call to curl
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curl = curl_easy_init();
|
||||
if ( curl )
|
||||
{
|
||||
struct curl_slist *chunk = NULL;
|
||||
char header_data[1024];
|
||||
// Let's build our own header
|
||||
sprintf(header_data,"Host: %s:%s", strtok((char *)this->Url,"http://"),
|
||||
this->TcpPort);
|
||||
chunk = curl_slist_append(chunk, header_data);
|
||||
sprintf(header_data,"Date: %s", date_formatted);
|
||||
chunk = curl_slist_append(chunk, header_data);
|
||||
chunk = curl_slist_append(chunk, "Content-Type: application/octet-stream");
|
||||
std::string digest_str;
|
||||
digest_str=Base::base64_encode(digest,strlen((const char *)digest));
|
||||
sprintf(header_data,"Authorization: AWS %s:%s", this->AccessKey,
|
||||
digest_str.c_str());
|
||||
chunk = curl_slist_append(chunk, header_data);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
||||
sprintf(header_data,"%s:%s/%s/%s", this->Url,this->TcpPort,
|
||||
this->Bucket,FileName);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, header_data);
|
||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_PUT, 1L);
|
||||
// curl read a file not a memory buffer (it shall be able to do it)
|
||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
|
||||
curl_buffer.ptr = data;
|
||||
curl_buffer.remaining_size = (size_t) size;
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_READDATA, &curl_buffer);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
|
||||
(curl_off_t)size);
|
||||
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
if(res != CURLE_OK)
|
||||
fprintf(stderr, "curl_easy_perform() failed: %s\n",
|
||||
curl_easy_strerror(res));
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
}
|
||||
|
||||
void Cloud::CloudWriter::writeFiles(void)
|
||||
{
|
||||
|
||||
// use a while loop because it is possible that while
|
||||
// processing the files new ones can be added
|
||||
std::string tmp="";
|
||||
char *cstr;
|
||||
size_t index = 0;
|
||||
if ( strlen(this->FileName.c_str()) > 1 )
|
||||
{
|
||||
// We must push the current buffer
|
||||
const std::string tmp = this->FileStream.str();
|
||||
const char* cstr = tmp.data();
|
||||
pushCloud((const char *)this->FileName.c_str(),cstr, tmp.size());
|
||||
}
|
||||
while (index < FileList.size()) {
|
||||
FileEntry entry = FileList.begin()[index];
|
||||
|
||||
if (shouldWrite(entry.FileName, entry.Object)) {
|
||||
this->FileStream.str("");
|
||||
this->FileStream.precision(std::numeric_limits<double>::digits10 + 1);
|
||||
this->FileStream.setf(ios::fixed,ios::floatfield);
|
||||
this->FileStream.imbue(std::locale::classic());
|
||||
entry.Object->SaveDocFile(*this);
|
||||
tmp = this->FileStream.str();
|
||||
cstr = (char *)tmp.data();
|
||||
pushCloud((const char *)entry.FileName.c_str(), (const char *)cstr, tmp.size());
|
||||
this->FileStream.str("");
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool Cloud::Module::cloudSave(const char *BucketName)
|
||||
{
|
||||
Document* doc = GetApplication().getActiveDocument();
|
||||
|
||||
auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Document");
|
||||
|
||||
// Save the name of the tip object in order to handle in Restore()
|
||||
if (doc->Tip.getValue()) {
|
||||
doc->TipName.setValue(doc->Tip.getValue()->getNameInDocument());
|
||||
}
|
||||
|
||||
std::string LastModifiedDateString = Base::TimeInfo::currentDateTimeString();
|
||||
doc->LastModifiedDate.setValue(LastModifiedDateString.c_str());
|
||||
// set author if needed
|
||||
bool saveAuthor = App::GetApplication().GetParameterGroupByPath
|
||||
("User parameter:BaseApp/Preferences/Document")->GetBool("prefSetAuthorOnSave",false);
|
||||
if (saveAuthor) {
|
||||
std::string Author = App::GetApplication().GetParameterGroupByPath
|
||||
("User parameter:BaseApp/Preferences/Document")->GetASCII("prefAuthor","");
|
||||
doc->LastModifiedBy.setValue(Author.c_str());
|
||||
}
|
||||
if ( strcmp(BucketName, doc->Label.getValue()) != 0 )
|
||||
doc->Label.setValue(BucketName);
|
||||
|
||||
Cloud::CloudWriter mywriter((const char*)this->Url.getStrValue().c_str(),
|
||||
(const char*)this->AccessKey.getStrValue().c_str(),
|
||||
(const char*)this->SecretKey.getStrValue().c_str(),
|
||||
(const char*)this->TcpPort.getStrValue().c_str(),
|
||||
BucketName);
|
||||
|
||||
mywriter.putNextEntry("Document.xml");
|
||||
|
||||
if (hGrp->GetBool("SaveBinaryBrep", false))
|
||||
mywriter.setMode("BinaryBrep");
|
||||
mywriter.Stream() << "<?xml version='1.0' encoding='utf-8'?>" << endl
|
||||
<< "<!--" << endl
|
||||
<< " FreeCAD Document, see http://www.freecadweb.org for more information..." << endl
|
||||
<< "-->" << endl;
|
||||
doc->Save(mywriter);
|
||||
|
||||
// Special handling for Gui document.
|
||||
doc->signalSaveDocument(mywriter);
|
||||
|
||||
// write additional files
|
||||
mywriter.writeFiles();
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
void readFiles(Cloud::CloudReader reader, Base::XMLReader *xmlreader)
|
||||
{
|
||||
// It's possible that not all objects inside the document could be created, e.g. if a module
|
||||
// is missing that would know these object types. So, there may be data files inside the Cloud
|
||||
// file that cannot be read. We simply ignore these files.
|
||||
// On the other hand, however, it could happen that a file should be read that is not part of
|
||||
// the zip file. This happens e.g. if a document is written without GUI up but is read with GUI
|
||||
// up. In this case the associated GUI document asks for its file which is not part of the
|
||||
// file, then.
|
||||
// In either case it's guaranteed that the order of the files is kept.
|
||||
|
||||
std::vector<Base::XMLReader::FileEntry>::const_iterator it = xmlreader->FileList.begin();
|
||||
while ( it != xmlreader->FileList.end()) {
|
||||
if ( reader.isTouched(it->FileName.c_str()) == 0 )
|
||||
{
|
||||
Base::Reader localreader(reader.GetEntry(it->FileName.c_str())->FileStream,it->FileName, xmlreader->FileVersion);
|
||||
it->Object->RestoreDocFile(localreader);
|
||||
if ( localreader.getLocalReader() != nullptr )
|
||||
{
|
||||
readFiles(reader, localreader.getLocalReader());
|
||||
}
|
||||
}
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Cloud::Module::cloudRestore (const char *BucketName)
|
||||
{
|
||||
|
||||
Document* doc = GetApplication().getActiveDocument();
|
||||
// clean up if the document is not empty
|
||||
// !TODO mind exceptions while restoring!
|
||||
|
||||
doc->clearUndos();
|
||||
|
||||
doc->emptyDocument();
|
||||
|
||||
std::stringstream oss;
|
||||
|
||||
Cloud::CloudReader myreader((const char*)this->Url.getStrValue().c_str(),
|
||||
(const char*)this->AccessKey.getStrValue().c_str(),
|
||||
(const char*)this->SecretKey.getStrValue().c_str(),
|
||||
(const char*)this->TcpPort.getStrValue().c_str(),
|
||||
BucketName);
|
||||
|
||||
// we shall pass there the intial Document.xml file
|
||||
|
||||
Base::XMLReader reader("Document.xml", myreader.GetEntry("Document.xml")->FileStream);
|
||||
|
||||
if (!reader.isValid())
|
||||
throw Base::FileException("Error reading Document.xml file","Document.xml");
|
||||
|
||||
|
||||
GetApplication().signalStartRestoreDocument(*doc);
|
||||
doc->setStatus(Document::Restoring, true);
|
||||
|
||||
try {
|
||||
// Document::Restore(reader);
|
||||
doc->Restore(reader);
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Base::Console().Error("Invalid Document.xml: %s\n", e.what());
|
||||
}
|
||||
|
||||
// Special handling for Gui document, the view representations must already
|
||||
// exist, what is done in Restore().
|
||||
// Note: This file doesn't need to be available if the document has been created
|
||||
// without GUI. But if available then follow after all data files of the App document.
|
||||
|
||||
doc->signalRestoreDocument(reader);
|
||||
|
||||
readFiles(myreader,&reader);
|
||||
|
||||
// reset all touched
|
||||
|
||||
doc->resetTouched();
|
||||
|
||||
// if(!doc->delaySignal)
|
||||
doc->afterRestore(true);
|
||||
|
||||
GetApplication().signalFinishRestoreDocument(*doc);
|
||||
doc->setStatus(Document::Restoring, false);
|
||||
return(true);
|
||||
|
||||
}
|
||||
|
||||
145
src/Mod/Cloud/App/AppCloud.h
Normal file
145
src/Mod/Cloud/App/AppCloud.h
Normal file
@@ -0,0 +1,145 @@
|
||||
#include <Base/Writer.h>
|
||||
#include <Base/Reader.h>
|
||||
#include <Base/Base64.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <curl/curl.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <xlocale.h>
|
||||
|
||||
#include <App/PropertyContainer.h>
|
||||
#include <App/PropertyStandard.h>
|
||||
#include <App/PropertyLinks.h>
|
||||
#include <App/Document.h>
|
||||
|
||||
#include <xercesc/framework/XMLPScanToken.hpp>
|
||||
#include <xercesc/sax2/Attributes.hpp>
|
||||
#include <xercesc/sax2/DefaultHandler.hpp>
|
||||
|
||||
#include <xercesc/parsers/XercesDOMParser.hpp>
|
||||
#include <xercesc/dom/DOM.hpp>
|
||||
#include <xercesc/sax/HandlerBase.hpp>
|
||||
#include <xercesc/framework/MemBufInputSource.hpp>
|
||||
|
||||
using namespace App;
|
||||
using namespace std;
|
||||
using namespace xercesc;
|
||||
|
||||
namespace Cloud {
|
||||
|
||||
class BaseExport CloudReader
|
||||
{
|
||||
public:
|
||||
CloudReader(const char* Url, const char* AccessKey, const char* SecretKey, const char* TcpPort, const char* Bucket);
|
||||
virtual ~CloudReader();
|
||||
int print=0;
|
||||
|
||||
struct FileEntry
|
||||
{
|
||||
char FileName[1024];
|
||||
std::stringstream FileStream;
|
||||
int touch=0;
|
||||
};
|
||||
void checkText(DOMText* text);
|
||||
void checkXML(DOMNode* node);
|
||||
void checkElement(DOMElement* element);
|
||||
void addFile(struct Cloud::CloudReader::FileEntry *new_entry);
|
||||
struct FileEntry *GetEntry(std::string FileName);
|
||||
void DownloadFile(Cloud::CloudReader::FileEntry *entry);
|
||||
int isTouched(std::string FileName);
|
||||
protected:
|
||||
std::list<Cloud::CloudReader::FileEntry*> FileList;
|
||||
const char* Url;
|
||||
const char* TcpPort;
|
||||
const char* AccessKey;
|
||||
const char* SecretKey;
|
||||
const char* Bucket;
|
||||
};
|
||||
|
||||
class Module : public Py::ExtensionModule<Module>
|
||||
{
|
||||
public:
|
||||
Module() : Py::ExtensionModule<Module>("Cloud")
|
||||
{
|
||||
add_varargs_method("cloudurl",&Module::sCloudUrl,
|
||||
"cloudurl(string) -- Connect to a Cloud Storage service."
|
||||
);
|
||||
|
||||
add_varargs_method("cloudaccesskey",&Module::sCloudAccessKey,
|
||||
"cloudurl(string) -- Connect to a Cloud Storage service."
|
||||
);
|
||||
|
||||
add_varargs_method("cloudsecretkey",&Module::sCloudSecretKey,
|
||||
"cloudurl(string) -- Connect to a Cloud Storage service."
|
||||
);
|
||||
|
||||
add_varargs_method("cloudtcpport",&Module::sCloudTcpPort,
|
||||
"cloudurl(string) -- Connect to a Cloud Storage service."
|
||||
);
|
||||
|
||||
add_varargs_method("cloudsave",&Module::sCloudSave,
|
||||
"cloudurl(string) -- Connect to a Cloud Storage service."
|
||||
);
|
||||
|
||||
add_varargs_method("cloudrestore",&Module::sCloudRestore,
|
||||
"cloudurl(string) -- Connect to a Cloud Storage service."
|
||||
);
|
||||
|
||||
initialize("This module is the Cloud module."); // register with Python
|
||||
}
|
||||
|
||||
virtual ~Module() {}
|
||||
|
||||
App::PropertyString Url;
|
||||
App::PropertyString TcpPort;
|
||||
App::PropertyString AccessKey;
|
||||
App::PropertyString SecretKey;
|
||||
bool cloudSave(const char* BucketName);
|
||||
bool cloudRestore(const char* BucketName);
|
||||
|
||||
private:
|
||||
Py::Object sCloudUrl (const Py::Tuple& args);
|
||||
Py::Object sCloudAccessKey (const Py::Tuple& args);
|
||||
Py::Object sCloudSecretKey (const Py::Tuple& args);
|
||||
Py::Object sCloudTcpPort (const Py::Tuple& args);
|
||||
Py::Object sCloudSave (const Py::Tuple& args);
|
||||
Py::Object sCloudRestore (const Py::Tuple& args);
|
||||
|
||||
|
||||
};
|
||||
|
||||
PyObject* initModule()
|
||||
{
|
||||
return (new Module)->module().ptr();
|
||||
}
|
||||
|
||||
|
||||
// This class is writing files to an S3 cloud storage class
|
||||
|
||||
class BaseExport CloudWriter : public Base::Writer
|
||||
{
|
||||
public:
|
||||
CloudWriter(const char* Url, const char* AccessKey, const char* SecretKey, const char* TcpPort, const char* Bucket);
|
||||
virtual ~CloudWriter();
|
||||
void pushCloud(const char *FileName, const char *data, long size);
|
||||
void putNextEntry(const char* file);
|
||||
virtual void writeFiles(void);
|
||||
|
||||
virtual std::ostream &Stream(void){return FileStream;}
|
||||
virtual bool shouldWrite(const std::string& name, const Base::Persistence *Object) const;
|
||||
|
||||
protected:
|
||||
std::string FileName;
|
||||
const char* Url;
|
||||
const char* TcpPort;
|
||||
const char* AccessKey;
|
||||
const char* SecretKey;
|
||||
const char* Bucket;
|
||||
std::stringstream FileStream;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
void readFiles(Cloud::CloudReader reader, Base::XMLReader *xmlreader);
|
||||
34
src/Mod/Cloud/App/CMakeLists.txt
Normal file
34
src/Mod/Cloud/App/CMakeLists.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
include_directories(
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${OCC_INCLUDE_DIR}
|
||||
${PYTHON_INCLUDE_DIRS}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${XercesC_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
${CURL_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
set(Cloud_LIBS
|
||||
FreeCADApp
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
${XercesC_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
)
|
||||
|
||||
SET(Cloud_SRCS
|
||||
AppCloud.cpp
|
||||
PreCompiled.cpp
|
||||
PreCompiled.h
|
||||
)
|
||||
|
||||
add_library(Cloud SHARED ${Cloud_SRCS})
|
||||
target_link_libraries(Cloud ${Cloud_LIBS})
|
||||
|
||||
|
||||
SET_BIN_DIR(Cloud Cloud /Mod/Cloud)
|
||||
SET_PYTHON_PREFIX_SUFFIX(Cloud)
|
||||
|
||||
install(TARGETS Cloud DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
24
src/Mod/Cloud/App/PreCompiled.cpp
Normal file
24
src/Mod/Cloud/App/PreCompiled.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) YEAR YOUR NAME <Your e-mail address> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
61
src/Mod/Cloud/App/PreCompiled.h
Normal file
61
src/Mod/Cloud/App/PreCompiled.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) YEAR YOUR NAME <Your e-mail address> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef APP_PRECOMPILED_H
|
||||
#define APP_PRECOMPILED_H
|
||||
|
||||
#include <FCConfig.h>
|
||||
|
||||
// Exporting of App classes
|
||||
#ifdef FC_OS_WIN32
|
||||
# define CloudAppExport __declspec(dllexport)
|
||||
#else // for Linux
|
||||
# define CloudAppExport
|
||||
#endif
|
||||
|
||||
#ifdef _PreComp_
|
||||
|
||||
// standard
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
// STL
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Xerces
|
||||
#include <xercesc/util/XercesDefs.hpp>
|
||||
|
||||
#endif //_PreComp_
|
||||
|
||||
#endif
|
||||
|
||||
30
src/Mod/Cloud/CMakeLists.txt
Normal file
30
src/Mod/Cloud/CMakeLists.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
add_subdirectory(App)
|
||||
if(BUILD_GUI)
|
||||
add_subdirectory(Gui)
|
||||
endif(BUILD_GUI)
|
||||
|
||||
set(Cloud_Scripts
|
||||
Init.py
|
||||
)
|
||||
|
||||
if(BUILD_GUI)
|
||||
list (APPEND Cloud_Scripts InitGui.py)
|
||||
endif(BUILD_GUI)
|
||||
|
||||
add_custom_target(CloudScripts ALL
|
||||
SOURCES ${Cloud_Scripts}
|
||||
)
|
||||
|
||||
fc_target_copy_resource_flat(CloudScripts
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_BINARY_DIR}/Mod/Cloud
|
||||
${Cloud_Scripts}
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
${Cloud_Scripts}
|
||||
DESTINATION
|
||||
Mod/Cloud
|
||||
)
|
||||
3
src/Mod/Cloud/Cloud.dox
Normal file
3
src/Mod/Cloud/Cloud.dox
Normal file
@@ -0,0 +1,3 @@
|
||||
/** \defgroup TEMPLATE Cloud
|
||||
* \ingroup WORKBENCHES */
|
||||
|
||||
82
src/Mod/Cloud/Gui/AppCloudGui.cpp
Normal file
82
src/Mod/Cloud/Gui/AppCloudGui.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) YEAR YOUR NAME <Your e-mail address> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <Python.h>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/PyObjectBase.h>
|
||||
#include <Gui/Application.h>
|
||||
|
||||
#include "Workbench.h"
|
||||
|
||||
#include <CXX/Extensions.hxx>
|
||||
#include <CXX/Objects.hxx>
|
||||
|
||||
// use a different name to CreateCommand()
|
||||
void CreateCloudCommands(void);
|
||||
|
||||
|
||||
namespace CloudGui {
|
||||
class Module : public Py::ExtensionModule<Module>
|
||||
{
|
||||
public:
|
||||
Module() : Py::ExtensionModule<Module>("CloudGui")
|
||||
{
|
||||
initialize("This module is the CloudGui module."); // register with Python
|
||||
}
|
||||
|
||||
virtual ~Module() {}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
PyObject* initModule()
|
||||
{
|
||||
return (new Module)->module().ptr();
|
||||
}
|
||||
|
||||
} // namespace CloudGui
|
||||
|
||||
|
||||
/* Python entry */
|
||||
PyMOD_INIT_FUNC(CloudGui)
|
||||
{
|
||||
if (!Gui::Application::Instance) {
|
||||
PyErr_SetString(PyExc_ImportError, "Cannot load Gui module in console application.");
|
||||
PyMOD_Return(0);
|
||||
}
|
||||
|
||||
// instantiating the commands
|
||||
CreateCloudCommands();
|
||||
CloudGui::Workbench::init();
|
||||
|
||||
// ADD YOUR CODE HERE
|
||||
//
|
||||
//
|
||||
PyObject* mod = CloudGui::initModule();
|
||||
Base::Console().Log("Loading GUI of Cloud module... done\n");
|
||||
PyMOD_Return(mod);
|
||||
}
|
||||
46
src/Mod/Cloud/Gui/CMakeLists.txt
Normal file
46
src/Mod/Cloud/Gui/CMakeLists.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${COIN3D_INCLUDE_DIRS}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${PYTHON_INCLUDE_DIRS}
|
||||
${XercesC_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(CloudGui_LIBS
|
||||
Cloud
|
||||
FreeCADGui
|
||||
)
|
||||
|
||||
if (BUILD_QT5)
|
||||
qt5_add_resources(Cloud_QRC_SRCS Resources/Cloud.qrc)
|
||||
else()
|
||||
qt4_add_resources(Cloud_QRC_SRCS Resources/Cloud.qrc)
|
||||
endif()
|
||||
|
||||
SET(CloudGui_SRCS
|
||||
${Cloud_QRC_SRCS}
|
||||
AppCloudGui.cpp
|
||||
Command.cpp
|
||||
PreCompiled.cpp
|
||||
PreCompiled.h
|
||||
Workbench.cpp
|
||||
Workbench.h
|
||||
)
|
||||
|
||||
SET(Cloud_SVG
|
||||
Resources/icons/CloudWorkbench.svg
|
||||
)
|
||||
|
||||
add_library(CloudGui SHARED ${CloudGui_SRCS} ${Cloud_SVG})
|
||||
target_link_libraries(CloudGui ${CloudGui_LIBS})
|
||||
|
||||
fc_copy_sources(CloudGui "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/Mod/Cloud" ${Cloud_SVG})
|
||||
|
||||
SET_BIN_DIR(CloudGui CloudGui /Mod/Cloud)
|
||||
SET_PYTHON_PREFIX_SUFFIX(CloudGui)
|
||||
|
||||
install(TARGETS CloudGui DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
INSTALL(FILES ${Cloud_SVG} DESTINATION "${CMAKE_INSTALL_DATADIR}/Mod/Cloud/Resources/icons")
|
||||
63
src/Mod/Cloud/Gui/Command.cpp
Normal file
63
src/Mod/Cloud/Gui/Command.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) YEAR YOUR NAME <Your e-mail address> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <App/Document.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Command.h>
|
||||
|
||||
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
//===========================================================================
|
||||
// CmdCloudTest THIS IS JUST A TEST COMMAND
|
||||
//===========================================================================
|
||||
DEF_STD_CMD(CmdCloudTest)
|
||||
|
||||
CmdCloudTest::CmdCloudTest()
|
||||
:Command("Cloud_Test")
|
||||
{
|
||||
sAppModule = "Cloud";
|
||||
sGroup = QT_TR_NOOP("Cloud");
|
||||
sMenuText = QT_TR_NOOP("Hello");
|
||||
sToolTipText = QT_TR_NOOP("Cloud Test function");
|
||||
sWhatsThis = "Cloud_Test";
|
||||
sStatusTip = QT_TR_NOOP("Cloud Test function");
|
||||
sPixmap = "Test1";
|
||||
sAccel = "CTRL+H";
|
||||
}
|
||||
|
||||
void CmdCloudTest::activated(int)
|
||||
{
|
||||
Base::Console().Message("Hello, World!\n");
|
||||
}
|
||||
|
||||
void CreateCloudCommands(void)
|
||||
{
|
||||
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
|
||||
rcCmdMgr.addCommand(new CmdCloudTest());
|
||||
}
|
||||
24
src/Mod/Cloud/Gui/PreCompiled.cpp
Normal file
24
src/Mod/Cloud/Gui/PreCompiled.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) YEAR YOUR NAME <Your e-mail address> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
70
src/Mod/Cloud/Gui/PreCompiled.h
Normal file
70
src/Mod/Cloud/Gui/PreCompiled.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) YEAR YOUR NAME <Your e-mail address> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef GUI_PRECOMPILED_H
|
||||
#define GUI_PRECOMPILED_H
|
||||
|
||||
#include <FCConfig.h>
|
||||
|
||||
// Importing of App classes
|
||||
#ifdef FC_OS_WIN32
|
||||
# define CloudAppExport __declspec(dllimport)
|
||||
# define CloudGuiExport __declspec(dllexport)
|
||||
#else // for Linux
|
||||
# define CloudAppExport
|
||||
# define CloudGuiExport
|
||||
#endif
|
||||
|
||||
#ifdef _PreComp_
|
||||
|
||||
// standard
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
// STL
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Xerces
|
||||
#include <xercesc/util/XercesDefs.hpp>
|
||||
|
||||
#ifdef FC_OS_WIN32
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
// Qt Toolkit
|
||||
#ifndef __Qt4All__
|
||||
# include <Gui/Qt4All.h>
|
||||
#endif
|
||||
|
||||
#endif //_PreComp_
|
||||
|
||||
#endif // GUI_PRECOMPILED_H
|
||||
4
src/Mod/Cloud/Gui/Resources/Cloud.qrc
Normal file
4
src/Mod/Cloud/Gui/Resources/Cloud.qrc
Normal file
@@ -0,0 +1,4 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
</qresource>
|
||||
</RCC>
|
||||
17
src/Mod/Cloud/Gui/Resources/icons/CloudWorkbench.svg
Normal file
17
src/Mod/Cloud/Gui/Resources/icons/CloudWorkbench.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="64.000000pt" height="64.000000pt" viewBox="0 0 64.000000 64.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by Jean-Marie Verdun using potrace 1.15, written by Peter Selinger 2001-2017
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,64.000000) scale(0.100000,-0.100000)"
|
||||
fill="#4472C4" stroke="none">
|
||||
<path d="M211 523 c-21 -10 -40 -31 -51 -55 -9 -21 -34 -53 -55 -71 -34 -29
|
||||
-39 -39 -42 -88 -4 -45 -1 -60 19 -89 34 -50 70 -59 238 -59 120 -1 152 3 186
|
||||
18 99 45 96 196 -4 238 -20 8 -50 13 -67 10 -29 -5 -33 -2 -49 33 -30 68 -109
|
||||
97 -175 63z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 781 B |
65
src/Mod/Cloud/Gui/Workbench.cpp
Normal file
65
src/Mod/Cloud/Gui/Workbench.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) YEAR YOUR NAME <Your e-mail address> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
|
||||
#include "Workbench.h"
|
||||
#include <Gui/MenuManager.h>
|
||||
#include <Gui/ToolBarManager.h>
|
||||
|
||||
using namespace CloudGui;
|
||||
|
||||
/// @namespace CloudGui @class Workbench
|
||||
TYPESYSTEM_SOURCE(CloudGui::Workbench, Gui::StdWorkbench)
|
||||
|
||||
Workbench::Workbench()
|
||||
{
|
||||
}
|
||||
|
||||
Workbench::~Workbench()
|
||||
{
|
||||
}
|
||||
/*
|
||||
Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
{
|
||||
Gui::MenuItem* root = StdWorkbench::setupMenuBar();
|
||||
Gui::MenuItem* item = root->findItem( "&Windows" );
|
||||
Gui::MenuItem* test = new Gui::MenuItem;
|
||||
root->insertItem( item, test );
|
||||
test->setCommand("Cloud");
|
||||
*test << "Cloud_Test";
|
||||
return root;
|
||||
}
|
||||
|
||||
Gui::ToolBarItem* Workbench::setupToolBars() const
|
||||
{
|
||||
Gui::ToolBarItem* root = StdWorkbench::setupToolBars();
|
||||
Gui::ToolBarItem* test = new Gui::ToolBarItem(root);
|
||||
test->setCommand( "Cloud Tools" );
|
||||
*test << "Cloud_Test";
|
||||
return root;
|
||||
}
|
||||
*/
|
||||
47
src/Mod/Cloud/Gui/Workbench.h
Normal file
47
src/Mod/Cloud/Gui/Workbench.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) YEAR YOUR NAME <Your e-mail address> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef Cloud_WORKBENCH_H
|
||||
#define Cloud_WORKBENCH_H
|
||||
|
||||
#include <Gui/Workbench.h>
|
||||
|
||||
namespace CloudGui {
|
||||
|
||||
class Workbench : public Gui::StdWorkbench
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
Workbench();
|
||||
virtual ~Workbench();
|
||||
|
||||
protected:
|
||||
// Gui::MenuItem* setupMenuBar() const;
|
||||
// Gui::ToolBarItem* setupToolBars() const;
|
||||
};
|
||||
|
||||
} // namespace CloudGui
|
||||
|
||||
|
||||
#endif // Cloud_WORKBENCH_H
|
||||
2
src/Mod/Cloud/Init.py
Normal file
2
src/Mod/Cloud/Init.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# FreeCAD init script of the Cloud module
|
||||
# (c) 2001 Juergen Riegel LGPL
|
||||
17
src/Mod/Cloud/InitGui.py
Normal file
17
src/Mod/Cloud/InitGui.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# Cloud gui init module
|
||||
# (c) 2001 Juergen Riegel LGPL
|
||||
|
||||
class CloudWorkbench ( Workbench ):
|
||||
"Cloud workbench object"
|
||||
def __init__(self):
|
||||
self.__class__.Icon = FreeCAD.getResourceDir() + "Mod/Cloud/Resources/icons/CloudWorkbench.svg"
|
||||
|
||||
MenuText = "Cloud"
|
||||
ToolTip = "Cloud workbench"
|
||||
def Initialize(self):
|
||||
# load the module
|
||||
import CloudGui
|
||||
def GetClassName(self):
|
||||
return "CloudGui::Workbench"
|
||||
|
||||
Gui.addWorkbench(CloudWorkbench())
|
||||
Reference in New Issue
Block a user