501 lines
24 KiB
Python
501 lines
24 KiB
Python
#***************************************************************************
|
|
#* *
|
|
#* Copyright (c) 2015 *
|
|
#* Yorik van Havre <yorik@uncreated.net> *
|
|
#* *
|
|
#* 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())
|