Tools: added --gui option to fcinfo tool

This commit is contained in:
Yorik van Havre
2019-07-28 13:59:03 -03:00
parent 772cfc56a0
commit a1edbb092c

View File

@@ -30,7 +30,11 @@ __url__ = ["http://www.freecadweb.org"]
__doc__ = '''
This utility prints information about a given FreeCAD file (*.FCStd)
on screen, including document properties, number of included objects,
object sizes and properties and values
object sizes and properties and values. Its main use is to compare
two files and be able to see the differences in a text-based form.
If no option is used, fcinfo prints the document properties and a list
of properties of each object found in the given file.
Usage:
@@ -39,30 +43,42 @@ Usage:
Options:
-h, --help: Prints this help text
-s, --short: Do not print all the properties contents of objects
-vs --veryshort: Only prints the document info, not objects info
-s, --short: Do not print object properties. Only one line
per object is printed, including its size and SHA1.
This is sufficient to see that an object has
changed, but not what exactly has changed.
-vs --veryshort: Only prints the document info, not objects info.
This is sufficient to see if a file has changed, as
its SHA1 code and timestamp will show it. But won't
show details of what has changed.
-g --gui: Adds visual properties too (if not using -s or -vs)
Git usage:
This script can be used as a textconv tool for git diff by
configuring your git folder as follows:
1) add to .gitattributes:
1) add to .gitattributes (or ~/.gitattributes for user-wide):
*.fcstd diff=fcinfo
2) add to .git/config (or ~/.gitconfig for user-wide):
[diff "fcinfo"]
textconv = /path/to/fcinfo
With this, when committing a .FCStd file with Git,
'git diff' will show you the difference between the two
texts obtained by fcinfo
'''
import sys, zipfile, xml.sax, os, hashlib
import sys
import zipfile
import xml.sax
import os
import hashlib
import re
@@ -70,7 +86,7 @@ class FreeCADFileHandler(xml.sax.ContentHandler):
def __init__(self, zfile, short = 0): # short 0=normal, 1=short, 2=veryshort
def __init__(self, zfile, short = 0): # short: 0=normal, 1=short, 2=veryshort
xml.sax.ContentHandler.__init__(self)
self.zfile = zfile
@@ -95,21 +111,30 @@ class FreeCADFileHandler(xml.sax.ContentHandler):
if ("type" in attributes):
self.contents[name] = attributes["type"]
elif tag == "ViewProvider":
if ("name" in attributes):
self.obj = self.clean(attributes["name"])
elif tag == "Part":
if self.obj:
s = self.zfile.read(attributes["file"]).__sizeof__()
r = self.zfile.read(attributes["file"])
s = r.__sizeof__()
if s < 1024:
s = str(s)+"B"
elif s > 1048576:
s = str(s/1048576)+"M"
else:
s = str(s/1024)+"K"
s += " " + str(hashlib.sha1(r).hexdigest()[:12])
self.contents[self.obj] += " (" + s + ")"
elif tag == "Property":
self.prop = None
if attributes["name"] not in ["Symbol"]:
# skip "internal" properties, unuseful for a diff
if attributes["name"] not in ["Symbol","AttacherType","MapMode","MapPathParameter","MapReversed",
"AttachmentOffset","SelectionStyle","TightGrid","GridSize","GridSnap",
"GridStyle","Lighting","Deviation","AngularDeflection","BoundingBox",
"Selectable","ShowGrid"]:
self.prop = attributes["name"]
elif tag in ["String","Uuid","Float","Integer","Bool","Link"]:
@@ -122,10 +147,31 @@ class FreeCADFileHandler(xml.sax.ContentHandler):
else:
self.contents[self.obj+"00000000::"+self.prop] = attributes["value"]
elif tag in ["PropertyVector"]:
if self.prop and self.obj and (self.short == 0):
val = "("+str(float(attributes["valueX"]))+","+str(float(attributes["valueY"]))+","+str(float(attributes["valueZ"]))+")"
self.contents[self.obj+"00000000::"+self.prop] = val
elif tag in ["PropertyPlacement"]:
if self.prop and self.obj and (self.short == 0):
val = "("+str(float(attributes["Px"]))+","+str(float(attributes["Py"]))+","+str(float(attributes["Pz"]))+")"
val += " ("+str(round(float(attributes["Q0"]),4))+","+str(round(float(attributes["Q1"]),4))+","
val += str(round(float(attributes["Q2"]),4))+","+str(round(float(attributes["Q3"]),4))+")"
self.contents[self.obj+"00000000::"+self.prop] = val
elif tag in ["PropertyColor"]:
if self.prop and self.obj and (self.short == 0):
c = int(attributes["value"])
r = float((c>>24)&0xFF)/255.0
g = float((c>>16)&0xFF)/255.0
b = float((c>>8)&0xFF)/255.0
val = str((r,g,b))
self.contents[self.obj+"00000000::"+self.prop] = val
elif tag == "Objects":
self.count = attributes["Count"]
self.obj = None
# Print all the contents of the document properties
items = self.contents.items()
items.sort()
@@ -188,6 +234,14 @@ if __name__ == '__main__':
if not "Document.xml" in zfile.namelist():
sys.exit(1)
doc = zfile.read("Document.xml")
if gui and "GuiDocument.xml" in zfile.namelist():
guidoc = zfile.read("GuiDocument.xml")
guidoc = re.sub(r"<\?xml.*?-->"," ",guidoc,flags=re.MULTILINE|re.DOTALL)
# a valid xml doc can have only one root element. So we need to insert
# all the contents of the GUiDocument <document> tag into the main one
doc = re.sub(r"<\/Document>","",doc,flags=re.MULTILINE|re.DOTALL)
guidoc = re.sub(r"<Document.*?>"," ",guidoc,flags=re.MULTILINE|re.DOTALL)
doc += guidoc
s = os.path.getsize(sys.argv[-1])
if s < 1024:
s = str(s)+"B"