Turned the spreadsheet into a FreeCAD object
This commit is contained in:
parent
3a64a9db8a
commit
7f1044a9bb
|
@ -20,6 +20,56 @@
|
|||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
import Spreadsheet_rc
|
||||
class SpreadsheetWorkbench(Workbench):
|
||||
"Spreadsheet workbench object"
|
||||
Icon = """
|
||||
/* XPM */
|
||||
static char * Spreadsheet_xpm[] = {
|
||||
"16 16 5 1",
|
||||
" c None",
|
||||
". c #151614",
|
||||
"+ c #575956",
|
||||
"@ c #969895",
|
||||
"# c #F7F9F6",
|
||||
" ",
|
||||
" ",
|
||||
" ...............",
|
||||
".@##@+########@.",
|
||||
".+@@+.@@@@@@@@+.",
|
||||
"..+++.+++++++++.",
|
||||
".@##@+########@.",
|
||||
".+@@+.@@@@@@@@+.",
|
||||
"..+++.+++++++++.",
|
||||
".@##@+########@.",
|
||||
".+@@+.@@@@@@@@+.",
|
||||
"..+++.+++++++++.",
|
||||
".@##@+########@.",
|
||||
"..+++.+++++++++.",
|
||||
" ",
|
||||
" "};"""
|
||||
|
||||
MenuText = "Spreadsheet"
|
||||
ToolTip = "Spreadsheet workbench"
|
||||
|
||||
def Initialize(self):
|
||||
import Spreadsheet,Spreadsheet_rc
|
||||
from DraftTools import translate
|
||||
commands = ["Spreadsheet_Create"]
|
||||
self.appendToolbar(str(translate("Spreadsheet","Spreadsheet tools")),commands)
|
||||
self.appendMenu(str(translate("Spreadsheet","&Spreadsheet")),commands)
|
||||
FreeCADGui.addIconPath(":/icons")
|
||||
FreeCADGui.addLanguagePath(":/translations")
|
||||
Log ('Loading Spreadsheet module... done\n')
|
||||
|
||||
def Activated(self):
|
||||
Msg("Spreadsheet workbench activated\n")
|
||||
|
||||
def Deactivated(self):
|
||||
Msg("Spreadsheet workbench deactivated\n")
|
||||
|
||||
def GetClassName(self):
|
||||
return "Gui::PythonWorkbench"
|
||||
|
||||
FreeCADGui.addWorkbench(SpreadsheetWorkbench)
|
||||
|
||||
|
||||
|
|
|
@ -20,36 +20,33 @@
|
|||
#* *
|
||||
#***************************************************************************
|
||||
|
||||
import re, math
|
||||
import re, math, FreeCAD, FreeCADGui
|
||||
from PyQt4 import QtCore,QtGui
|
||||
from DraftTools import translate
|
||||
|
||||
class Spreadsheet(object):
|
||||
"A spreadsheet object"
|
||||
"""An object representing a spreadsheet. Can be used as a
|
||||
FreeCAD object or as a standalone python object.
|
||||
Cells of the spreadsheet can be got/set as arguments, as:
|
||||
|
||||
myspreadsheet.a1 = 54
|
||||
print(myspreadsheet.a1)
|
||||
myspreadsheet.a2 = "My text"
|
||||
myspreadsheet.b1 = "=a1*3"
|
||||
print(myspreadsheet.a3)
|
||||
|
||||
Functions usable in formulae are limited to the contents of
|
||||
the math module."""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self,obj=None):
|
||||
if obj:
|
||||
obj.Proxy = self
|
||||
self._cells = {}
|
||||
# a list of safe functions to allow
|
||||
safe_list = ['acos', 'asin', 'atan', 'atan2', 'ceil',
|
||||
'cos', 'cosh', 'e', 'exp', 'fabs',
|
||||
'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log',
|
||||
'log10', 'modf', 'pi', 'pow', 'radians', 'sin',
|
||||
'sinh', 'sqrt', 'tan', 'tanh']
|
||||
self._tools = dict((k, getattr(math, k)) for k in safe_list)
|
||||
# adding abs
|
||||
self._tools["abs"] = abs
|
||||
# removing all builtins from allowed functions
|
||||
self._tools["__builtins__"] = None
|
||||
self._relations = {}
|
||||
self.cols = []
|
||||
self.rows = []
|
||||
|
||||
def __repr__(self):
|
||||
return "Spreadsheet object containing " + str(len(self._cells)) + " cells"
|
||||
|
||||
def allowedFunctions(self):
|
||||
"returns a list of allowed functions in cells"
|
||||
return self.tools.keys()
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
#print "setting key:",key," to value:",value
|
||||
|
@ -58,7 +55,7 @@ class Spreadsheet(object):
|
|||
if value:
|
||||
if self.isFunction(value):
|
||||
self._updateDependencies(key,value)
|
||||
c,r = splitKey(key)
|
||||
c,r = self.splitKey(key)
|
||||
if not c in self.cols:
|
||||
self.cols.append(c)
|
||||
self.cols.sort()
|
||||
|
@ -67,17 +64,42 @@ class Spreadsheet(object):
|
|||
self.rows.sort()
|
||||
else:
|
||||
self.__dict__.__setitem__(key,value)
|
||||
|
||||
|
||||
def __getattr__(self, key):
|
||||
if key in self._cells:
|
||||
if self.isFunction(self._cells[key]):
|
||||
#print "result = ",self.getFunction(key)
|
||||
return eval(self._format(key),self._tools,{"self":self})
|
||||
# building a list of safe functions allowed in eval
|
||||
safe_list = ['acos', 'asin', 'atan', 'atan2', 'ceil',
|
||||
'cos', 'cosh', 'e', 'exp', 'fabs',
|
||||
'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log',
|
||||
'log10', 'modf', 'pi', 'pow', 'radians', 'sin',
|
||||
'sinh', 'sqrt', 'tan', 'tanh']
|
||||
tools = dict((k, getattr(math, k)) for k in safe_list)
|
||||
# adding abs
|
||||
tools["abs"] = abs
|
||||
# removing all builtins from allowed functions
|
||||
tools["__builtins__"] = None
|
||||
try:
|
||||
e = eval(self._format(key),tools,{"self":self})
|
||||
except:
|
||||
print "Error evaluating formula"
|
||||
return self._cells[key]
|
||||
else:
|
||||
return e
|
||||
else:
|
||||
return self._cells[key]
|
||||
else:
|
||||
return None
|
||||
|
||||
def __getstate__(self):
|
||||
return self._cells
|
||||
|
||||
def __setstate__(self,state):
|
||||
if state:
|
||||
self._cells = state
|
||||
# TODO rebuild rows, cols and _relations
|
||||
|
||||
def _format(self,key):
|
||||
"formats all cellnames in the function a the given cell"
|
||||
elts = re.split(r'(\W+)',self._cells[key][1:])
|
||||
|
@ -102,7 +124,10 @@ class Spreadsheet(object):
|
|||
self._relations[a].append(key)
|
||||
else:
|
||||
self._relations[a] = [key]
|
||||
|
||||
|
||||
def execute(self,obj=None):
|
||||
pass
|
||||
|
||||
def isFunction(self,key):
|
||||
"isFunction(cell): returns True if the given cell or value is a function"
|
||||
if key in self._cells:
|
||||
|
@ -138,7 +163,7 @@ class Spreadsheet(object):
|
|||
if not nu:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def splitKey(self,key):
|
||||
"splitKey(cell): splits a key between column and row"
|
||||
c = ''
|
||||
|
@ -149,18 +174,18 @@ class Spreadsheet(object):
|
|||
else:
|
||||
r += ch
|
||||
return c,r
|
||||
|
||||
|
||||
def getFunction(self,key):
|
||||
"getFunction(cell): returns the function contained in the given cell, instead of the value"
|
||||
if key in self._cells:
|
||||
return self._cells[key]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def getSize(self):
|
||||
"getSize(): returns a tuple with number of columns and rows of this spreadsheet"
|
||||
return (len(self.columns),len(self.rows))
|
||||
|
||||
|
||||
def getCells(self,index):
|
||||
"getCells(index): returns the cells from the given column of row number"
|
||||
cells = {}
|
||||
|
@ -169,34 +194,106 @@ class Spreadsheet(object):
|
|||
if index in [c,r]:
|
||||
cells[k] = self._cells[k]
|
||||
return cells
|
||||
|
||||
|
||||
|
||||
class ViewProviderSpreadsheet(object):
|
||||
def __init__(self, vobj):
|
||||
vobj.Proxy = self
|
||||
|
||||
def getIcon(self):
|
||||
import Spreadsheet_rc
|
||||
return ":/icons/Spreadsheet.svg"
|
||||
|
||||
def __getstate__(self):
|
||||
return None
|
||||
|
||||
def __setstate__(self,state):
|
||||
return None
|
||||
|
||||
def getDisplayModes(self,vobj):
|
||||
return ["None"]
|
||||
|
||||
def getDefaultDisplayMode(self):
|
||||
return "None"
|
||||
|
||||
def setDisplayMode(self,mode):
|
||||
return mode
|
||||
|
||||
def setEdit(self,vobj,mode):
|
||||
if hasattr(self,"editor"):
|
||||
pass
|
||||
else:
|
||||
#FreeCADGui.Control.showDialog(SpreadsheetTaskPanel())
|
||||
self.editor = SpreadsheetView(vobj.Object)
|
||||
addSpreadsheetView(self.editor)
|
||||
return True
|
||||
|
||||
def unsetEdit(self,vobj,mode):
|
||||
#FreeCADGui.Control.closeDialog()
|
||||
return False
|
||||
|
||||
|
||||
class SpreadsheetView(QtGui.QWidget):
|
||||
"A spreadsheet viewer for FreeCAD"
|
||||
|
||||
def __init__(self):
|
||||
|
||||
def __init__(self,spreadsheet=None):
|
||||
from DraftTools import translate
|
||||
QtGui.QWidget.__init__(self)
|
||||
self.setWindowIcon(QtGui.QIcon(":/icons/Spreadsheet.svg"))
|
||||
self.setWindowTitle(str(translate("Spreadsheet","Spreadsheet")))
|
||||
self.setObjectName("Spreadsheet viewer")
|
||||
self.verticalLayout = QtGui.QVBoxLayout(self)
|
||||
|
||||
# add editor line
|
||||
self.horizontalLayout = QtGui.QHBoxLayout()
|
||||
self.label = QtGui.QLabel(self)
|
||||
self.label.setMinimumSize(QtCore.QSize(82, 0))
|
||||
self.label.setText(str(translate("Spreadsheet","Cell"))+":")
|
||||
self.horizontalLayout.addWidget(self.label)
|
||||
self.lineEdit = QtGui.QLineEdit(self)
|
||||
self.horizontalLayout.addWidget(self.lineEdit)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||
|
||||
# add table
|
||||
self.table = QtGui.QTableWidget(30,26,self)
|
||||
for i in range(26):
|
||||
ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i]
|
||||
self.table.setHorizontalHeaderItem(i, QtGui.QTableWidgetItem(ch))
|
||||
self.verticalLayout.addWidget(self.table)
|
||||
self.spreadsheet = None
|
||||
self.spreadsheet = spreadsheet
|
||||
self.update()
|
||||
|
||||
QtCore.QObject.connect(self.table, QtCore.SIGNAL("cellChanged(int,int)"), self.changeCell)
|
||||
|
||||
QtCore.QObject.connect(self.table, QtCore.SIGNAL("currentCellChanged(int,int,int,int)"), self.activeCell)
|
||||
|
||||
def __del__(self):
|
||||
if self.spreadsheet:
|
||||
if hasattr(self.spreadsheet,"ViewObject"):
|
||||
if self.spreadsheet.ViewObject:
|
||||
if hasattr(self.spreadsheet.ViewObject,"editor"):
|
||||
del self.spreadsheet.ViewObject.editor
|
||||
|
||||
def update(self):
|
||||
"fills the cells with the contents of the spreadsheet"
|
||||
if self.spreadsheet:
|
||||
for cell in self.spreadsheet.Proxy._cells.keys():
|
||||
c,r = self.spreadsheet.Proxy.splitKey(cell)
|
||||
c = "abcdefghijklmnopqrstuvwxyz".index(c)
|
||||
r = r-1
|
||||
self.table.item(r,c).setText(getattr(self.spreadsheet.Proxy,cell))
|
||||
|
||||
def changeCell(self,r,c):
|
||||
"changes the contens of a cell"
|
||||
key = "abcdefghijklmnopqrstuvwxyz"[c]+str(r+1)
|
||||
value = self.table.item(r,c).text()
|
||||
print "Changing "+key+" to "+value
|
||||
if self.spreadsheet:
|
||||
setattr(self.spreadsheet,key,value)
|
||||
|
||||
setattr(self.spreadsheet.Proxy,key,value)
|
||||
|
||||
def activeCell(self,r,c,or,oc):
|
||||
"sets the contents of the active cell to the header"
|
||||
print "setting cell ",r,c
|
||||
|
||||
def clear(self):
|
||||
"clears the spreadsheet"
|
||||
for r in range(self.table.columnCount):
|
||||
|
@ -204,10 +301,35 @@ class SpreadsheetView(QtGui.QWidget):
|
|||
self.table.item(r,c).setText("")
|
||||
|
||||
|
||||
class _CommandSpreadsheet:
|
||||
"the Spreadsheet FreeCAD command"
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Spreadsheet',
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Spreadsheet_Create","Spreadsheet"),
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Spreadsheet_Create","Adds a spreadsheet object to the active document")}
|
||||
|
||||
def Activated(self):
|
||||
from DraftTools import translate
|
||||
FreeCAD.ActiveDocument.openTransaction(str(translate("Arch","Create Spreadsheet")))
|
||||
FreeCADGui.doCommand("import Spreadsheet")
|
||||
FreeCADGui.doCommand("Spreadsheet.makeSpreadsheet()")
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
|
||||
|
||||
def makeSpreadsheet():
|
||||
"makeSpreadsheet(): adds a spreadsheet object to the active document"
|
||||
obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Spreadsheet")
|
||||
Spreadsheet(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
ViewProviderSpreadsheet(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
|
||||
def addSpreadsheetView(view):
|
||||
"addSpreadsheetView(view): adds the given spreadsheet view to the FreeCAD MDI area"
|
||||
import FreeCAD
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui,Spreadsheet_rc
|
||||
import Spreadsheet_rc
|
||||
mdi = FreeCADGui.getMainWindow().findChild(QtGui.QMdiArea)
|
||||
mdi.addSubWindow(view)
|
||||
|
||||
FreeCADGui.addCommand('Spreadsheet_Create',_CommandSpreadsheet())
|
||||
|
|
Loading…
Reference in New Issue
Block a user