Skip to content

Commit

Permalink
[TreeToAscii] Code clean-up
Browse files Browse the repository at this point in the history
  • Loading branch information
galou committed Mar 19, 2020
1 parent 267d57f commit 5156aa0
Show file tree
Hide file tree
Showing 2 changed files with 209 additions and 173 deletions.
209 changes: 209 additions & 0 deletions Information/TreeToAscii.FCMacro
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
#!/usr/bin/python
#####################################
# Copyright (c) openBrain 2020
# Licensed under LGPL v2
#
# This FreeCAD macro prints the Tree of selected object(s) as ASCII art.
# Several styles are available. Tree branch pattern is customizable.
# It can export to clipboard, file or embedded text document.
# This mainly aims at documenting the model.
#
# Version history :
# *0.5 : beta release
#
#####################################

__Name__ = 'Tree To ASCII'
__Comment__ = 'Prints the Tree of selected object(s) as ASCII art'
__Author__ = 'openBrain'
__Version__ = '0.5.1'
__Date__ = '2020-03-19'
__License__ = 'LGPL v2'
__Web__ = 'https://www.freecadweb.org/wiki/Macro_FCTree2Ascii'
__Wiki__ = 'https://www.freecadweb.org/wiki/Macro_FCTree2Ascii'
__Icon__ = ''
__Help__ = 'Select object(s) you want to print the tree for then run'
__Status__ = 'Beta'
__Requires__ = 'FreeCAD >= 0.17'
__Communication__ = 'https://forum.freecadweb.org/viewtopic.php?f=22&t=43504'

import FreeCAD as app
import FreeCADGui as gui
from PySide import QtGui, QtCore # Special FreeCAD's PySide, which may be PySide2!

g_preference_path = 'User parameter:BaseApp/Preferences/Mod/TreeToText'
g_preference_pattern = 'TreePattern'
g_preference_style = 'TreeStyle'

# Defines styles as 'name: (fork str, branch str)'. The strings of one style
# should have the same length.
# The first one defines the default style (in Python3).
g_styles = {
'Modern': (' ├ ', ' │ '), # Unicode U+251C, Unicode U+2502
'ASCII': (' \\_', ' | ')
}
g_default_pattern = '{LBL} ({NAM})'

g_text_tree = ''


def print_children(objs=None, level=0, baseline=''):
"""Build a string representing the tree by recursive calls."""
global g_text_tree

for cnt, obj in enumerate(objs, 1):
data = {
'LBL': obj.Label,
'NAM': obj.Name,
'SNAM': ''.join(filter(str.isalpha, obj.Name)),
'TYP': obj.TypeId,
'BTYP': obj.TypeId.partition('::')[0],
'STYP': obj.TypeId.rpartition('::')[-1],
}
fork_str = g_styles[g_style_combo.currentText()][0]
branch_str = g_styles[g_style_combo.currentText()][1]
g_text_tree += baseline + fork_str
try:
g_text_tree += g_pattern_edit.text().format(**data)
except (ValueError, IndexError, KeyError):
g_text_tree = 'Error in generating pattern'
return
g_text_tree += '\n'
if cnt == len(objs):
baselinechild = baseline + ' ' * len(branch_str)
else:
baselinechild = baseline + branch_str
print_children(obj.ViewObject.claimChildren(), level + 1, baselinechild)


def copy_to_clip():
"""Copy the text tree to clipboard."""
g_tree_view.selectAll()
g_tree_view.copy()
_update_tree_view('Copied to clipboard.')
QtCore.QTimer.singleShot(3000, _update_tree_view)


def save_to_file():
"""Save the text tree into a file."""
_path = QtGui.QFileDialog.getSaveFileName()
if _path[0]:
# Save with Qt rather than open() to ask before overwriting the file.
save_file = QtCore.QFile(_path[0])
if save_file.open(QtCore.QFile.ReadWrite):
save_file_content = QtCore.QTextStream(save_file)
save_file_content << g_text_tree
save_file.flush()
save_file.close()
g_tree_view.setPlainText('Saved to file: {}'.format(_path[0]))
else:
g_tree_view.setPlainText('ERROR: Cannot open file "{}"'.format(
_path[0]))
QtCore.QTimer.singleShot(3000, _update_tree_view)


def embed_to_text():
"""Store the text tree into an embedded document."""
try:
text_doc = app.activeDocument().addObject('App::TextDocument',
'ModelTree')
except:
_update_tree_view(
'ERROR: cannot create Text document. Maybe your version is too old')
if text_doc:
text_doc.Text = g_text_tree
_update_tree_view('Embedded to text document : {}'.format(
text_doc.Label))
QtCore.QTimer.singleShot(3000, _update_tree_view)


def _update_tree_view(txt=None):
"""Update g_tree_view with the tree or the given text."""
if txt is None:
g_tree_view.setPlainText(g_text_tree)
else:
g_tree_view.setPlainText(txt)


def update_txt():
"""Update g_tree_view with the updated text tree."""
global g_text_tree

g_text_tree = ''
print_children(gui.Selection.getSelection())
_update_tree_view()


def _on_generate():
"""Save parameters and update the g_tree_view with the text tree."""
param = app.ParamGet(g_preference_path)
param.SetString(g_preference_pattern, g_pattern_edit.text())
param.SetString(g_preference_style, g_style_combo.currentText())
update_txt()


# Get saved parameters or use defaults.
param = app.ParamGet(g_preference_path)
g_name_pattern = param.GetString(g_preference_pattern, g_default_pattern)
default_style = list(g_styles.keys())[0]
g_tree_style = param.GetString(g_preference_style, default_style)
if g_tree_style not in g_styles:
g_tree_style = default_style

# Build UI and show
dlg = QtGui.QDialog(gui.getMainWindow(), QtCore.Qt.Tool)
dlg_layout = QtGui.QVBoxLayout(dlg)
gen_layout = QtGui.QHBoxLayout()
g_pattern_edit = QtGui.QLineEdit(g_name_pattern, dlg)
g_pattern_edit.setToolTip("""Defined variables are:
{LBL}: object Label
{NAM}: object Name
{SNAM}: object ShortName (without digits)
{TYP}: object Type
{BTYP}: object BaseType
{STYP}: object ShortType (without base)
If you need to print curly braces, they have to be doubled.""")

generate_button = QtGui.QPushButton('Generate', dlg)
generate_button.clicked.connect(_on_generate)

g_style_combo = QtGui.QComboBox(dlg)
g_style_combo.addItems(list(g_styles.keys()))
g_style_combo.setCurrentIndex(list(g_styles.keys()).index(g_tree_style))

gen_layout.addWidget(QtGui.QLabel('Generating pattern: '))
gen_layout.addWidget(g_pattern_edit)
gen_layout.addWidget(QtGui.QLabel('Style : '))
gen_layout.addWidget(g_style_combo)
gen_layout.addWidget(generate_button)

g_tree_view = QtGui.QPlainTextEdit(g_text_tree)
g_tree_view.setReadOnly(True)
g_tree_view.setMinimumWidth(gui.getMainWindow().width() / 2)
g_tree_view.setMinimumHeight(gui.getMainWindow().height() / 2)
g_tree_view.setLineWrapMode(QtGui.QPlainTextEdit.NoWrap)

button_box = QtGui.QDialogButtonBox()

copy_clip_button = QtGui.QPushButton('Copy to clipboard', button_box)
button_box.addButton(copy_clip_button, QtGui.QDialogButtonBox.ActionRole)
copy_clip_button.clicked.connect(copy_to_clip)

save_button = QtGui.QPushButton('Save to file', button_box)
button_box.addButton(save_button, QtGui.QDialogButtonBox.ActionRole)
save_button.clicked.connect(save_to_file)

store_embed_button = QtGui.QPushButton('Embed in a text file', button_box)
button_box.addButton(store_embed_button, QtGui.QDialogButtonBox.ActionRole)
store_embed_button.clicked.connect(embed_to_text)

close_dlg_button = QtGui.QPushButton('Close', button_box)
button_box.addButton(close_dlg_button, QtGui.QDialogButtonBox.RejectRole)
button_box.rejected.connect(dlg.reject)

dlg_layout.insertLayout(0, gen_layout)
dlg_layout.addWidget(g_tree_view)
dlg_layout.addWidget(button_box)

update_txt()
dlg.exec_()
173 changes: 0 additions & 173 deletions Utility/FCTree2Ascii.FCMacro

This file was deleted.

0 comments on commit 5156aa0

Please sign in to comment.