Commit 667d200c authored by sumpfralle's avatar sumpfralle

turned all old-style classes into new-style classes

moved data file location handling to a separate module
moved most model handling functions to separate "plugins"
created a basic "core" handler for settings, widgets and events


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@1061 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 3a99ef31
This diff is collapsed.
<?xml version="1.0"?>
<interface>
<!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="window1">
<child>
<object class="GtkVBox" id="ModelMirrorBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">5</property>
<child>
<object class="GtkFrame" id="frame3">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment51">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="xscale">0</property>
<property name="left_padding">12</property>
<child>
<object class="GtkVBox" id="vbox29">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkVButtonBox" id="vbuttonbox8">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkRadioButton" id="MirrorPlaneXY">
<property name="label" translatable="yes">X-Y</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="MirrorPlaneXZ">
<property name="label" translatable="yes">X-Z</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">MirrorPlaneXY</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="MirrorPlaneYZ">
<property name="label" translatable="yes">Y-Z</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">MirrorPlaneXY</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHButtonBox" id="hbuttonbox10">
<property name="visible">True</property>
<property name="layout_style">start</property>
<child>
<object class="GtkButton" id="PlaneMirrorButton">
<property name="label" translatable="yes">Mirror</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label16">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Plane&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
<?xml version="1.0"?>
<interface>
<!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="window1">
<child>
<object class="GtkFrame" id="ModelPolygonFrame">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment55">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkHButtonBox" id="hbuttonbox8">
<property name="visible">True</property>
<property name="spacing">3</property>
<property name="layout_style">start</property>
<child>
<object class="GtkButton" id="ToggleModelDirectionButton">
<property name="label" translatable="yes">Toggle direction</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">2</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="DirectionsGuessButton">
<property name="label" translatable="yes">Revise directions</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label26">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Polygon winding&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
</child>
</object>
</interface>
This diff is collapsed.
<?xml version="1.0"?>
<interface>
<!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="window1">
<child>
<object class="GtkFrame" id="ModelProjectionFrame">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment56">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<object class="GtkVBox" id="vbox47">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">3</property>
<child>
<object class="GtkRadioButton" id="ProjectionModelTop">
<property name="label" translatable="yes">Top</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="ProjectionModelMiddle">
<property name="label" translatable="yes">Middle</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">ProjectionModelTop</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="ProjectionModelBottom">
<property name="label" translatable="yes">Bottom</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">ProjectionModelTop</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<property name="spacing">2</property>
<child>
<object class="GtkRadioButton" id="ProjectionModelCustom">
<property name="label" translatable="yes">custom z:</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">ProjectionModelTop</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="ProjectionZLevel">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
<property name="adjustment">ProjectionZLevelValue</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="layout_style">start</property>
<child>
<object class="GtkButton" id="ProjectionButton">
<property name="label" translatable="yes">Calculate 2D projection</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">4</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label28">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;2D Projection&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
</child>
</object>
<object class="GtkAdjustment" id="ProjectionZLevelValue">
<property name="lower">-2000</property>
<property name="upper">2000</property>
<property name="step_increment">1</property>
</object>
</interface>
This diff is collapsed.
This diff is collapsed.
<?xml version="1.0"?>
<interface>
<!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="window1">
<child>
<object class="GtkVBox" id="ModelSwapBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">5</property>
<child>
<object class="GtkFrame" id="frame4">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment52">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="xscale">0</property>
<property name="left_padding">12</property>
<child>
<object class="GtkVBox" id="vbox9">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkVButtonBox" id="vbuttonbox9">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkRadioButton" id="SwapAxesXY">
<property name="label" translatable="yes">X &lt;-&gt; Y</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="SwapAxesXZ">
<property name="label" translatable="yes">X &lt;-&gt; Z</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">SwapAxesXY</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="SwapAxesYZ">
<property name="label" translatable="yes">Y &lt;-&gt; Z</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="draw_indicator">True</property>
<property name="group">SwapAxesXY</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="SwapAxesButton">
<property name="label" translatable="yes">Swap</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label17">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Axes pair&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -22,7 +22,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
import os
class EMCToolExporter:
class EMCToolExporter(object):
def __init__(self, tools):
self.tools = tools
......
......@@ -64,7 +64,7 @@ def _get_num_converter(step_width):
return lambda number: decimal.Decimal(format_string % number)
class GCodeGenerator:
class GCodeGenerator(object):
NUM_OF_AXES = 3
......
......@@ -25,7 +25,7 @@ from pycam import VERSION
import datetime
import os
class STLExporter:
class STLExporter(object):
def __init__(self, model, name="model", created_by="pycam", linesep=None,
**kwargs):
......
......@@ -24,7 +24,7 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
SVG_OUTPUT_DPI = 90
class SVGExporter:
class SVGExporter(object):
def __init__(self, output, unit="mm", maxx=None, maxy=None):
if isinstance(output, basestring):
......
......@@ -33,9 +33,6 @@ TRANSFORMATIONS = {
"x": ((1, 0, 0, 0), (0, 0, 1, 0), (0, -1, 0, 0)),
"y": ((0, 0, -1, 0), (0, 1, 0, 0), (1, 0, 0, 0)),
"z": ((0, 1, 0, 0), (-1, 0, 0, 0), (0, 0, 1, 0)),
"xy": ((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, -1, 0)),
"xz": ((1, 0, 0, 0), (0, -1, 0, 0), (0, 0, 1, 0)),
"yz": ((-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0)),
"x_swap_y": ((0, 1, 0, 0), (1, 0, 0, 0), (0, 0, 1, 0)),
"x_swap_z": ((0, 0, 1, 0), (0, 1, 0, 0), (1, 0, 0, 0)),
"y_swap_z": ((1, 0, 0, 0), (0, 0, 1, 0), (0, 1, 0, 0)),
......@@ -141,7 +138,7 @@ def get_rotation_matrix_from_to(v_orig, v_dest):
t * rot_axis.y * rot_axis.z + s * rot_axis.x,
t * rot_axis.z * rot_axis.z + c)
def get_rotation_matrix_axis_angle(rot_axis, rot_angle):
def get_rotation_matrix_axis_angle(rot_axis, rot_angle, use_radians=True):
""" calculate rotation matrix for a normalized vector and an angle
see http://mathworld.wolfram.com/RotationMatrix.html
......@@ -153,6 +150,8 @@ def get_rotation_matrix_axis_angle(rot_axis, rot_angle):
@rtype: tuple(float)
@return: the roation
"""
if not use_radians:
rot_angle *= math.pi / 180
sin = number(math.sin(rot_angle))
cos = number(math.cos(rot_angle))
return ((cos + rot_axis[0]*rot_axis[0]*(1-cos),
......
......@@ -39,7 +39,7 @@ except ImportError:
get_point_object = lambda point: point
class Path:
class Path(object):
id = 0
def __init__(self):
self.id = Path.id
......
......@@ -32,7 +32,7 @@ DEBUG_POLYGONEXTRACTOR2 = False
DEBUG_POLYGONEXTRACTOR3 = False
class PolygonExtractor:
class PolygonExtractor(object):
CONTOUR = 1
MONOTONE = 2
......
......@@ -28,7 +28,7 @@ except ImportError:
GL_enabled = False
class Node:
class Node(object):
def __repr__(self):
s = ""
for bound in self.bound:
......
......@@ -86,7 +86,7 @@ def connect_button_handlers(signal, original_button, derived_button):
original_button)
class Camera:
class Camera(object):
def __init__(self, settings, get_dim_func, view=None):
self.view = None
......@@ -281,7 +281,7 @@ class Camera:
return (factors_x, factors_y)
class ModelViewWindowGL:
class ModelViewWindowGL(object):
def __init__(self, gui, settings, notify_destroy=None, accel_group=None,
item_buttons=None, context_menu_actions=None):
# assume, that initialization will fail
......
This diff is collapsed.
......@@ -60,7 +60,7 @@ def get_config_filename(filename=None):
return os.path.join(config_dir, filename)
class Settings:
class Settings(object):
GET_INDEX = 0
SET_INDEX = 1
......@@ -118,7 +118,7 @@ class Settings:
return self.items.keys()
class ProcessSettings:
class ProcessSettings(object):
BASIC_DEFAULT_CONFIG = """
[ToolDefault]
......@@ -556,7 +556,7 @@ process: 3
return os.linesep.join(result)
class ToolpathSettings:
class ToolpathSettings(object):
SECTIONS = {
"Bounds": {
......
......@@ -193,7 +193,7 @@ def keyPressed(key, x, y):
elif _KeyHandlerFunc:
_KeyHandlerFunc(key, x, y)
class mouseState:
class mouseState(object):
button = None
state = None
x = 0
......
......@@ -150,7 +150,7 @@ def get_dependency_report(details, prefix=""):
return os.linesep.join(result)
class EmergencyDialog:
class EmergencyDialog(object):
""" This graphical message window requires no external dependencies.
The Tk interface package is part of the main python distribution.
Use this class for displaying dependency errors (especially on Windows).
......
......@@ -72,7 +72,7 @@ def _process_one_triangle((model, cutter, up_vector, triangle, z)):
return result, None
class CollisionPaths:
class CollisionPaths(object):
def __init__(self):
self.waterlines = []
......@@ -193,7 +193,7 @@ class CollisionPaths:
return result
class ContourFollow:
class ContourFollow(object):
def __init__(self, cutter, models, path_processor, physics=None):
self.cutter = cutter
......
......@@ -39,7 +39,7 @@ def _process_one_grid_line((positions, minz, maxz, model, cutter, physics)):
return get_max_height_dynamic(model, cutter, positions, minz, maxz, physics)
class Dimension:
class Dimension(object):
def __init__(self, start, end):
self.start = float(start)
self.end = float(end)
......@@ -70,7 +70,7 @@ class Dimension:
return self.value
class DropCutter:
class DropCutter(object):
def __init__(self, cutter, models, path_processor, physics=None):
self.cutter = cutter
......
......@@ -35,7 +35,7 @@ import pycam.Utils.log
log = pycam.Utils.log.get_logger()
class EngraveCutter:
class EngraveCutter(object):
def __init__(self, cutter, trimesh_models, contour_model, path_processor,
clockwise=False, physics=None):
......
......@@ -43,7 +43,7 @@ def _process_one_line((p1, p2, depth, models, cutter, physics)):
return points
class PushCutter:
class PushCutter(object):
def __init__(self, cutter, models, path_processor, physics=None):
if physics is None:
......
......@@ -28,7 +28,7 @@ from pycam.Geometry.Point import Point
import pycam.Utils.threading
class Hit:
class Hit(object):
def __init__(self, cl, cp, t, d, direction):
self.cl = cl
self.cp = cp
......
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import math
import pycam.Plugins
import pycam.Utils.log
log = pycam.Utils.log.get_logger()
class ModelExtrusion(pycam.Plugins.PluginBase):
UI_FILE = "model_extrusion.ui"
def setup(self):
if self.gui:
extrusion_frame = self.gui.get_object("ModelExtrusionFrame")
extrusion_frame.unparent()
self.core.register_event("model-change-after",
self._update_extrude_widgets)
self.core.register_ui("model_handling", "Extrusion",
extrusion_frame, 5)
self.gui.get_object("ExtrudeButton").connect("clicked",
self._extrude_model)
self.gui.get_object("ExtrusionHeight").set_value(1)
self.gui.get_object("ExtrusionWidth").set_value(1)
self.gui.get_object("ExtrusionGrid").set_value(0.5)
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelExtrusionFrame"))
self.core.unregister_event("model-change-after",
self._update_extrude_widgets)
def _update_extrude_widgets(self):
model = self.core.get("model")
is_extrudable = (not model is None) \
and hasattr(model, "extrude")
extrude_widget = self.gui.get_object("ModelExtrusionFrame")
if is_extrudable:
extrude_widget.show()
else:
extrude_widget.hide()
def _extrude_model(self, widget=None):
model = self.core.get("model")
if not model:
return
self.core.get("update_progress")("Extruding model")
extrusion_type_selector = self.gui.get_object("ExtrusionTypeSelector")
type_model = extrusion_type_selector.get_model()
type_active = extrusion_type_selector.get_active()
if type_active >= 0:
type_string = type_model[type_active][0]
height = self.gui.get_object("ExtrusionHeight").get_value()
width = self.gui.get_object("ExtrusionWidth").get_value()
grid_size = self.gui.get_object("ExtrusionGrid").get_value()
if type_string == "radius_up":
func = lambda x: height * math.sqrt((width ** 2 - max(0, width - x) ** 2))
elif type_string == "radius_down":
func = lambda x: height * (1 - math.sqrt((width ** 2 - min(width, x) ** 2)) / width)
elif type_string == "skewed":
func = lambda x: height * min(1, x / width)
else:
log.error("Unknown extrusion type selected: %s" % type_string)
return
new_model = model.extrude(stepping=grid_size, func=func,
callback=self.core.get("update_progress"))
if new_model:
self.core.get("load_model")(new_model)
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import pycam.Plugins
class ModelPlaneMirror(pycam.Plugins.PluginBase):
UI_FILE = "model_plane_mirror.ui"
def setup(self):
if self.gui:
mirror_box = self.gui.get_object("ModelMirrorBox")
mirror_box.unparent()
self.core.register_ui("model_handling", "Mirror", mirror_box, 0)
self.gui.get_object("PlaneMirrorButton").connect("clicked",
self._plane_mirror)
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelMirrorBox"))
def _plane_mirror(self, widget=None):
model = self.core.get("model")
if not model:
return
self.core.emit_event("model-change-before")
self.core.get("update_progress")("Mirroring model")
self.core.get("disable_progress_cancel_button")()
for plane in ("XY", "XZ", "YZ"):
if self.gui.get_object("MirrorPlane%s" % plane).get_active():
break
model.transform_by_template("%s_mirror" % plane.lower(),
callback=self.core.get("update_progress"))
self.core.emit_event("model-change-after")
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import pycam.Plugins
class ModelPolygons(pycam.Plugins.PluginBase):
UI_FILE = "model_polygons.ui"
def setup(self):
if self.gui:
polygon_frame = self.gui.get_object("ModelPolygonFrame")
polygon_frame.unparent()
self.core.register_ui("model_handling", "Polygons", polygon_frame, 0)
self.core.register_event("model-change-after",
self._update_polygon_controls)
self.gui.get_object("ToggleModelDirectionButton").connect("clicked",
self._toggle_direction)
self.gui.get_object("DirectionsGuessButton").connect("clicked",
self._revise_directions)
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelPolygonFrame"))
def _update_polygon_controls(self):
model = self.core.get("model")
is_reversible = model and hasattr(model, "reverse_directions")
frame = self.gui.get_object("ModelPolygonFrame")
if is_reversible:
frame.show()
else:
frame.hide()
def _toggle_direction(self, widget=None):
model = self.core.get("model")
if not model or not hasattr(model, "reverse_directions"):
return
self.core.emit_event("model-change-before")
self.core.get("update_progress")("Reversing directions of contour model")
model.reverse_directions(callback=self.core.get("update_progress"))
self.core.emit_event("model-change-after")
def _revise_directions(self, widget=None):
model = self.core.get("model")
if not model or not hasattr(model, "revise_directions"):
return
self.core.emit_event("model-change-before")
self.core.get("update_progress")("Analyzing directions of contour model")
model.revise_directions(callback=self.core.get("update_progress"))
self.core.emit_event("model-change-after")
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import pycam.Plugins
class ModelPosition(pycam.Plugins.PluginBase):
UI_FILE = "model_position.ui"
def setup(self):
if self.gui:
position_box = self.gui.get_object("ModelPositionBox")
position_box.unparent()
self.core.register_ui("model_handling", "Position", position_box, -20)
shift_model_button = self.gui.get_object("ShiftModelButton")
shift_model_button.connect("clicked", self._shift_model)
align_model_button = self.gui.get_object("AlignPositionButton")
align_model_button.connect("clicked", self._align_model)
# grab default button for shift/align controls
for axis in "XYZ":
obj = self.gui.get_object("ShiftPosition%s" % axis)
obj.connect("focus-in-event", lambda widget, data: \
shift_model_button.grab_default())
obj.connect("focus-out-event", lambda widget, data: \
shift_model_button.get_toplevel().set_default(None))
for axis in "XYZ":
for name_template in ("AlignPosition%s", "AlignPosition%sMin",
"AlignPosition%sCenter", "AlignPosition%sMax"):
obj = self.gui.get_object("AlignPosition%s" % axis)
obj.connect("focus-in-event", lambda widget, data: \
align_model_button.grab_default())
obj.connect("focus-out-event", lambda widget, data: \
align_model_button.get_toplevel().set_default(None))
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelPositionBox"))
def _shift_model(self, widget=None):
model = self.core.get("model")
if not model:
return
self.core.emit_event("model-change-before")
self.core.get("update_progress")("Aligning model")
self.core.get("disable_progress_cancel_button")()
shift = [self.gui.get_object("ShiftPosition%s" % axis).get_value()
for axis in "XYZ"]
model.shift(shift[0], shift[1], shift[2],
callback=self.core.get("update_progress"))
self.core.emit_event("model-change-after")
def _align_model(self, widget=None):
model = self.core.get("model")
if not model:
return
self.core.emit_event("model-change-before")
self.core.get("update_progress")("Shifting model")
self.core.get("disable_progress_cancel_button")()
dest = [self.gui.get_object("AlignPosition%s" % axis).get_value()
for axis in "XYZ"]
shift_values = []
for axis in "XYZ":
dest = self.gui.get_object("AlignPosition%s" % axis).get_value()
alignments = ("Min", "Center", "Max")
for alignment in alignments:
objname = "AlignPosition%s%s" % (axis, alignment)
min_axis = getattr(model, "min%s" % axis.lower())
max_axis = getattr(model, "max%s" % axis.lower())
if self.gui.get_object(objname).get_active():
if alignment == "Min":
shift = dest - min_axis
elif alignment == "Center":
shift = dest - (min_axis + max_axis) / 2.0
else:
shift = dest - max_axis
shift_values.append(shift)
model.shift(shift_values[0], shift_values[1], shift_values[2],
callback=self.core.get("update_progress"))
self.core.emit_event("model-change-after")
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import pycam.Plugins
from pycam.Geometry.Plane import Plane
from pycam.Geometry.Point import Point, Vector
import pycam.Utils.log
log = pycam.Utils.log.get_logger()
class ModelProjection(pycam.Plugins.PluginBase):
UI_FILE = "model_projection.ui"
def setup(self):
if self.gui:
projection_frame = self.gui.get_object("ModelProjectionFrame")
projection_frame.unparent()
self.core.register_ui("model_handling", "Projection",
projection_frame, 10)
self.core.register_event("model-change-after",
self._update_controls)
self.gui.get_object("ProjectionButton").connect("clicked",
self._projection)
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelProjectionFrame"))
self.core.unregister_event("model-change-after",
self._update_controls)
def _update_controls(self):
model = self.core.get("model")
is_projectable = model and hasattr(model, "get_waterline_contour")
control = self.gui.get_object("ModelProjectionFrame")
if is_projectable:
control.show()
else:
control.hide()
def _projection(self, widget=None):
model = self.core.get("model")
if not model or not hasattr(model, "get_waterline_contour"):
return
self.core.get("update_progress")("Calculating 2D projection")
for objname, z_level in (("ProjectionModelTop", model.maxz),
("ProjectionModelMiddle", (model.minz + model.maxz) / 2.0),
("ProjectionModelBottom", model.minz),
("ProjectionModelCustom",
self.gui.get_object("ProjectionZLevel").get_value())):
plane = Plane(Point(0, 0, z_level), Vector(0, 0, 1))
log.info("Projecting 3D model at level z=%g" % plane.p.z)
projection = model.get_waterline_contour(plane)
if projection:
self.core.get("load_model")(projection)
else:
log.warn("The 2D projection at z=%g is empty. Aborted." % \
plane.p.z)
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import pycam.Plugins
import pycam.Geometry.Matrix
class ModelRotation(pycam.Plugins.PluginBase):
UI_FILE = "model_rotation.ui"
def setup(self):
if self.gui:
rotation_box = self.gui.get_object("ModelRotationBox")
rotation_box.unparent()
self.core.register_ui("model_handling", "Rotation", rotation_box,
-10)
self.gui.get_object("RotateModelButton").connect("clicked",
self._rotate_model)
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelRotationBox"))
def _rotate_model(self, widget=None):
model = self.core.get("model")
if not model:
return
self.core.emit_event("model-change-before")
self.core.get("update_progress")("Rotating model")
self.core.get("disable_progress_cancel_button")()
for axis in "XYZ":
if self.gui.get_object("RotationAxis%s" % axis).get_active():
break
axis_vector = {"X": (1, 0, 0), "Y": (0, 1, 0), "Z": (0, 0, 1)}[axis]
for control, angle in (("RotationAngle90CCKW", -90),
("RotationAngle90CKW", 90),
("RotationAngle180", 180),
("RotationAngleCustomCKW",
self.gui.get_object("RotationAngle").get_value())):
if self.gui.get_object(control).get_active():
break
matrix = pycam.Geometry.Matrix.get_rotation_matrix_axis_angle(
axis_vector, angle, use_radians=False)
model.transform_by_matrix(matrix,
callback=self.core.get("update_progress"))
self.core.emit_event("model-change-after")
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import pycam.Plugins
class ModelScaling(pycam.Plugins.PluginBase):
UI_FILE = "model_scaling.ui"
def setup(self):
if self.gui:
scale_box = self.gui.get_object("ModelScaleBox")
scale_box.unparent()
self.core.register_ui("model_handling", "Scale", scale_box, -5)
self.core.register_event("model-change-after",
self._update_scale_dimensions)
update_model = lambda widget=None: self.core.emit_event(
"model-change-after")
scale_percent = self.gui.get_object("ScalePercent")
scale_button = self.gui.get_object("ScaleModelButton")
scale_percent.set_value(100)
scale_percent.connect("focus-in-event",
lambda widget, data: scale_button.grab_default())
scale_percent.connect("focus-out-event", lambda widget, data: \
scale_box.get_toplevel().set_default(None))
scale_button.connect("clicked", self._scale_model)
# scale model to an axis dimension
self.gui.get_object("ScaleDimensionAxis").connect("changed",
update_model)
scale_dimension_button = self.gui.get_object("ScaleAllAxesButton")
scale_dimension_control = self.gui.get_object(
"ScaleDimensionControl")
scale_dimension_control.connect("focus-in-event",
lambda widget, data: scale_dimension_button.grab_default())
scale_dimension_control.connect("focus-out-event",
lambda widget, data: \
scale_box.get_toplevel().set_default(None))
scale_dimension_button.connect("clicked",
self._scale_model_axis_fit, True)
self.gui.get_object("ScaleSelectedAxisButton").connect("clicked",
self._scale_model_axis_fit, False)
self.gui.get_object("ScaleInchMM").connect("clicked",
self._scale_model, 100 * 25.4)
self.gui.get_object("ScaleMMInch").connect("clicked",
self._scale_model, 100 / 25.4)
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelScaleBox"))
def _update_scale_dimensions(self):
model = self.core.get("model")
if not model:
return
# scale controls
axis_control = self.gui.get_object("ScaleDimensionAxis")
scale_button = self.gui.get_object("ScaleSelectedAxisButton")
scale_value = self.gui.get_object("ScaleDimensionControl")
index = axis_control.get_active()
dims = (model.maxx - model.minx, model.maxy - model.miny,
model.maxz - model.minz)
value = dims[index]
non_zero_dimensions = [i for i, dim in enumerate(dims) if dim > 0]
enable_controls = index in non_zero_dimensions
scale_button.set_sensitive(enable_controls)
scale_value.set_sensitive(enable_controls)
scale_value.set_value(value)
def _scale_model(self, widget=None, percent=None):
model = self.core.get("model")
if not model:
return
if percent is None:
percent = self.gui.get_object("ScalePercent").get_value()
factor = percent / 100.0
if (factor <= 0) or (factor == 1):
return
self.core.emit_event("model-change-before")
self.core.get("update_progress")("Scaling model")
self.core.get("disable_progress_cancel_button")()
model.scale(factor, callback=self.core.get("update_progress"))
self.core.emit_event("model-change-after")
def _scale_model_axis_fit(self, widget=None, proportionally=False):
model = self.core.get("model")
if not model:
return
value = self.gui.get_object("ScaleDimensionValue").get_value()
index = self.gui.get_object("ScaleDimensionAxis").get_active()
axes = "xyz"
axis_suffix = axes[index]
factor = value / (getattr(model, "max" + axis_suffix) - \
getattr(model, "min" + axis_suffix))
self.core.emit_event("model-change-before")
self.core.get("update_progress")("Scaling model")
self.core.get("disable_progress_cancel_button")()
if proportionally:
model.scale(factor, callback=self.core.get("update_progress"))
else:
factor_x, factor_y, factor_z = (1, 1, 1)
if index == 0:
factor_x = factor
elif index == 1:
factor_y = factor
elif index == 2:
factor_z = factor
else:
return
model.scale(factor_x, factor_y, factor_z,
callback=self.core.get("update_progress"))
# move the model to its previous center
self.core.emit_event("model-change-after")
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import pycam.Plugins
class ModelSwapAxes(pycam.Plugins.PluginBase):
UI_FILE = "model_swap_axes.ui"
def setup(self):
if self.gui:
swap_box = self.gui.get_object("ModelSwapBox")
swap_box.unparent()
self.core.register_ui("model_handling", "Swap axes", swap_box, 0)
self.gui.get_object("SwapAxesButton").connect("clicked",
self._swap_axes)
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelSwapBox"))
def _swap_axes(self, widget=None):
model = self.core.get("model")
if not model:
return
self.core.emit_event("model-change-before")
self.core.get("update_progress")("Swap axes of model")
self.core.get("disable_progress_cancel_button")()
for axes, template in (("XY", "x_swap_y"), ("XZ", "x_swap_z"),
("YZ", "y_swap_z")):
if self.gui.get_object("SwapAxes%s" % axes).get_active():
break
model.transform_by_template(template,
callback=self.core.get("update_progress"))
self.core.emit_event("model-change-after")
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2011 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import os
import imp
import inspect
import gtk
import pycam.Utils.log
import pycam.Utils.locations
_log = pycam.Utils.log.get_logger()
class PluginBase(object):
UI_FILE = None
def __init__(self, core, name):
self.enabled = True
self.name = name
self.core = core
self.gui = None
if self.UI_FILE:
gtk_build_file = pycam.Utils.locations.get_ui_file_location(
self.UI_FILE)
if gtk_build_file:
self.gui = gtk.Builder()
try:
self.gui.add_from_file(gtk_build_file)
except RuntimeError:
self.gui = None
if not self.setup():
raise RuntimeError("Failed to load plugin '%s'" % str(name))
def setup(self):
raise NotImplementedError("Module %s (%s) does not implement " + \
"'setup'" % (self.name, __file__))
def teardown(self):
raise NotImplementedError("Module %s (%s) does not implement " + \
"'teardown'" % (self.name, __file__))
class PluginManager(object):
def __init__(self, core):
self.core = core
self.modules = {}
def import_plugins(self, directory=None):
if directory is None:
directory = os.path.dirname(__file__)
try:
files = os.listdir(directory)
except OSError:
return
for filename in files:
if filename.endswith(".py") and (filename != "__init__.py") and \
os.path.isfile(os.path.join(directory, filename)):
mod_name = filename[0:-(len(".py"))]
try:
mod_file, mod_filename, mod_desc = imp.find_module(
mod_name, [directory])
full_mod_name = "pycam.Plugins.%s" % mod_name
mod = imp.load_module(full_mod_name, mod_file,
mod_filename, mod_desc)
except ImportError:
_log.debug("Skipping broken plugin %s" % os.path.join(
directory, filename))
continue
for attr in dir(mod):
item = getattr(mod, attr)
if inspect.isclass(item) and hasattr(item, "setup"):
self._load_plugin(item, mod_filename, attr)
def _load_plugin(self, obj, filename, local_name):
name = "%s.%s" % (os.path.basename(filename)[0:-len(".py")], local_name)
if name in self.modules:
_log.debug("Cleaning up module %s" % name)
self.modules[name].teardown()
_log.debug("Initializing module %s (%s)" % (name, filename))
self.modules[name] = obj(self.core, name)
......@@ -31,7 +31,7 @@ except ImportError:
GL_enabled = False
class ODEBlocks:
class ODEBlocks(object):
def __init__(self, tool_settings, (minx, maxx, miny, maxy, minz, maxz),
x_steps=None, y_steps=None):
......
......@@ -41,18 +41,18 @@ NUM_CELL_X = 0
NUM_CELL_Y = 0
class ZBufferItem:
class ZBufferItem(object):
def __init__(self, z=0.0):
self.z = float(z)
self.changed = True
self.list = -1
class ZCellItem:
class ZCellItem(object):
def __init__(self):
self.list = -1
self.array = None
class ZBuffer:
class ZBuffer(object):
def __init__(self, minx, maxx, xres, miny, maxy, yres, minz, maxz):
global NUM_CELL_X, NUM_CELL_Y
self.minx = float(minx)
......
......@@ -161,9 +161,12 @@ def get_support_distributed(model, z_plane, average_distance,
polygons = model.get_cropped_model_by_bounds(bounds).get_polygons(
z=z_plane, ignore_below=False)
else:
polygons = model.get_waterline_contour(Plane(Point(0, 0, z_plane),
Vector(0, 0, 1))).get_cropped_model_by_bounds(bounds)\
.get_polygons()
waterline_model = model.get_waterline_contour(Plane(Point(0, 0, z_plane),
Vector(0, 0, 1))).get_cropped_model_by_bounds(bounds)
if not waterline_model:
return
else:
polygons = waterline_model.get_polygons()
# minimum required distance between two bridge start points
avoid_distance = 1.5 * (abs(length) + thickness)
if start_at_corners:
......
......@@ -281,7 +281,7 @@ class Toolpath(object):
self.toolpath = new_paths
class Bounds:
class Bounds(object):
TYPE_RELATIVE_MARGIN = 0
TYPE_FIXED_MARGIN = 1
......
......@@ -237,7 +237,7 @@ def get_external_program_location(key):
return None
class ProgressCounter:
class ProgressCounter(object):
def __init__(self, max_value, update_callback):
self.max_value = max_value
......
......@@ -20,7 +20,7 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
class Iterator:
class Iterator(object):
def __init__(self, seq, start=0):
self.seq = seq
self.ind = start
......@@ -73,7 +73,7 @@ class Iterator:
return len(self.seq) - self.ind
class CyclicIterator:
class CyclicIterator(object):
def __init__(self, seq, start=0):
self.seq = seq
self.ind = start
......
# -*- coding: utf-8 -*-
"""
$Id$
Copyright 2010 Lars Kruse <devel@sumpfralle.de>
This file is part of PyCAM.
PyCAM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PyCAM 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
"""
import os
import sys
DATA_DIR_ENVIRON_KEY = "PYCAM_DATA_DIR"
FONT_DIR_ENVIRON_KEY = "PYCAM_FONT_DIR"
DATA_BASE_DIRS = [os.path.realpath(os.path.join(os.path.dirname(__file__),
os.pardir, os.pardir, os.pardir, "share")),
os.path.join(sys.prefix, "local", "share", "pycam"),
os.path.join(sys.prefix, "share", "pycam")]
FONTS_SUBDIR = "fonts"
UI_SUBDIR = "ui"
# necessary for "pyinstaller"
if "_MEIPASS2" in os.environ:
DATA_BASE_DIRS.insert(0, os.path.join(os.path.normpath(os.environ["_MEIPASS2"]), "share"))
# respect an override via an environment setting
if DATA_DIR_ENVIRON_KEY in os.environ:
DATA_BASE_DIRS.insert(0, os.path.normpath(os.environ[DATA_DIR_ENVIRON_KEY]))
if FONT_DIR_ENVIRON_KEY in os.environ:
FONT_DIR_OVERRIDE = os.path.normpath(os.environ[FONT_DIR_ENVIRON_KEY])
else:
FONT_DIR_OVERRIDE = None
FONT_DIR_FALLBACK = "/usr/share/qcad/fonts"
def get_ui_file_location(filename, silent=False):
return get_data_file_location(os.path.join(UI_SUBDIR, filename), silent=silent)
def get_data_file_location(filename, silent=False):
for base_dir in DATA_BASE_DIRS:
test_path = os.path.join(base_dir, filename)
if os.path.exists(test_path):
return test_path
else:
if not silent:
lines = []
lines.append("Failed to locate a resource file (%s) in %s!" \
% (filename, DATA_BASE_DIRS))
lines.append("You can extend the search path by setting the " \
+ "environment variable '%s'." % str(DATA_DIR_ENVIRON_KEY))
log.error(os.linesep.join(lines))
return None
def get_font_dir():
if FONT_DIR_OVERRIDE:
if os.path.isdir(FONT_DIR_OVERRIDE):
return FONT_DIR_OVERRIDE
else:
log.warn(("You specified a font dir that does not exist (%s). " \
+ "I will ignore it.") % FONT_DIR_OVERRIDE)
font_dir = get_data_file_location(FONTS_SUBDIR, silent=True)
if not font_dir is None:
return font_dir
else:
log.warn(("Failed to locate the fonts directory '%s' below '%s'. " \
+ "Falling back to '%s'.") \
% (FONTS_SUBDIR, DATA_BASE_DIRS, FONT_DIR_FALLBACK))
if os.path.isdir(FONT_DIR_FALLBACK):
return FONT_DIR_FALLBACK
else:
log.warn(("The fallback font directory (%s) does not exist. " \
+ "No fonts will be available.") % FONT_DIR_FALLBACK)
return None
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment