This commit is contained in:
452
trunk/freecad/PartsLibrary.FCMacro
Normal file
452
trunk/freecad/PartsLibrary.FCMacro
Normal file
@@ -0,0 +1,452 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#***************************************************************************
|
||||
#* *
|
||||
#* Copyright (c) 2013 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 *
|
||||
#* *
|
||||
#***************************************************************************
|
||||
from __future__ import print_function
|
||||
|
||||
__title__="FreeCAD Parts Library Macro"
|
||||
__author__ = "Yorik van Havre"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
'''
|
||||
FreeCAD Parts Library import macro
|
||||
|
||||
INSTALLATION
|
||||
|
||||
This script is made to be used as a FreeCAD macro, and to be placed
|
||||
inside your macros folder (default is $HOME/.FreeCAD on mac/linux,
|
||||
C:/Users/youruser/Application Data/FreeCAD on windows).
|
||||
|
||||
After it is installed on the above location, it will be available
|
||||
in the macros menu. On first run, it will ask you for the location
|
||||
of your library.
|
||||
|
||||
USAGE
|
||||
|
||||
This macro adds a browser window to the FreeCAD interface, from
|
||||
which you can browse and install items from the library.
|
||||
|
||||
ADVANCED USE
|
||||
|
||||
The update, config, and push buttons all rely on git, and need the
|
||||
python-git package installed. Once that is done, and provided the
|
||||
library is a git repository (ie. you cloned it with git instead of
|
||||
just downloading it), the above mentioned buttons will be enabled.
|
||||
|
||||
The "update" button will simply update your local library with the
|
||||
latest contents from the online repository.
|
||||
|
||||
CONTRIBUTING
|
||||
|
||||
When cloning the official FreeCAD Parts library, you will usually
|
||||
not have write permission to it, and therefore cannot push to it.
|
||||
|
||||
The best way to proceed is, instead of cloning the FreeCAD library
|
||||
directly, to fork it first (for example using the github "fork"
|
||||
button), then clone that foked repo instead, where you will have
|
||||
the correct permissions.
|
||||
|
||||
Once you pushed some contents there, you can make a pull request on
|
||||
the official repo to have it merged.
|
||||
|
||||
If you create a folder named Private in your library, it won't be
|
||||
considered when pushing, so you can place private Parts there.
|
||||
'''
|
||||
|
||||
|
||||
import FreeCAD, FreeCADGui, Part, zipfile, tempfile, Mesh, os, subprocess
|
||||
from PySide import QtGui, QtCore
|
||||
|
||||
param = FreeCAD.ParamGet('User parameter:Plugins/parts_library')
|
||||
s = param.GetString('destination')
|
||||
#print('User parameter:Plugins/partlib : destination : ',s)
|
||||
|
||||
if s:
|
||||
LIBRARYPATH = s
|
||||
else:
|
||||
folderDialog = QtGui.QFileDialog.getExistingDirectory(None,QtGui.QApplication.translate("PartsLibrary", "Location of your existing Parts library", None, QtGui.QApplication.UnicodeUTF8))
|
||||
param.SetString('destination',folderDialog)
|
||||
LIBRARYPATH = param.GetString('destination')
|
||||
|
||||
class ExpFileSystemModel(QtGui.QFileSystemModel):
|
||||
"a custom QFileSystemModel that displays freecad file icons"
|
||||
def __init__(self):
|
||||
QtGui.QFileSystemModel.__init__(self)
|
||||
|
||||
def data(self, index, role):
|
||||
if index.column() == 0 and role == QtCore.Qt.DecorationRole:
|
||||
if index.data().lower().endswith('.fcstd'):
|
||||
return QtGui.QIcon(':icons/freecad-doc.png')
|
||||
elif index.data().lower() == "private":
|
||||
return QtGui.QIcon.fromTheme("folder-lock")
|
||||
return super(ExpFileSystemModel, self).data(index, role)
|
||||
|
||||
class ExpDockWidget(QtGui.QDockWidget):
|
||||
"a library explorer dock widget"
|
||||
|
||||
def __init__(self,LIBRARYPATH):
|
||||
QtGui.QDockWidget.__init__(self)
|
||||
|
||||
self.setObjectName("PartsLibrary")
|
||||
|
||||
# setting up a directory model that shows only fcstd, step and brep
|
||||
self.dirmodel = ExpFileSystemModel()
|
||||
self.dirmodel.setRootPath(LIBRARYPATH)
|
||||
self.dirmodel.setNameFilters(["*.fcstd","*.FcStd","*.FCSTD","*.stp","*.STP","*.step","*.STEP", "*.brp", "*.BRP", "*.brep", "*.BREP"])
|
||||
self.dirmodel.setNameFilterDisables(0)
|
||||
|
||||
self.folder = QtGui.QTreeView()
|
||||
self.folder.setModel(self.dirmodel)
|
||||
self.folder.clicked[QtCore.QModelIndex].connect(self.clicked)
|
||||
self.folder.doubleClicked[QtCore.QModelIndex].connect(self.doubleclicked)
|
||||
# Don't show columns for size, file type, and last modified
|
||||
self.folder.setHeaderHidden(True)
|
||||
self.folder.hideColumn(1)
|
||||
self.folder.hideColumn(2)
|
||||
self.folder.hideColumn(3)
|
||||
self.folder.setRootIndex(self.dirmodel.index(LIBRARYPATH))
|
||||
|
||||
self.preview = QtGui.QLabel()
|
||||
self.preview.setFixedHeight(128)
|
||||
|
||||
self.updatebutton = QtGui.QPushButton()
|
||||
icon = QtGui.QIcon.fromTheme("emblem-synchronizing")
|
||||
self.updatebutton.setIcon(icon)
|
||||
self.updatebutton.clicked.connect(self.updatelibrary)
|
||||
self.updatebutton.hide()
|
||||
|
||||
self.configbutton = QtGui.QPushButton()
|
||||
icon = QtGui.QIcon.fromTheme("emblem-system")
|
||||
self.configbutton.setIcon(icon)
|
||||
self.configbutton.clicked.connect(self.setconfig)
|
||||
self.configbutton.hide()
|
||||
|
||||
self.formatLabel = QtGui.QLabel()
|
||||
self.formatLabel.hide()
|
||||
|
||||
self.savebutton = QtGui.QPushButton()
|
||||
icon = QtGui.QIcon.fromTheme("document-save")
|
||||
self.savebutton.setIcon(icon)
|
||||
self.savebutton.clicked.connect(self.addtolibrary)
|
||||
self.savebutton.hide()
|
||||
|
||||
self.pushbutton = QtGui.QPushButton()
|
||||
icon = QtGui.QIcon.fromTheme("document-export")
|
||||
self.pushbutton.setIcon(icon)
|
||||
self.pushbutton.clicked.connect(self.pushlibrary)
|
||||
self.pushbutton.hide()
|
||||
|
||||
self.prevbutton = QtGui.QPushButton()
|
||||
self.prevbutton.clicked.connect(self.showpreview)
|
||||
self.prevbutton.setStyleSheet("text-align: left;")
|
||||
|
||||
self.optbutton = QtGui.QPushButton()
|
||||
self.optbutton.clicked.connect(self.showoptions)
|
||||
self.optbutton.setStyleSheet("text-align: left;")
|
||||
|
||||
self.fcstdCB = QtGui.QCheckBox('FCStd')
|
||||
self.fcstdCB.setCheckState(QtCore.Qt.Checked)
|
||||
self.fcstdCB.setEnabled(False)
|
||||
self.fcstdCB.hide()
|
||||
self.stepCB = QtGui.QCheckBox('STEP')
|
||||
self.stepCB.setCheckState(QtCore.Qt.Checked)
|
||||
self.stepCB.hide()
|
||||
self.stlCB = QtGui.QCheckBox('STL')
|
||||
self.stlCB.setCheckState(QtCore.Qt.Checked)
|
||||
self.stlCB.hide()
|
||||
|
||||
container = QtGui.QWidget()
|
||||
grid = QtGui.QGridLayout()
|
||||
grid.setSpacing(10)
|
||||
|
||||
grid.addWidget(self.folder,0,0,1,2)
|
||||
grid.addWidget(self.prevbutton,1,0,1,2)
|
||||
grid.addWidget(self.preview,2,0,1,2)
|
||||
grid.addWidget(self.optbutton,3,0,1,2)
|
||||
|
||||
grid.addWidget(self.updatebutton,4,0,1,1)
|
||||
grid.addWidget(self.configbutton,4,1,1,1)
|
||||
grid.addWidget(self.formatLabel,5,0,1,2)
|
||||
grid.addWidget(self.fcstdCB,6,0,1,2)
|
||||
grid.addWidget(self.stepCB,7,0,1,2)
|
||||
grid.addWidget(self.stlCB,8,0,1,2)
|
||||
grid.addWidget(self.savebutton,9,0,1,1)
|
||||
grid.addWidget(self.pushbutton,9,1,1,1)
|
||||
|
||||
global repo
|
||||
repo = None
|
||||
try:
|
||||
import git
|
||||
except:
|
||||
FreeCAD.Console.PrintWarning("python-git not found. Git-related functions will be disabled\n")
|
||||
else:
|
||||
try:
|
||||
repo = git.Repo(LIBRARYPATH)
|
||||
except:
|
||||
FreeCAD.Console.PrintWarning("Your library is not a valid Git repository. Git-related functions will be disabled\n")
|
||||
else:
|
||||
if not repo.remotes:
|
||||
FreeCAD.Console.PrintWarning("No remote repository set. Git-related functions will be disabled\n")
|
||||
repo = None
|
||||
if not repo:
|
||||
self.updatebutton.setEnabled(False)
|
||||
#self.configbutton.setEnabled(False)
|
||||
self.pushbutton.setEnabled(False)
|
||||
|
||||
self.retranslateUi()
|
||||
container.setLayout(grid)
|
||||
self.setWidget(container)
|
||||
|
||||
def retranslateUi(self):
|
||||
self.setWindowTitle(QtGui.QApplication.translate("PartsLibrary", "Parts Library", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.updatebutton.setText(QtGui.QApplication.translate("PartsLibrary", "Update from Git", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.configbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Config", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.formatLabel.setText(QtGui.QApplication.translate("PartsLibrary", "Add to library", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.savebutton.setText(QtGui.QApplication.translate("PartsLibrary", "Save", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pushbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Push to Git", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.optbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Options ⏷", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.prevbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Preview ⏶", None, QtGui.QApplication.UnicodeUTF8))
|
||||
|
||||
def clicked(self, index):
|
||||
path = self.dirmodel.filePath(index)
|
||||
if path.lower().endswith(".fcstd"):
|
||||
zfile=zipfile.ZipFile(path)
|
||||
files=zfile.namelist()
|
||||
# check for meta-file if it's really a FreeCAD document
|
||||
if files[0] == "Document.xml":
|
||||
image="thumbnails/Thumbnail.png"
|
||||
if image in files:
|
||||
image=zfile.read(image)
|
||||
thumbfile = tempfile.mkstemp(suffix='.png')[1]
|
||||
thumb = open(thumbfile,"wb")
|
||||
thumb.write(image)
|
||||
thumb.close()
|
||||
im = QtGui.QPixmap(thumbfile)
|
||||
self.preview.setPixmap(im)
|
||||
return
|
||||
self.preview.clear()
|
||||
|
||||
def doubleclicked(self, index):
|
||||
path = self.dirmodel.filePath(index)
|
||||
if path.lower().endswith(".stp") or path.lower().endswith(".step") or path.lower().endswith(".brp") or path.lower().endswith(".brep"):
|
||||
Part.show(Part.read(path))
|
||||
elif path.lower().endswith(".fcstd"):
|
||||
FreeCADGui.ActiveDocument.mergeProject(path)
|
||||
FreeCADGui.SendMsgToActiveView("ViewFit")
|
||||
|
||||
def addtolibrary(self):
|
||||
fileDialog = QtGui.QFileDialog.getSaveFileName(None,u"Choose category and set a filename without extension", LIBRARYPATH)
|
||||
if fileDialog != '':
|
||||
#filename = fileDialog[0].split("/")[-1]
|
||||
#if filename.split(".")[-1].lowercase == "fcstd" or "stl
|
||||
FCfilename = fileDialog[0] + ".fcstd"
|
||||
FreeCAD.ActiveDocument.saveCopy(FCfilename)
|
||||
if self.stepCB.isChecked() or self.stlCB.isChecked():
|
||||
toexport = []
|
||||
objs = FreeCAD.ActiveDocument.Objects
|
||||
for obj in objs :
|
||||
if obj.ViewObject.Visibility == True :
|
||||
toexport.append(obj)
|
||||
if self.stepCB.isChecked() :
|
||||
STEPfilename = fileDialog[0] + ".step"
|
||||
Part.export(toexport,STEPfilename)
|
||||
if self.stlCB.isChecked() :
|
||||
STLfilename = fileDialog[0] + ".stl"
|
||||
Mesh.export(toexport,STLfilename)
|
||||
|
||||
def pushlibrary(self):
|
||||
modified_files = [f for f in repo.git.diff("--name-only").split("\n") if (f and (f != 'PartsLibrary.FCMacro'))]
|
||||
#print(modified_files)
|
||||
untracked_files = [f for f in repo.git.ls_files("--other","--exclude-standard").split("\n") if f]
|
||||
#print(untracked_files)
|
||||
import ArchServer
|
||||
d = ArchServer._ArchGitDialog()
|
||||
d.label.setText(str(len(modified_files)+len(untracked_files))+" new and modified file(s)")
|
||||
d.lineEdit.setText("Changed " + str(modified_files))
|
||||
d.checkBox.hide()
|
||||
d.radioButton.hide()
|
||||
d.radioButton_2.hide()
|
||||
r = d.exec_()
|
||||
if r:
|
||||
for o in modified_files + untracked_files:
|
||||
repo.git.add(o)
|
||||
repo.git.commit(m=d.lineEdit.text())
|
||||
if d.checkBox.isChecked():
|
||||
repo.git.push()
|
||||
|
||||
def updatelibrary(self):
|
||||
repo.git.pull()
|
||||
|
||||
def setconfig(self):
|
||||
d = ConfigDialog()
|
||||
if repo:
|
||||
d.lineEdit.setText(repo.remote().url)
|
||||
if hasattr(repo.remote(),"pushurl"):
|
||||
d.lineEdit_2.setText(repo.remote().pushurl)
|
||||
else:
|
||||
d.lineEdit_2.setText(repo.remote().url)
|
||||
else:
|
||||
d.groupBox.setEnabled(False)
|
||||
d.groupBox_2.setEnabled(False)
|
||||
r = d.exec_()
|
||||
|
||||
def showoptions(self):
|
||||
controls = [self.updatebutton,self.configbutton,self.formatLabel,
|
||||
self.fcstdCB,self.stepCB,self.stlCB,self.savebutton,self.pushbutton]
|
||||
tree = [self.preview]
|
||||
if self.updatebutton.isVisible():
|
||||
for c in controls:
|
||||
c.hide()
|
||||
for c in tree:
|
||||
c.show()
|
||||
self.optbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Options ⏷", None, QtGui.QApplication.UnicodeUTF8))
|
||||
else:
|
||||
for c in controls:
|
||||
c.show()
|
||||
for c in tree:
|
||||
c.hide()
|
||||
self.optbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Options ⏶", None, QtGui.QApplication.UnicodeUTF8))
|
||||
|
||||
def showpreview(self):
|
||||
if self.preview.isVisible():
|
||||
self.preview.hide()
|
||||
self.prevbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Preview ⏷", None, QtGui.QApplication.UnicodeUTF8))
|
||||
else:
|
||||
self.preview.show()
|
||||
self.prevbutton.setText(QtGui.QApplication.translate("PartsLibrary", "Preview ⏶", None, QtGui.QApplication.UnicodeUTF8))
|
||||
|
||||
|
||||
|
||||
class ConfigDialog(QtGui.QDialog):
|
||||
def __init__(self):
|
||||
QtGui.QDialog.__init__(self)
|
||||
self.setObjectName("GitConfig")
|
||||
self.resize(420, 250)
|
||||
self.verticalLayout = QtGui.QVBoxLayout(self)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
|
||||
self.groupBox_3 = QtGui.QGroupBox(self)
|
||||
self.groupBox_3.setObjectName("groupBox_3")
|
||||
self.horizontalLayout_3 = QtGui.QHBoxLayout(self.groupBox_3)
|
||||
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
|
||||
self.lineEdit_3 = QtGui.QLineEdit(self.groupBox_3)
|
||||
self.lineEdit_3.setObjectName("lineEdit_3")
|
||||
self.horizontalLayout_3.addWidget(self.lineEdit_3)
|
||||
self.pushButton_3 = QtGui.QPushButton(self.groupBox_3)
|
||||
self.pushButton_3.setObjectName("pushButton_3")
|
||||
self.horizontalLayout_3.addWidget(self.pushButton_3)
|
||||
self.verticalLayout.addWidget(self.groupBox_3)
|
||||
|
||||
self.groupBox = QtGui.QGroupBox(self)
|
||||
self.groupBox.setObjectName("groupBox")
|
||||
self.horizontalLayout = QtGui.QHBoxLayout(self.groupBox)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.lineEdit = QtGui.QLineEdit(self.groupBox)
|
||||
self.lineEdit.setObjectName("lineEdit")
|
||||
self.horizontalLayout.addWidget(self.lineEdit)
|
||||
self.pushButton = QtGui.QPushButton(self.groupBox)
|
||||
self.pushButton.setObjectName("pushButton")
|
||||
self.horizontalLayout.addWidget(self.pushButton)
|
||||
self.verticalLayout.addWidget(self.groupBox)
|
||||
|
||||
self.groupBox_2 = QtGui.QGroupBox(self)
|
||||
self.groupBox_2.setObjectName("groupBox_2")
|
||||
self.verticalLayout_2 = QtGui.QVBoxLayout(self.groupBox_2)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.lineEdit_2 = QtGui.QLineEdit(self.groupBox_2)
|
||||
self.lineEdit_2.setObjectName("lineEdit_2")
|
||||
self.verticalLayout_2.addWidget(self.lineEdit_2)
|
||||
self.label = QtGui.QLabel(self.groupBox_2)
|
||||
self.label.setObjectName("label")
|
||||
self.verticalLayout_2.addWidget(self.label)
|
||||
self.verticalLayout.addWidget(self.groupBox_2)
|
||||
|
||||
self.buttonBox = QtGui.QDialogButtonBox(self)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.verticalLayout.addWidget(self.buttonBox)
|
||||
|
||||
self.retranslateUi()
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), self.accept)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), self.reject)
|
||||
QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL("clicked()"), self.setdefaulturl)
|
||||
QtCore.QObject.connect(self.pushButton_3, QtCore.SIGNAL("clicked()"), self.changepath)
|
||||
QtCore.QMetaObject.connectSlotsByName(self)
|
||||
|
||||
librarypath = FreeCAD.ParamGet('User parameter:Plugins/parts_library').GetString('destination','')
|
||||
self.lineEdit_3.setText(librarypath)
|
||||
|
||||
def retranslateUi(self):
|
||||
self.setWindowTitle(QtGui.QApplication.translate("PartsLibrary", "Parts library configuration", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.groupBox.setTitle(QtGui.QApplication.translate("PartsLibrary", "Pull server (where you get your updates from)", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.lineEdit.setToolTip(QtGui.QApplication.translate("PartsLibrary", "Enter the URL of the pull server here", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pushButton.setToolTip(QtGui.QApplication.translate("PartsLibrary", "Use the official FreeCAD-library repository", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pushButton.setText(QtGui.QApplication.translate("PartsLibrary", "use official", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.groupBox_2.setTitle(QtGui.QApplication.translate("PartsLibrary", "Push server (where you push your changes to)", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.lineEdit_2.setToolTip(QtGui.QApplication.translate("PartsLibrary", "Enter the URL of the push server here", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.label.setText(QtGui.QApplication.translate("PartsLibrary", "Warning: You need write permission on this server", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.groupBox_3.setTitle(QtGui.QApplication.translate("PartsLibrary", "Library path", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.lineEdit_3.setToolTip(QtGui.QApplication.translate("PartsLibrary", "Enter the path to your parts library", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pushButton_3.setToolTip(QtGui.QApplication.translate("PartsLibrary", "Browse to your path library", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pushButton_3.setText(QtGui.QApplication.translate("PartsLibrary", "...", None, QtGui.QApplication.UnicodeUTF8))
|
||||
|
||||
def setdefaulturl(self):
|
||||
self.lineEdit.setText("https://github.com/FreeCAD/FreeCAD-library.git")
|
||||
|
||||
def changepath(self):
|
||||
librarypath = FreeCAD.ParamGet('User parameter:Plugins/parts_library').GetString('destination','')
|
||||
np = QtGui.QFileDialog.getExistingDirectory(self,"Location of your existing Parts library",librarypath)
|
||||
if np:
|
||||
self.lineEdit_3.setText(np)
|
||||
|
||||
def accept(self):
|
||||
if repo:
|
||||
cw = repo.remote().config_writer
|
||||
if self.lineEdit.text():
|
||||
cw.set("url", str(self.lineEdit.text()))
|
||||
if self.lineEdit_2.text():
|
||||
cw.set("pushurl", str(self.lineEdit_2.text()))
|
||||
if hasattr(cw,"release"):
|
||||
cw.release()
|
||||
if self.lineEdit_3.text():
|
||||
FreeCAD.ParamGet('User parameter:Plugins/parts_library').SetString('destination',self.lineEdit_3.text())
|
||||
QtGui.QDialog.accept(self)
|
||||
|
||||
if QtCore.QDir(LIBRARYPATH).exists():
|
||||
m = FreeCADGui.getMainWindow()
|
||||
w = m.findChild(QtGui.QDockWidget,"PartsLibrary")
|
||||
if w:
|
||||
if hasattr(w,"isVisible"):
|
||||
if w.isVisible():
|
||||
w.hide()
|
||||
else:
|
||||
w.show()
|
||||
else:
|
||||
# something went wrong with our widget... Recreate it
|
||||
del w
|
||||
m.addDockWidget(QtCore.Qt.RightDockWidgetArea,ExpDockWidget(LIBRARYPATH))
|
||||
else:
|
||||
m.addDockWidget(QtCore.Qt.RightDockWidgetArea,ExpDockWidget(LIBRARYPATH))
|
||||
else:
|
||||
print("Library path ", LIBRARYPATH, "not found.")
|
||||
35
trunk/freecad/contenitore.py
Normal file
35
trunk/freecad/contenitore.py
Normal file
@@ -0,0 +1,35 @@
|
||||
import FreeCAD as App
|
||||
import FreeCADGui
|
||||
import FreeCAD
|
||||
import Part
|
||||
import math
|
||||
|
||||
class Contenitore:
|
||||
def __init__(self,obj, unitsX=20, unitsY=30,unitsZ=3):
|
||||
obj.addProperty("App::PropertyFloat","unitsX","Box","Size in X direction.").unitsX = unitsX
|
||||
obj.addProperty("App::PropertyFloat","unitsY","Box","Size in Y direction.").unitsY = unitsY
|
||||
obj.addProperty("App::PropertyFloat","unitsZ","Box","Size in Z direction.").unitsZ = unitsZ
|
||||
obj.Proxy = self
|
||||
|
||||
def execute(self, fp):
|
||||
'''Print a short message when doing a recomputation, this method is mandatory'''
|
||||
fp.Shape = Contenitore.buildshape(fp.unitsX, fp.unitsY, fp.unitsZ)
|
||||
|
||||
@staticmethod
|
||||
def buildshape( unitsX, unitsY, unitsZ):
|
||||
wall=1.5
|
||||
|
||||
# box
|
||||
l=unitsX
|
||||
w=unitsY
|
||||
height=unitsZ
|
||||
c1=Part.makeBox(l, w, height,FreeCAD.Vector(-l/2.0,-w/2.0,0))
|
||||
c2=Part.makeBox(l+2*wall, w+2*wall, height+wall,FreeCAD.Vector(-(l+2*wall)/2.0,-(w+2*wall)/2.0,-wall))
|
||||
d1=c2.cut(c1)
|
||||
return d1
|
||||
|
||||
|
||||
a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Box")
|
||||
Contenitore(a)
|
||||
a.ViewObject.Proxy=0 # just set it to something different from None (this assignment is needed to run an internal notification)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
102
trunk/freecad/lego.py
Normal file
102
trunk/freecad/lego.py
Normal file
@@ -0,0 +1,102 @@
|
||||
import FreeCAD as App
|
||||
import FreeCADGui
|
||||
import FreeCAD
|
||||
import Part
|
||||
import math
|
||||
|
||||
class Lego:
|
||||
def __init__(self,obj, unitsX=4, unitsY=2,unitsZ=1,modifier=1):
|
||||
obj.addProperty("App::PropertyInteger","unitsX","Lego","Size in knobs in X direction.").unitsX = unitsX
|
||||
obj.addProperty("App::PropertyInteger","unitsY","Lego","Size in knobs in Y direction.").unitsY = unitsY
|
||||
obj.addProperty("App::PropertyInteger","unitsZ","Lego","Size in knobs in Z direction.").unitsZ = unitsZ
|
||||
obj.addProperty("App::PropertyInteger","modifier","Lego","Variant No ").modifier = modifier
|
||||
obj.Proxy = self
|
||||
|
||||
def execute(self, fp):
|
||||
'''Print a short message when doing a recomputation, this method is mandatory'''
|
||||
fp.Shape = Lego.buildshape(fp.unitsX, fp.unitsY, fp.unitsZ, fp.modifier)
|
||||
|
||||
@staticmethod
|
||||
def buildshape( unitsX, unitsY, unitsZ, modifier):
|
||||
gap=0.1
|
||||
gaps=2*gap
|
||||
unitSize = 8
|
||||
height_U=3.2 # 9.6
|
||||
knobHeight=1.8
|
||||
knobRadius=4.9/2
|
||||
wall=1.35 # 1.5 guessed
|
||||
upWall=1.2 # 5.5 guessed
|
||||
supportthickness=0.6 # 0.15x4 or 0.20x3
|
||||
maxsupportlayerthickness=0.15
|
||||
supportdistance=4 # 4x4=16mm^2, printer option
|
||||
cylRadius = (unitSize*math.sqrt(2)-2*knobRadius)/2 #0000003,2568542494923801952067548968388
|
||||
#cylWall = round(3.25685,5)
|
||||
cylWall = 0.8
|
||||
|
||||
# box
|
||||
l=unitSize*unitsX-gaps
|
||||
w=unitSize*unitsY-gaps
|
||||
height=height_U*unitsZ
|
||||
c1=Part.makeBox(l, w, height,FreeCAD.Vector(-l/2.0,-w/2.0,0))
|
||||
c2=Part.makeBox(l-gaps-2*wall, w-gaps-2*wall, height,FreeCAD.Vector(-(l-gaps-2*wall)/2.0,-(w-gaps-2*wall)/2.0,-1*upWall))
|
||||
d1=c1.cut(c2)
|
||||
shape1=d1
|
||||
|
||||
# knobs
|
||||
knobs=Part.Shape()
|
||||
knob=Part.makeCylinder(knobRadius,knobHeight+upWall/2,FreeCAD.Vector(0,0,height-upWall/2.0))
|
||||
for x in range(unitsX):
|
||||
for y in range(unitsY):
|
||||
newknob=knob.copy()
|
||||
newknob.translate((x*unitSize, y*unitSize, 0))
|
||||
if knobs.isNull():
|
||||
knobs=newknob
|
||||
else:
|
||||
knobs=knobs.fuse(newknob)
|
||||
knobs.translate(((1-unitsX)*unitSize/2, (1-unitsY)*unitSize/2, 0))
|
||||
|
||||
# Cylinder
|
||||
if ((unitsX > 1) and (unitsY > 1)):
|
||||
cyl=Part.makeCylinder(cylRadius,height-upWall/2).cut(Part.makeCylinder(cylRadius-cylWall,height))
|
||||
cyl.translate((0,0,0))#upWall/8))
|
||||
cyls=Part.Shape()
|
||||
for x in range(unitsX-1):
|
||||
for y in range(unitsY-1):
|
||||
newcyl=cyl.copy()
|
||||
newcyl.translate((x*unitSize, y*unitSize, 0))
|
||||
if cyls.isNull():
|
||||
cyls=newcyl
|
||||
else:
|
||||
cyls=cyls.fuse(newcyl)
|
||||
cyls.translate(((2-unitsX)*unitSize/2, (2-unitsY)*unitSize/2, 0))
|
||||
|
||||
# Modifier bits:
|
||||
# 0.. 0: flat; 1: with knobs
|
||||
# 1.. 0: flat; 1: with cylinders on the bottom site
|
||||
# 2.. 0:
|
||||
# 3.. 0:
|
||||
# 4.. 0:
|
||||
# 5.. 0:
|
||||
# 6.. 0:
|
||||
# 7.. 0:
|
||||
|
||||
if (modifier & 1) == 0: # Without knobs
|
||||
pass
|
||||
|
||||
if (modifier & 1) == 1: # With knobs
|
||||
newknobs=knobs.copy()
|
||||
#newknobs.translate((0,0,0))
|
||||
shape1=shape1.fuse(newknobs)
|
||||
|
||||
if (modifier & 2) == 0:
|
||||
pass
|
||||
|
||||
if (modifier & 2) == 2:
|
||||
shape1=shape1.fuse(cyls)
|
||||
|
||||
return shape1
|
||||
|
||||
a=FreeCAD.ActiveDocument.addObject("Part::FeaturePython","Lego")
|
||||
Lego(a)
|
||||
a.ViewObject.Proxy=0 # just set it to something different from None (this assignment is needed to run an internal notification)
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
2
trunk/freecad/start_bolts.FCMacro
Normal file
2
trunk/freecad/start_bolts.FCMacro
Normal file
@@ -0,0 +1,2 @@
|
||||
import BOLTS
|
||||
BOLTS.show_widget()
|
||||
Reference in New Issue
Block a user