diff --git a/src/Mod/Arch/Arch.py b/src/Mod/Arch/Arch.py index d2f08dcffe..3be3b74bf5 100644 --- a/src/Mod/Arch/Arch.py +++ b/src/Mod/Arch/Arch.py @@ -58,7 +58,6 @@ from ArchFrame import * from ArchPanel import * from ArchEquipment import * from ArchCutPlane import * -from ArchServer import * from ArchMaterial import * from ArchSchedule import * from ArchPrecast import * diff --git a/src/Mod/Arch/ArchServer.py b/src/Mod/Arch/ArchServer.py deleted file mode 100644 index 9e06b44586..0000000000 --- a/src/Mod/Arch/ArchServer.py +++ /dev/null @@ -1,500 +0,0 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2015 * -#* Yorik van Havre * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* This program 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 program; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#*************************************************************************** - -import FreeCAD, os, time, tempfile, base64, Draft -from PySide import QtCore, QtGui - -if FreeCAD.GuiUp: - import FreeCADGui - from DraftTools import translate - from PySide.QtCore import QT_TRANSLATE_NOOP -else: - # \cond - def translate(ctxt,txt): - return txt - def QT_TRANSLATE_NOOP(ctxt,txt): - return txt - # \endcond - -## @package ArchServer -# \ingroup ARCH -# \brief The Server object and tools -# -# This module provides utility functions to connect with -# online or local servers like BimServer or GIT - -__title__="FreeCAD Arch Server commands" -__author__ = "Yorik van Havre" -__url__ = "http://www.freecadweb.org" - - - -# BIMSERVER ########################################################### - - - -class _CommandBimserver: - - "the Arch Bimserver command definition" - - def GetResources(self): - return {'Pixmap' : 'Arch_Bimserver', - 'MenuText': QT_TRANSLATE_NOOP("Arch_Bimserver","BIM server"), - 'ToolTip': QT_TRANSLATE_NOOP("Arch_Bimserver","Connects and interacts with a BIM server instance")} - - def Activated(self): - try: - import requests - except: - FreeCAD.Console.PrintError(translate("Arch","requests python module not found, aborting. Please install python-requests\n")) - return - try: - import json - except: - FreeCAD.Console.PrintError(translate("Arch","json python module not found, aborting. Please install python-json\n")) - else: - FreeCADGui.Control.showDialog(_BimServerTaskPanel()) - - -class _BimServerTaskPanel: - - '''The TaskPanel for the BimServer command''' - - def __init__(self): - self.form = FreeCADGui.PySideUic.loadUi(":/ui/BimServerTaskPanel.ui") - self.form.setWindowIcon(QtGui.QIcon(":/icons/Arch_Bimserver.svg")) - self.form.labelStatus.setText("") - QtCore.QObject.connect(self.form.buttonServer, QtCore.SIGNAL("clicked()"), self.login) - QtCore.QObject.connect(self.form.buttonBrowser, QtCore.SIGNAL("clicked()"), self.browse) - QtCore.QObject.connect(self.form.comboProjects, QtCore.SIGNAL("currentIndexChanged(int)"), self.getRevisions) - QtCore.QObject.connect(self.form.buttonOpen, QtCore.SIGNAL("clicked()"), self.openFile) - QtCore.QObject.connect(self.form.buttonUpload, QtCore.SIGNAL("clicked()"), self.uploadFile) - self.prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch") - self.Projects = [] - self.Revisions = [] - self.RootObjects = Draft.getObjectsOfType(FreeCAD.ActiveDocument.Objects,"Site")+Draft.getObjectsOfType(FreeCAD.ActiveDocument.Objects,"Building") - for o in self.RootObjects: - self.form.comboRoot.addItem(o.Label) - self.setLogged(False) - url,token = self.getPrefs() - if url and token: - self.getProjects() - - def getStandardButtons(self): - return int(QtGui.QDialogButtonBox.Close) - - def accept(self): - FreeCADGui.Control.closeDialog() - - def getPrefs(self): - url = self.prefs.GetString("BimServerUrl","http://localhost:8082") - if hasattr(self,"token"): - token = self.token - else: - token = self.prefs.GetString("BimServerToken","") - if token: - self.token = token - return url,token - - def setLogged(self,logged): - if logged: - self.form.buttonServer.setText("Connected") - self.form.buttonServer.setIcon(QtGui.QIcon(":/icons/edit_OK.svg")) - self.form.buttonServer.setToolTip("Click to log out") - self.Connected = True - else: - self.form.buttonServer.setText("Not connected") - self.form.buttonServer.setIcon(QtGui.QIcon(":/icons/edit_Cancel.svg")) - self.form.buttonServer.setToolTip("Click to log in") - self.Connected = False - - def login(self): - self.setLogged(False) - self.form.labelStatus.setText("") - if self.Connected: - # if the user pressed logout, delete the token - self.prefs.SetString("BimServerToken","") - else: - url,token = self.getPrefs() - loginform = FreeCADGui.PySideUic.loadUi(":/ui/DialogBimServerLogin.ui") - loginform.editUrl.setText(url) - dlg = loginform.exec_() - if dlg: - url = loginform.editUrl.text() - login = loginform.editLogin.text() - passwd = loginform.editPassword.text() - store = loginform.checkStore.isChecked() - import requests, json - self.form.labelStatus.setText("Logging in...") - url2 = url + "/json" - data = {'request': {'interface': 'AuthInterface', 'method': 'login', 'parameters': {'username': login, 'password': passwd}}} - try: - resp = requests.post(url2,data = json.dumps(data)) - except: - FreeCAD.Console.PrintError(translate("Arch","Unable to connect to BimServer at")+" "+url+"\n") - self.form.labelStatus.setText(translate("Arch","Connection failed.")) - return - if resp.ok: - try: - token = resp.json()["response"]["result"] - except: - return - else: - if store: - self.prefs.SetString("BimServerUrl",url) - if token: - self.prefs.SetString("BimServerToken",token) - else: - self.prefs.SetString("BimServerToken","") - if token: - self.token = token - self.getProjects() - self.form.labelStatus.setText("") - - def browse(self): - url = self.prefs.GetString("BimServerUrl","http://localhost:8082")+"/apps/bimviews" - if self.prefs.GetBool("BimServerBrowser",False): - FreeCADGui.addModule("WebGui") - FreeCADGui.doCommand("WebGui.openBrowser(\""+url+"\")") - else: - QtGui.QDesktopServices.openUrl(QtCore.QUrl(url, QtCore.QUrl.TolerantMode)) - - def getProjects(self): - self.setLogged(False) - self.Projects = [] - self.form.labelStatus.setText("") - import requests, json - url,token = self.getPrefs() - if url and token: - self.form.labelStatus.setText(translate("Arch","Getting projects list...")) - url += "/json" - data = { "token": token, "request": { "interface": "SettingsInterface", "method": "getServerSettings", "parameters": { } } } - try: - resp = requests.post(url,data = json.dumps(data)) - except: - FreeCAD.Console.PrintError(translate("Arch","Unable to connect to BimServer at")+" "+url[:-5]+"\n") - self.form.labelStatus.setText(translate("Arch","Connection failed.")) - return - if resp.ok: - try: - name = resp.json()["response"]["result"]["name"] - except: - pass # unable to get the server name - else: - self.form.labelServerName.setText(name) - data = { "token": token, "request": { "interface": "ServiceInterface", "method": "getAllProjects", "parameters": { "onlyTopLevel": "false", "onlyActive": "true" } } } - resp = requests.post(url,data = json.dumps(data)) - if resp.ok: - try: - projects = resp.json()["response"]["result"] - except: - FreeCAD.Console.PrintError(translate("Arch","Unable to get projects list from BimServer\n")) - else: - self.setLogged(True) - self.form.comboProjects.clear() - for p in projects: - self.form.comboProjects.addItem(p["name"]) - self.Projects = projects - self.form.comboProjects.setCurrentIndex(0) - self.getRevisions(0) - self.form.labelStatus.setText("") - - def getRevisions(self,index): - self.form.labelStatus.setText("") - self.form.listRevisions.clear() - self.Revisions = [] - import requests, json - url,token = self.getPrefs() - if url and token: - url += "/json" - if (index >= 0) and (len(self.Projects) > index): - p = self.Projects[index] - self.form.labelStatus.setText(translate("Arch","Getting revisions...")) - for rev in p["revisions"]: - data = { "token": token, "request": { "interface": "ServiceInterface", "method": "getRevision", "parameters": { "roid": rev } } } - resp = requests.post(url,data = json.dumps(data)) - if resp.ok: - try: - name = resp.json()["response"]["result"]["comment"] - date = resp.json()["response"]["result"]["date"] - except: - pass # unable to get the revision - else: - date = time.strftime("%a %d %b %Y %H:%M:%S GMT", time.gmtime(int(date)/1000.0)) - self.form.listRevisions.addItem(date+" - "+name) - self.Revisions.append(resp.json()["response"]["result"]) - self.form.labelStatus.setText("") - - def openFile(self): - self.form.labelStatus.setText("") - if (self.form.listRevisions.currentRow() >= 0) and (len(self.Revisions) > self.form.listRevisions.currentRow()): - rev = self.Revisions[self.form.listRevisions.currentRow()] - import requests, json - url,token = self.getPrefs() - if url and token: - FreeCAD.Console.PrintMessage(translate("Arch","Downloading file from Bimserver...\n")) - self.form.labelStatus.setText(translate("Arch","Checking available serializers...")) - url += "/json" - serializer = None - for s in ["Ifc2x3tc1"]: # Ifc4 seems unreliable ATM, let's stick with good old Ifc2x3... - data = { "token": token, "request": { "interface": "ServiceInterface", "method": "getSerializerByName", "parameters": { "serializerName": s } } } - resp = requests.post(url,data = json.dumps(data)) - if resp.ok: - try: - srl = resp.json()["response"]["result"] - except: - pass # unable to get this serializer - else: - serializer = srl - break - if not serializer: - FreeCAD.Console.PrintError(translate("Arch","Unable to get a valid serializer from the BimServer\n")) - return - tf = QtGui.QFileDialog.getSaveFileName(QtGui.qApp.activeWindow(), "Save the downloaded IFC file?", None, "IFC files (*.ifc)") - if tf: - tf = tf[0] - self.form.labelStatus.setText(translate("Arch","Downloading file...")) - data = { "token": token, "request": { "interface": "ServiceInterface", "method": "downloadRevisions", "parameters": { "roids": [rev["oid"]], "serializerOid": serializer["oid"], "sync": "false" } } } - resp = requests.post(url,data = json.dumps(data)) - if resp.ok: - try: - downloadid = resp.json()["response"]["result"] - except: - FreeCAD.Console.PrintError(translate("Arch","Unable to obtain a valid download for this revision from the BimServer\n")) - return - data = { "token": token, "request": { "interface": "ServiceInterface", "method": "getDownloadData", "parameters": { "topicId": downloadid } } } - resp = requests.post(url,data = json.dumps(data)) - if resp.ok: - try: - downloaddata = resp.json()["response"]["result"]["file"] - except: - FreeCAD.Console.PrintError(translate("Arch","Unable to download the data for this revision.\n")) - return - else: - FreeCAD.Console.PrintMessage(translate("Arch","Opening file...\n")) - self.form.labelStatus.setText(translate("Arch","Opening file...")) - if not tf: - th,tf = tempfile.mkstemp(suffix=".ifc") - f = open(tf,"wb") - f.write(base64.b64decode(downloaddata)) - f.close() - os.close(th) - import importIFC - importIFC.open(tf) - os.remove(tf) - self.form.labelStatus.setText("") - - def uploadFile(self): - self.form.labelStatus.setText("") - if (self.form.comboProjects.currentIndex() >= 0) and (len(self.Projects) > self.form.comboProjects.currentIndex()) and (self.form.comboRoot.currentIndex() >= 0): - project = self.Projects[self.form.comboProjects.currentIndex()] - import requests, json - url,token = self.getPrefs() - if url and token: - url += "/json" - deserializer = None - FreeCAD.Console.PrintMessage(translate("Arch","Saving file...\n")) - self.form.labelStatus.setText(translate("Arch","Checking available deserializers...")) - import ifcopenshell - schema = ifcopenshell.schema_identifier.lower() - data = { "token": token, "request": { "interface": "PluginInterface", "method": "getAllDeserializers", "parameters": { "onlyEnabled": "true" } } } - resp = requests.post(url,data = json.dumps(data)) - if resp.ok: - try: - for d in resp.json()["response"]["result"]: - if schema in d["name"].lower(): - deserializer = d - break - except: - pass - if not deserializer: - FreeCAD.Console.PrintError(translate("Arch","Unable to get a valid deserializer for the schema")+" "+schema+"\n") - return - tf = QtGui.QFileDialog.getSaveFileName(QtGui.qApp.activeWindow(), translate("Arch","Save the IFC file before uploading?"), None, translate("Arch","IFC files (*.ifc)")) - if tf: - tf = tf[0] - if not tf: - tf = os.path.join(tempfile._get_default_tempdir(),next(tempfile._get_candidate_names())+".ifc") - import importIFC - self.form.labelStatus.setText(translate("Arch","Saving file...")) - importIFC.export([self.RootObjects[self.form.comboRoot.currentIndex()]],tf) - f = open(tf,"rb") - ifcdata = base64.b64encode(f.read()) - f.close() - FreeCAD.Console.PrintMessage(translate("Arch","Uploading file to Bimserver...\n")) - self.form.labelStatus.setText(translate("Arch","Uploading file...")) - data = { "token": token, "request": { "interface": "ServiceInterface", "method": "checkin", "parameters": { "poid": project["oid"], "comment": self.form.editComment.text(), "deserializerOid": deserializer["oid"], "fileSize": os.path.getsize(tf), "fileName": os.path.basename(tf), "data": ifcdata, "merge": "false", "sync": "true" } } } - resp = requests.post(url,data = json.dumps(data)) - if resp.ok: - if resp.json()["response"]["result"]: - FreeCAD.Console.PrintMessage(translate("Arch","File upload successful\n")) - self.getRevisions(self.form.comboProjects.currentIndex()) - else: - FreeCAD.Console.PrintError(translate("Arch","File upload failed\n")) - self.form.labelStatus.setText("") - - - -# GIT ########################################################### - - - -class _CommandGit: - "the Arch Git Commit command definition" - def GetResources(self): - return {'Pixmap' : 'Git', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Arch_Git","Git"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Arch_Git","Manages the current document with Git")} - - def Activated(self): - f = FreeCAD.ActiveDocument.FileName - if not f: - FreeCAD.Console.PrintError(translate("Arch","This document is not saved. Please save it first.\n")) - return - try: - import git - except: - FreeCAD.Console.PrintError(translate("Arch","The Python Git module was not found. Please install the python-git package.\n")) - return - try: - repo = git.Repo(os.path.dirname(f)) - except: - FreeCAD.Console.PrintError(translate("Arch","This document doesn't appear to be part of a Git repository.\n")) - return - else: - FreeCADGui.Control.showDialog(_GitTaskPanel(repo)) - - -class _GitTaskPanel: - - '''The TaskPanel for the Git command''' - - def __init__(self,repo): - self.form = FreeCADGui.PySideUic.loadUi(":/ui/GitTaskPanel.ui") - self.form.setWindowIcon(QtGui.QIcon(":/icons/Git.svg")) - self.form.labelStatus.setText("") - QtCore.QObject.connect(self.form.buttonRefresh, QtCore.SIGNAL("clicked()"), self.getFiles) - QtCore.QObject.connect(self.form.buttonLog, QtCore.SIGNAL("clicked()"), self.getLog) - QtCore.QObject.connect(self.form.buttonSelectAll, QtCore.SIGNAL("clicked()"), self.form.listFiles.selectAll) - QtCore.QObject.connect(self.form.buttonDiff, QtCore.SIGNAL("clicked()"), self.getDiff) - QtCore.QObject.connect(self.form.buttonCommit, QtCore.SIGNAL("clicked()"), self.commit) - QtCore.QObject.connect(self.form.buttonPush, QtCore.SIGNAL("clicked()"), self.push) - QtCore.QObject.connect(self.form.buttonPull, QtCore.SIGNAL("clicked()"), self.pull) - self.repo = repo - self.getRemotes() - self.getFiles() - - def getStandardButtons(self): - return int(QtGui.QDialogButtonBox.Close) - - def accept(self): - FreeCADGui.Control.closeDialog() - - def getFiles(self): - self.form.labelStatus.setText("") - self.form.listFiles.clear() - self.modified = self.repo.git.diff("--name-only").split() - self.untracked = self.repo.git.ls_files("--other","--exclude-standard").split() - for f in self.modified: - self.form.listFiles.addItem(f) - for f in self.untracked: - self.form.listFiles.addItem(f+" *") - self.form.labelStatus.setText(translate("Arch","Branch")+": "+self.repo.active_branch.name) - - def getLog(self): - textform = FreeCADGui.PySideUic.loadUi(":/ui/DialogDisplayText.ui") - textform.setWindowTitle("Git log") - textform.browserText.setPlainText(self.repo.git.log()) - textform.exec_() - - def getDiff(self): - if (self.form.listFiles.currentRow() >= 0): - f = (self.modified+self.untracked)[self.form.listFiles.currentRow()] - textform = FreeCADGui.PySideUic.loadUi(":/ui/DialogDisplayText.ui") - textform.setWindowTitle("Diff: "+f) - textform.browserText.setPlainText(self.repo.git.diff(f)) - textform.exec_() - - def getRemotes(self): - self.form.listRepos.clear() - if self.repo.remotes: - for r in self.repo.remotes: - self.form.listRepos.addItem(r.name+": "+r.url) - else: - FreeCAD.Console.PrintWarning(translate("Arch","Warning: no remote repositories.\n")) - - def commit(self): - if not self.form.listFiles.selectedItems(): - FreeCAD.Console.PrintError(translate("Arch","Please select file(s) to commit.\n")) - self.form.labelStatus.setText(translate("Arch","No file selected")) - return - if not self.form.editMessage.text(): - FreeCAD.Console.PrintError(translate("Arch","Please write a commit message.\n")) - self.form.labelStatus.setText(translate("Arch","No commit message")) - return - for it in self.form.listFiles.selectedItems(): - f = it.text() - if f[-2:] == " *": - f = f[:-2] - self.repo.git.add(f) - s = self.repo.git.commit(m=self.form.editMessage.text()) - FreeCAD.Console.PrintMessage(translate("Arch","Successfully committed %i files.\n") % len(self.form.listFiles.selectedItems())) - self.form.labelStatus.setText(translate("Arch","Files committed.")) - if s: - FreeCAD.Console.PrintMessage(s+"\n") - self.getFiles() - - def push(self): - if len(self.form.listRepos.selectedItems()) != 1: - FreeCAD.Console.PrintError(translate("Arch","Please select a repo to push to.\n")) - self.form.labelStatus.setText(translate("Arch","No repo selected")) - return - self.form.labelStatus.setText(translate("Arch","Pushing files...")) - r = self.form.listRepos.selectedItems()[0].text().split(":")[0] - s = self.repo.git.push(r) - FreeCAD.Console.PrintMessage(translate("Arch","Successfully pushed to")+" "+r+"\n") - self.form.labelStatus.setText(translate("Arch","Files pushed.")) - if s: - FreeCAD.Console.PrintMessage(s+"\n") - self.getFiles() - - def pull(self): - if len(self.form.listRepos.selectedItems()) != 1: - FreeCAD.Console.PrintError(translate("Arch","Please select a repo to pull from.\n")) - self.form.labelStatus.setText(translate("Arch","No repo selected")) - return - self.form.labelStatus.setText(translate("Arch","Pulling files...")) - r = self.form.listRepos.selectedItems()[0].text().split(":")[0] - s = self.repo.git.pull(r) - FreeCAD.Console.PrintMessage(translate("Arch","Successfully pulled from")+" "+r+"\n") - self.form.labelStatus.setText(translate("Arch","Files pulled.")) - if s: - FreeCAD.Console.PrintMessage(s+"\n") - if os.path.basename(FreeCAD.ActiveDocument.FileName) in s: - FreeCAD.Console.PrintWarning(translate("Arch","Warning: the current document file has been changed by this pull. Please save your document to keep your changes.\n")) - - - -if FreeCAD.GuiUp: - FreeCADGui.addCommand('Arch_Bimserver',_CommandBimserver()) - FreeCADGui.addCommand('Arch_Git',_CommandGit()) diff --git a/src/Mod/Arch/CMakeLists.txt b/src/Mod/Arch/CMakeLists.txt index 2120f1c467..ad2b1e4a09 100644 --- a/src/Mod/Arch/CMakeLists.txt +++ b/src/Mod/Arch/CMakeLists.txt @@ -31,7 +31,6 @@ SET(Arch_SRCS ArchPanel.py ArchEquipment.py ArchCutPlane.py - ArchServer.py ArchMaterial.py ArchSchedule.py ArchProfile.py diff --git a/src/Mod/Arch/InitGui.py b/src/Mod/Arch/InitGui.py index aabbf68625..920382b415 100644 --- a/src/Mod/Arch/InitGui.py +++ b/src/Mod/Arch/InitGui.py @@ -44,7 +44,7 @@ class ArchWorkbench(Workbench): "Arch_SelectNonSolidMeshes","Arch_RemoveShape", "Arch_CloseHoles","Arch_MergeWalls","Arch_Check", "Arch_IfcExplorer","Arch_ToggleIfcBrepFlag","Arch_3Views", - "Arch_Bimserver","Arch_Git","Arch_IfcSpreadsheet","Arch_ToggleSubs"] + "Arch_IfcSpreadsheet","Arch_ToggleSubs"] # draft tools self.drafttools = ["Draft_Line","Draft_Wire","Draft_Circle","Draft_Arc","Draft_Ellipse", diff --git a/src/Mod/Web/CMakeLists.txt b/src/Mod/Web/CMakeLists.txt index e007f7f48f..e0c11d989c 100644 --- a/src/Mod/Web/CMakeLists.txt +++ b/src/Mod/Web/CMakeLists.txt @@ -1,10 +1,6 @@ add_subdirectory(App) if(BUILD_GUI) - SET(Web_Scripts - Webscripts/__init__.py - Webscripts/Sketchfab.py - ) if(Qt5WebKitWidgets_FOUND OR QT_QTWEBKIT_FOUND) add_subdirectory(Gui) endif() @@ -17,11 +13,3 @@ INSTALL( DESTINATION Mod/Web ) - -INSTALL( - FILES - Webscripts/__init__.py - Webscripts/Sketchfab.py - DESTINATION - Mod/Web/Webscripts -) diff --git a/src/Mod/Web/Gui/Command.cpp b/src/Mod/Web/Gui/Command.cpp index b1a0af47ec..06e0f9fd7d 100644 --- a/src/Mod/Web/Gui/Command.cpp +++ b/src/Mod/Web/Gui/Command.cpp @@ -237,35 +237,6 @@ bool CmdWebBrowserZoomOut::isActive(void) return getGuiApplication()->sendHasMsgToActiveView("ZoomOut"); } -//=========================================================================== -// CmdWebSketchfab -//=========================================================================== - -DEF_STD_CMD_A(CmdWebSketchfab); - -CmdWebSketchfab::CmdWebSketchfab() - : Command("Web_Sketchfab") -{ - sAppModule = "Web"; - sGroup = QT_TR_NOOP("Web"); - sMenuText = QT_TR_NOOP("Sketchfab"); - sToolTipText = QT_TR_NOOP("Uploads a model to your sketchfab account"); - sWhatsThis = sToolTipText; - sStatusTip = sToolTipText; - sPixmap = "actions/web-sketchfab"; -} - -void CmdWebSketchfab::activated(int iMsg) -{ - Q_UNUSED(iMsg); - doCommand(Command::Gui,"from Webscripts import Sketchfab"); - doCommand(Command::Gui,"FreeCADGui.Control.showDialog(Sketchfab.SketchfabTaskPanel())"); -} - -bool CmdWebSketchfab::isActive(void) -{ - return hasActiveDocument(); -} void CreateWebCommands(void) { @@ -278,5 +249,4 @@ void CreateWebCommands(void) rcCmdMgr.addCommand(new CmdWebBrowserStop()); rcCmdMgr.addCommand(new CmdWebBrowserZoomIn()); rcCmdMgr.addCommand(new CmdWebBrowserZoomOut()); - rcCmdMgr.addCommand(new CmdWebSketchfab()); } diff --git a/src/Mod/Web/Gui/Workbench.cpp b/src/Mod/Web/Gui/Workbench.cpp index 9526963c34..163322b571 100644 --- a/src/Mod/Web/Gui/Workbench.cpp +++ b/src/Mod/Web/Gui/Workbench.cpp @@ -333,9 +333,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const << "Web_BrowserStop" << "Separator" << "Web_BrowserZoomIn" - << "Web_BrowserZoomOut" - << "Separator" - << "Web_Sketchfab"; + << "Web_BrowserZoomOut"; return root; diff --git a/src/Mod/Web/Webscripts/Sketchfab.py b/src/Mod/Web/Webscripts/Sketchfab.py deleted file mode 100644 index 9416354854..0000000000 --- a/src/Mod/Web/Webscripts/Sketchfab.py +++ /dev/null @@ -1,296 +0,0 @@ -#*************************************************************************** -#* * -#* Copyright (c) 2017 - Yorik van Havre * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* This program 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 program; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#* * -#*************************************************************************** - -from __future__ import print_function - -__title__ = "Sketchfab uploader" -__author__ = "Yorik van Havre" -__url__ = "http://www.freecadweb.org" - -import FreeCAD, FreeCADGui, WebGui, os, zipfile, requests, tempfile, json, time, re -from PySide import QtCore, QtGui - -# \cond -try: - def translate(context, text, disambig=None): - return QtGui.QApplication.translate(context, text, disambig, QtGui.QApplication.UnicodeUTF8) -except AttributeError: - def translate(context, text, disambig=None): - return QtGui.QApplication.translate(context, text, disambig) -# \endcond - -SKETCHFAB_UPLOAD_URL = "https://api.sketchfab.com/v3/models" -SKETCHFAB_TOKEN_URL = "https://sketchfab.com/settings/password" -SKETCHFAB_MODEL_URL = "https://sketchfab.com/show/" - - -class SketchfabTaskPanel: - - '''The TaskPanel for Sketchfab upload''' - - def __init__(self): - - self.url = None - self.form = FreeCADGui.PySideUic.loadUi(":/ui/TaskDlgSketchfab.ui") - self.form.ProgressBar.hide() - self.form.Button_View.hide() - QtCore.QObject.connect(self.form.Button_Token,QtCore.SIGNAL("pressed()"),self.getToken) - QtCore.QObject.connect(self.form.Button_Upload,QtCore.SIGNAL("pressed()"),self.upload) - QtCore.QObject.connect(self.form.Button_View,QtCore.SIGNAL("pressed()"),self.viewModel) - self.form.Text_Name.setText(FreeCAD.ActiveDocument.Label) - self.form.Text_Token.setText(FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Web").GetString("SketchfabToken","")) - - def isAllowedAlterSelection(self): - - return True - - def isAllowedAlterView(self): - - return True - - def getStandardButtons(self): - - return int(QtGui.QDialogButtonBox.Close) - - def accept(self): - - FreeCADGui.ActiveDocument.resetEdit() - return True - - def getToken(self): - - QtGui.QDesktopServices.openUrl(SKETCHFAB_TOKEN_URL) - - def get_request_payload(self, token, data={}, files={}, json_payload=False): - - """Helper method that returns the authentication token and proper content - type depending on whether or not we use JSON payload.""" - headers = {'Authorization': 'Token {}'.format(token)} - if json_payload: - headers.update({'Content-Type': 'application/json'}) - data = json.dumps(data) - return {'data': data, 'files': files, 'headers': headers} - - def saveFile(self): - - import FreeCADGui - if self.form.Radio_Selection.isChecked(): - objects = FreeCADGui.Selection.getSelection() - else: - objects = [obj for obj in FreeCAD.ActiveDocument.Objects if obj.ViewObject.isVisible()] - if not objects: - QtGui.QMessageBox.critical(None,translate("Web","Nothing to upload"),translate("The selection of the document contains no object to upload")) - return None - filename = os.path.join(tempfile._get_default_tempdir(),next(tempfile._get_candidate_names())) - filetype = self.form.Combo_Filetype.currentIndex() - # 0 = obj + mtl, 1 = obj, 2 = dae, 3 = stl, 4 = IGES, 5 = iv (currently not working) - if filetype == 0: # OBJ + MTL - import importOBJ - importOBJ.export(objects,filename+".obj") - return self.packFiles(filename,[filename+".obj",filename+".mtl"]) - elif filetype == 1: # OBJ (mesh exporter) - import Mesh - Mesh.export(objects,filename+".obj") - return self.packFiles(filename,[filename+".obj"]) - elif filetype == 2: # DAE - import importDAE - importDAE.export(objects,filename+".dae") - return self.packFiles(filename,[filename+".dae"]) - elif filetype == 3: # STL - import Mesh - Mesh.export(objects,filename+".stl") - return self.packFiles(filename,[filename+".stl"]) - elif filetype == 4: # IGES - import Part - Part.export(objects,filename+".iges") - return self.packFiles(filename,[filename+".iges"]) - elif filetype == 5: # IV - import FreeCADGui - FreeCADGui.export(objects,filename+".iv") - # removing FreeCAD-specific nodes - f = open(filename+".iv","rb") - s = f.read() - f.close() - ver = FreeCAD.Version() - vinfo = "# Exported by FreeCAD v" + ver[0] + "." + ver[1] + " build" + ver[2] + "\n" - vinfo += "# http://www.freecadweb.org\n" - s = s.replace("#Inventor V2.1 ascii","#Inventor V2.1 ascii\n"+vinfo) - s = s.replace("SoBrepEdgeSet","SoIndexedLineSet") - s = s.replace("SoBrepFaceSet","SoIndexedFaceSet") - s = s.replace("\n","--endl--") - s = re.sub("highlightIndex .*?\]"," ",s) - s = re.sub("partIndex .*?\]"," ",s) - s = s.replace("--endl--","\n") - f = open(filename+".iv","wb") - f.write(s) - f.close() - return self.packFiles(filename,[filename+".iv"]) - - def packFiles(self,filename,fileslist): - - for f in fileslist: - if not os.path.exists(f): - return None - z = zipfile.ZipFile(filename+".zip","w") - for f in fileslist: - z.write(f) - z.close() - for f in fileslist: - os.remove(f) - s = os.path.getsize(filename+".zip") - if s > 1048576: - size = str(s >> 20)+" MB" - else: - size = str(s >> 10)+" KB" - return (filename+".zip",size) - - def upload(self): - - if not self.form.Text_Name.text(): - QtGui.QMessageBox.critical(None,translate("Web","Model name is empty"),translate("You must provide a name for your model")) - return - if not self.form.Text_Token.text(): - QtGui.QMessageBox.critical(None,translate("Web","No token provided"),translate("The token is empty. Please press the Obtain button to get your user API token from Sketchfab, then copy / paste the API token to the field below")) - return - FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Web").SetString("SketchfabToken",self.form.Text_Token.text()) - pack = self.saveFile() - if not pack: - QtGui.QMessageBox.critical(None,translate("Web","File packing error"),translate("Unable to save and zip a file for upload")) - return - if os.path.getsize(pack[0]) >= 52428800: - b = QtGui.QMessageBox() - b.setText(translate("Web","Big upload")) - b.setInformativeText(translate("Web","The file to be uploaded is %s, which is above the maximum 50Mb allowed by free Sketchfab accounts. Pro accounts allow for up to 200Mb. Continue?") % pack[1]) - b.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) - b.setDefaultButton(QtGui.QMessageBox.Cancel) - ret = b.exec_() - if ret != QtGui.QMessageBox.Ok: - return - data = { - "name": self.form.Text_Name.text(), - "description": self.form.Text_Description.text(), - "tags": ["freecad"]+[t.strip() for t in self.form.Text_Tags.text().split(",")], - "private": self.form.Check_Private.isChecked(), - "source":"freecad", - } - files = { - "modelFile": open(pack[0], 'rb') - } - self.form.Button_Upload.hide() - # for now this is a fake progress bar, it won't move, just to show the user that the upload is in progress - self.form.ProgressBar.setFormat(translate("Web","Uploading")+" "+pack[1]+"...") - self.form.ProgressBar.show() - QtGui.qApp.processEvents() - try: - r = requests.post(SKETCHFAB_UPLOAD_URL, **self.get_request_payload(self.form.Text_Token.text(), data, files=files)) - except requests.exceptions.RequestException as e: - QtGui.QMessageBox.critical(None,translate("Web","Upload error"),translate("Web","Upload failed:")+" "+str(e)) - self.form.ProgressBar.hide() - self.form.Button_Upload.show() - return - if r.status_code != requests.codes.created: - QtGui.QMessageBox.critical(None,translate("Web","Upload error"),translate("Web","Upload failed:")+" "+str(r.json())) - self.form.ProgressBar.hide() - self.form.Button_Upload.show() - return - self.url = r.headers['Location'] - if self.form.Combo_Filetype.currentIndex() in [0,1,5]: # OBJ format, sketchfab expects inverted Y/Z axes - self.form.ProgressBar.setFormat(translate("Web","Awaiting confirmation...")) - self.form.ProgressBar.setValue(75) - if self.poll(self.url): - self.form.ProgressBar.setFormat(translate("Web","Fixing model...")) - QtGui.qApp.processEvents() - self.patch(self.url) - else: - QtGui.QMessageBox.warning(None,translate("Web","Patch error"),translate("Web","Patching failed. The model was successfully uploaded, but might still require manual adjustments:")) - self.form.ProgressBar.hide() - self.form.Button_View.show() - - def poll(self,url): - - """GET the model endpoint to check the processing status.""" - max_errors = 10 - errors = 0 - retry = 0 - max_retries = 50 - retry_timeout = 5 # seconds - while (retry < max_retries) and (errors < max_errors): - try: - r = requests.get(url, **self.get_request_payload(self.form.Text_Token.text())) - except requests.exceptions.RequestException as e: - print ('Sketchfab: Polling failed with error: ',str(e)) - errors += 1 - retry += 1 - continue - result = r.json() - if "error" in result: - e = result["error"] - else: - e = result - if r.status_code != requests.codes.ok: - print ('Sketchfab: Polling failed with error: ',str(e)) - errors += 1 - retry += 1 - continue - processing_status = result['status']['processing'] - if processing_status == 'PENDING': - retry += 1 - time.sleep(retry_timeout) - continue - elif processing_status == 'PROCESSING': - retry += 1 - time.sleep(retry_timeout) - continue - elif processing_status == 'FAILED': - print ('Sketchfab: Polling failed: ',str(e)) - return False - elif processing_status == 'SUCCEEDED': - return True - retry += 1 - print ('Sketchfab: Stopped polling after too many retries or too many errors') - return False - - def patch(self,url): - - "applies different fixes to the uploaded model" - options_url = os.path.join(url, 'options') - data = { - 'orientation': '{"axis": [1, 0, 0], "angle": 270}' - } - try: - r = requests.patch(options_url, **self.get_request_payload(self.form.Text_Token.text(), data, json_payload=True)) - except requests.exceptions.RequestException as e: - QtGui.QMessageBox.warning(None,translate("Web","Patch error"),translate("Web","Patching failed. The model was successfully uploaded, but might still require manual adjustments:")+" "+str(e)) - else: - if r.status_code != 204: - QtGui.QMessageBox.warning(None,translate("Web","Patch error"),translate("Web","Patching failed. The model was successfully uploaded, but might still require manual adjustments:")+" "+str(r.content)) - - def viewModel(self): - - if self.url: - url = self.url.replace("api","www") - url = url.replace("/v3","") - QtGui.QDesktopServices.openUrl(url) - - - - diff --git a/src/Mod/Web/Webscripts/__init__.py b/src/Mod/Web/Webscripts/__init__.py deleted file mode 100644 index e69de29bb2..0000000000