Commit e03e4dc1 authored by sumpfralle's avatar sumpfralle

added a simple plugin manager

fixe numerous "teardown" handlers


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@1129 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent 21de7ac0
......@@ -33,6 +33,7 @@
<menuitem action="Toggle3DView"/>
<menuitem action="ToggleLogWindow"/>
<menuitem action="ToggleProcessPoolWindow"/>
<menuitem action="TogglePluginWindow"/>
</menu>
<menu action="HelpMenu">
<menuitem action="HelpUserManual"/>
......
<?xml version="1.0"?>
<interface>
<!-- interface-requires gtk+ 2.12 -->
<!-- interface-naming-policy project-wide -->
<object class="GtkListStore" id="PluginsModel">
<columns>
<!-- column-name name -->
<column type="gchararray"/>
<!-- column-name description -->
<column type="gchararray"/>
<!-- column-name enabled -->
<column type="gboolean"/>
<!-- column-name dependencies -->
<column type="gchararray"/>
<!-- column-name dependencies_satisfied -->
<column type="gboolean"/>
<!-- column-name source -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0" translatable="yes">ModelPosition</col>
<col id="1" translatable="yes">Shifting and alignment</col>
<col id="2">True</col>
<col id="3" translatable="yes">Models</col>
<col id="4">True</col>
<col id="5" translatable="yes">/home/...</col>
</row>
<row>
<col id="0" translatable="yes">OpenGLWindow</col>
<col id="1" translatable="yes">Visualize the scene via OpenGL</col>
<col id="2">False</col>
<col id="3" translatable="yes">Many</col>
<col id="4">False</col>
<col id="5" translatable="yes">http://somewher.org</col>
</row>
</data>
</object>
<object class="GtkDialog" id="PluginManagerWindow">
<property name="width_request">640</property>
<property name="height_request">500</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Plugins</property>
<property name="role">pycam-plugins</property>
<property name="type_hint">normal</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<property name="shadow_type">etched-out</property>
<child>
<object class="GtkTreeView" id="PluginsTable">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="model">PluginsModel</property>
<property name="reorderable">True</property>
<property name="rules_hint">True</property>
<property name="search_column">0</property>
<property name="tooltip_column">5</property>
<child>
<object class="GtkTreeViewColumn" id="PluginsEnabled">
<property name="title">Enabled</property>
<property name="sort_column_id">2</property>
<child>
<object class="GtkCellRendererToggle" id="PluginsEnabledCell">
<property name="xpad">1</property>
</object>
<attributes>
<attribute name="sensitive">4</attribute>
<attribute name="activatable">4</attribute>
<attribute name="active">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="PluginsNameColumn">
<property name="title">Name</property>
<property name="sort_column_id">0</property>
<child>
<object class="GtkCellRendererText" id="PluginsNameCell"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="PluginsDescriptionColumn">
<property name="sizing">autosize</property>
<property name="title">Description</property>
<property name="expand">True</property>
<property name="sort_column_id">1</property>
<child>
<object class="GtkCellRendererText" id="PluginsDescriptionCell">
<property name="wrap_mode">word-char</property>
</object>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn" id="PluginsDependenciesColumn">
<property name="title">Dependencies</property>
<property name="sort_column_id">3</property>
<child>
<object class="GtkCellRendererText" id="PluginsDependenciesCell"/>
<attributes>
<attribute name="markup">3</attribute>
</attributes>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="ClosePluginManager">
<property name="label">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">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="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">ClosePluginManager</action-widget>
</action-widgets>
</object>
<object class="GtkToggleAction" id="TogglePluginWindow">
<property name="label">Plugin Manager</property>
<property name="short_label">Plugin Manager</property>
<property name="icon_name">preferences-other</property>
</object>
</interface>
......@@ -190,12 +190,13 @@ class EventCore(pycam.Gui.Settings.Settings):
def unregister_event(self, event, func):
if event in self.event_handlers:
removal_list = []
for index, item in enumerate(self.event_handlers[event][EVENT_HANDLER_INDEX]):
handlers = self.event_handlers[event]
for index, item in enumerate(handlers[EVENT_HANDLER_INDEX]):
if func == item[HANDLER_FUNC_INDEX]:
removal_list.append(index)
removal_list.reverse()
for index in removal_list:
self.event_handlers[event].pop(index)
handlers[EVENT_HANDLER_INDEX].pop(index)
else:
log.debug("Trying to unregister an unknown event: %s" % event)
......@@ -237,6 +238,16 @@ class EventCore(pycam.Gui.Settings.Settings):
self.ui_sections[section][UI_FUNC_INDEX] = (add_action, clear_action)
self._rebuild_ui_section(section)
def unregister_ui_section(self, section):
if section in self.ui_sections:
ui_section = self.ui_sections[section]
while ui_section[UI_WIDGET_INDEX]:
ui_section[UI_WIDGET_INDEX].pop()
del self.ui_sections[section]
else:
log.debug("Trying to unregister a non-existent ui section: %s" % \
str(section))
def _rebuild_ui_section(self, section):
if section in self.ui_sections:
ui_section = self.ui_sections[section]
......
......@@ -51,22 +51,27 @@ class Clipboard(pycam.Plugins.PluginBase):
self.core.register_event("model-selection-changed",
self._update_clipboard_widget)
# menu item and shortcut
actiongroup = self._gtk.ActionGroup("clipboard")
for objname, func, hotkey in (
("CopyModelToClipboard", self.copy_model_to_clipboard, "<Control>c"),
("PasteModelFromClipboard", self.paste_model_from_clipboard, "<Control>v")):
action = self.gui.get_object(objname)
action.connect("activate", func)
key, mod = self._gtk.accelerator_parse(hotkey)
# TODO: move the "<pycam>" accel path somewhere else
accel_path = "<pycam>/%s" % objname
action.set_accel_path(accel_path)
self._gtk.accel_map_change_entry(accel_path, key, mod, True)
actiongroup.add_action(action)
self.core.get("gtk-uimanager").insert_action_group(actiongroup, pos=-1)
self.copy_action = self.gui.get_object("CopyModelToClipboard")
self.copy_action.connect("activate", self.copy_model_to_clipboard)
self.register_gtk_accelerator("clipboard", self.copy_action,
"<Control>c", "CopyModelToClipboard")
self.paste_action = self.gui.get_object("PasteModelFromClipboard")
self.paste_action.connect("activate", self.paste_model_from_clipboard)
self.register_gtk_accelerator("clipboard", self.paste_action,
"<Control>v", "PasteModelFromClipboard")
self._update_clipboard_widget()
return True
def teardown(self):
if self.gui:
self.core.unregister_event("model-selection-changed",
self._update_clipboard_widget)
self.unregister_gtk_accelerator("clipboard", self.copy_action)
self.unregister_gtk_accelerator("clipboard", self.paste_action)
self.core.set("clipboard-set", None)
# TODO: check if this disconnects the clipboard-change-handler
self.clipboard = None
def _get_exportable_models(self):
models = self.core.get("models").get_selected()
exportable = []
......
......@@ -86,7 +86,13 @@ class Fonts(pycam.Plugins.PluginBase):
self._font_dialog_window_visible = False
self._font_dialog_window_position = None
self.font_selector = None
return True
return True
def teardown(self):
self.core.add_item("fonts", None)
if self.gui:
self.unregister_gtk_accelerator("fonts",
self.gui.get_object("ShowFontDialog"))
def toggle_font_dialog_window(self, widget=None, event=None, state=None):
# only "delete-event" uses four arguments
......
......@@ -37,16 +37,10 @@ class Log(pycam.Plugins.PluginBase):
import gtk
self._gtk = gtk
# menu item and shortcut
actiongroup = self._gtk.ActionGroup("log")
log_action = self.gui.get_object("ToggleLogWindow")
log_action.connect("toggled", self.toggle_log_window)
key, mod = self._gtk.accelerator_parse("<Control>l")
# TODO: move the "<pycam>" accel path somewhere else
accel_path = "<pycam>/ToggleLogWindow"
log_action.set_accel_path(accel_path)
self._gtk.accel_map_change_entry(accel_path, key, mod, True)
actiongroup.add_action(log_action)
self.core.get("gtk-uimanager").insert_action_group(actiongroup, pos=-1)
self.register_gtk_accelerator("log", log_action,
"<Control>l", "ToggleLogWindow")
# status bar
self.status_bar = self.gui.get_object("StatusBar")
self.gui.get_object("StatusBarEventBox").connect("button-press-event",
......@@ -70,6 +64,15 @@ class Log(pycam.Plugins.PluginBase):
pycam.Utils.log.add_hook(self.add_log_message)
return True
def teardown(self):
if self.gui:
self.log_window.hide()
self.unregister_gtk_accelerator("log",
self.gui.get_object("ToggleLogWindow"))
self.core.unregister_ui("main_window",
self.gui.get_object("StatusBarEventBox"))
# TODO: disconnect the log handler
def add_log_message(self, title, message, record=None):
timestamp = datetime.datetime.fromtimestamp(
record.created).strftime("%H:%M")
......
......@@ -67,6 +67,8 @@ class ModelExtrusion(pycam.Plugins.PluginBase):
self.gui.get_object("ModelExtrusionFrame"))
self.core.unregister_event("model-change-after",
self._update_extrude_widgets)
self.core.unregister_event("model-selection-changed",
self._update_extrude_widgets)
def _get_extrudable_models(self):
models = self.core.get("models").get_selected()
......
......@@ -45,6 +45,8 @@ class ModelPlaneMirror(pycam.Plugins.PluginBase):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelMirrorBox"))
self.core.unregister_event("model-selection-changed",
self._update_plane_widgets)
def _update_plane_widgets(self):
plane_widget = self.gui.get_object("ModelMirrorBox")
......
......@@ -49,6 +49,10 @@ class ModelPolygons(pycam.Plugins.PluginBase):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelPolygonFrame"))
self.core.unregister_event("model-change-after",
self._update_polygon_controls)
self.core.unregister_event("model-selection-changed",
self._update_polygon_controls)
def _get_polygon_models(self):
models = []
......
......@@ -62,6 +62,8 @@ class ModelPosition(pycam.Plugins.PluginBase):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelPositionBox"))
self.core.unregister_event("model-selection-changed",
self._update_position_widgets)
def _update_position_widgets(self):
widget = self.gui.get_object("ModelPositionBox")
......
......@@ -50,6 +50,8 @@ class ModelProjection(pycam.Plugins.PluginBase):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelProjectionFrame"))
self.core.unregister_event("model-selection-changed",
self._update_controls)
self.core.unregister_event("model-change-after",
self._update_controls)
......
......@@ -47,6 +47,8 @@ class ModelRotation(pycam.Plugins.PluginBase):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelRotationBox"))
self.core.unregister_event("model-selection-changed",
self._update_controls)
def _update_controls(self):
widget = self.gui.get_object("ModelRotationBox")
......
......@@ -36,8 +36,6 @@ class ModelScaling(pycam.Plugins.PluginBase):
self.core.register_ui("model_handling", "Scale", scale_box, -5)
self.core.register_event("model-change-after",
self._update_scale_controls)
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)
......@@ -48,7 +46,8 @@ class ModelScaling(pycam.Plugins.PluginBase):
scale_button.connect("clicked", self._scale_model)
# scale model to an axis dimension
self.gui.get_object("ScaleDimensionAxis").connect("changed",
update_model)
lambda widget=None: self.core.emit_event(
"model-change-after"))
scale_dimension_button = self.gui.get_object("ScaleAllAxesButton")
scale_dimension_control = self.gui.get_object(
"ScaleDimensionControl")
......@@ -74,6 +73,10 @@ class ModelScaling(pycam.Plugins.PluginBase):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelScaleBox"))
self.core.unregister_event("model-change-after",
self._update_scale_controls)
self.core.unregister_event("model-selection-changed",
self._update_scale_controls)
def _update_scale_controls(self):
models = self.core.get("models").get_selected()
......
......@@ -34,18 +34,16 @@ class ModelSupport(pycam.Plugins.PluginBase):
support_frame = self.gui.get_object("ModelExtensionsFrame")
support_frame.unparent()
self.core.register_ui("model_handling", "Support", support_frame, 0)
support_model_changed = lambda widget=None: self.core.emit_event(
"support-model-changed")
self.core.register_event("model-change-after",
support_model_changed)
self._support_model_changed)
self.core.register_event("bounds-changed",
support_model_changed)
self._support_model_changed)
self.core.register_event("support-model-changed",
self.update_support_model)
support_model_type_selector = self.gui.get_object(
"SupportGridTypesControl")
support_model_type_selector.connect("changed",
support_model_changed)
self._support_model_changed)
def add_support_type(obj, name):
types_model = support_model_type_selector.get_model()
types_model.append((obj, name))
......@@ -80,15 +78,16 @@ class ModelSupport(pycam.Plugins.PluginBase):
break
else:
support_model_type_selector.set_active(-1)
# TODO: remove public settings
self.core.add_item("support_model_type",
get_support_model_type,
set_support_model_type)
grid_thickness = self.gui.get_object("SupportGridThickness")
grid_thickness.connect("value-changed", support_model_changed)
grid_thickness.connect("value-changed", self._support_model_changed)
self.core.add_item("support_grid_thickness",
grid_thickness.get_value, grid_thickness.set_value)
grid_height = self.gui.get_object("SupportGridHeight")
grid_height.connect("value-changed", support_model_changed)
grid_height.connect("value-changed", self._support_model_changed)
self.core.add_item("support_grid_height",
grid_height.get_value, grid_height.set_value)
# support grid defaults
......@@ -101,9 +100,17 @@ class ModelSupport(pycam.Plugins.PluginBase):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelExtensionsFrame"))
self.core.unregister_ui("support_model_type_selector", "none")
self.core.unregister_event("model-change-after",
self._support_model_changed)
self.core.unregister_event("bounds-changed",
self._support_model_changed)
self.core.unregister_event("support-model-changed",
self.update_support_model)
def _support_model_changed(self, widget=None):
self.core.emit_event("support-model-changed")
def update_support_model(self, widget=None):
grid_type = self.core.get("support_model_type")
if grid_type == "none":
......
......@@ -55,11 +55,21 @@ class ModelSupportDistributed(pycam.Plugins.PluginBase):
minimum_bridges.connect("value-changed", self.update_support_model)
self.core.add_item("support_grid_minimum_bridges",
minimum_bridges.get_value, minimum_bridges.set_value)
# TODO: remove these public settings
self.core.set("support_grid_average_distance", 30)
self.core.set("support_grid_minimum_bridges", 2)
self.core.set("support_grid_length", 5)
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("support_model_type_selector",
"distributed_edges")
self.core.unregister_ui("support_model_type_selector",
"distributed_corners")
self.core.unregister_ui("support_model_settings",
self.gui.get_object("DistributedSupportExpander"))
def update_support_controls(self):
grid_type = self.core.get("support_model_type")
if grid_type in ("distributed_edges", "distributed_corners"):
......
......@@ -113,6 +113,7 @@ class ModelSupportGrid(pycam.Plugins.PluginBase):
while len(adjustments) <= index:
adjustments.append(0)
adjustments[index] = value
# TODO: remove these public settings
self.core.add_item("support_grid_adjustment_value",
get_set_grid_adjustment_value, get_set_grid_adjustment_value)
self.core.register_event("support-model-changed",
......@@ -121,6 +122,14 @@ class ModelSupportGrid(pycam.Plugins.PluginBase):
self.core.set("support_grid_distance_x", 10.0)
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("support_model_type_selector", "grid")
self.core.unregister_ui("support_model_settings",
self.gui.get_object("SupportModelGridBox"))
self.core.unregister_event("support-model-changed",
self.update_support_model)
def update_support_model(self, widget=None):
grid_type = self.core.get("support_model_type")
if grid_type == "grid":
......
......@@ -45,6 +45,8 @@ class ModelSwapAxes(pycam.Plugins.PluginBase):
if self.gui:
self.core.unregister_ui("model_handling",
self.gui.get_object("ModelSwapBox"))
self.core.unregister_event("model-selection-changed",
self._update_controls)
def _update_controls(self):
box = self.gui.get_object("ModelSwapBox")
......
......@@ -100,6 +100,15 @@ class Models(pycam.Plugins.ListPluginBase):
self.core.set("models", self)
return True
def teardown(self):
if self.gui:
self.core.unregister_event("model-selection-changed",
self._get_colors_of_selected_models)
self.core.unregister_ui_section("model_handling")
self.core.unregister_ui("main", self.gui.get_object("ModelBox"))
self.core.set("models", None)
return True
def _get_colors_of_selected_models(self, widget=None):
color_button = self.gui.get_object("ModelColorButton")
models = self.get_selected()
......@@ -156,10 +165,3 @@ class Models(pycam.Plugins.ListPluginBase):
return [self[index] for index, item in enumerate(self._treemodel)
if item[self.COLUMN_VISIBLE]]
def teardown(self):
if self.gui:
self.core.unregister_ui("main", self.gui.get_object("ModelBox"))
self.core.unregister_ui_section("main", "model_handling")
self.core.set("models", None)
return True
......@@ -35,7 +35,6 @@ class OpenGLViewToolpath(pycam.Plugins.PluginBase):
def teardown(self):
self.core.unregister_event("visualize-items", self.draw_toolpath)
return True
def draw_toolpath(self):
if self.core.get("show_toolpath") \
......
......@@ -86,7 +86,7 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
self.initialized = False
self.busy = False
self.is_visible = False
self._position = [100, 100]
self._position = [200, 200]
toggle_3d = self.gui.get_object("Toggle3DView")
handler = toggle_3d.connect("toggled", self.toggle_3d_view)
self._toggle_action_handler = (toggle_3d, handler)
......@@ -187,10 +187,13 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
self.context_menu.show_all()
else:
self.context_menu = None
self.core.register_event("model-change-after", self.update_model_dimensions)
self.core.register_event("visual-item-updated", self.update_model_dimensions)
self.core.register_event("model-change-after",
self.update_model_dimensions)
self.core.register_event("visual-item-updated",
self.update_model_dimensions)
self.core.register_event("visual-item-updated", self.update_view)
self.core.register_event("visualization-state-changed", self._update_widgets)
self.core.register_event("visualization-state-changed",
self._update_widgets)
# show the window
self.area.show()
self.container.show()
......@@ -198,7 +201,17 @@ class OpenGLWindow(pycam.Plugins.PluginBase):
return True
def teardown(self):
return True
if self.gui:
self.window.hide()
self.unregister_gtk_accelerator("opengl",
self.gui.get_object("Toggle3DView"))
self.core.unregister_event("model-change-after",
self.update_model_dimensions)
self.core.unregister_event("visual-item-updated",
self.update_model_dimensions)
self.core.unregister_event("visual-item-updated", self.update_view)
self.core.unregister_event("visualization-state-changed",
self._update_widgets)
def update_view(self, widget=None, data=None):
if self.is_visible:
......
......@@ -91,8 +91,12 @@ class Toolpaths(pycam.Plugins.PluginBase):
return True
def teardown(self):
self.core.unregister_ui("preferences",
self.gui.get_object("MultiprocessingFrame"))
if self.gui:
self.process_pool_window.hide()
self.core.unregister_ui("preferences",
self.gui.get_object("MultiprocessingFrame"))
self.unregister_gtk_accelerator("processes",
self.gui.get_object("ToggleProcessPoolWindow"))
def toggle_process_pool_window(self, widget=None, value=None, action=None):
toggle_process_pool_checkbox = self.gui.get_object("ToggleProcessPoolWindow")
......
# -*- 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
# imported later (on demand)
#import gtk
import pycam.Plugins
class PluginSelector(pycam.Plugins.PluginBase):
UI_FILE = "plugin_selector.ui"
COLUMN_NAME, COLUMN_DESCRIPTION, COLUMN_ENABLED, COLUMN_DEPENDS, \
COLUMN_DEPENDS_OK, COLUMN_SOURCE = range(6)
def setup(self):
if self.gui:
import gtk
self.plugin_window = self.gui.get_object("PluginManagerWindow")
self.plugin_window.connect("delete-event",
self.toggle_plugin_window, False)
self.plugin_window.connect("destroy",
self.toggle_plugin_window, False)
self.plugin_window.add_accel_group(
self.core.get("gtk-accel-group"))
self.gui.get_object("ClosePluginManager").connect("clicked",
self.toggle_plugin_window, False)
self._treemodel = self.gui.get_object("PluginsModel")
self._treemodel.clear()
action = self.gui.get_object("TogglePluginWindow")
action.connect("toggled", self.toggle_plugin_window)
self.register_gtk_accelerator("plugins", action, None,
"TogglePluginWindow")
self.gui.get_object("PluginsEnabledCell").connect("toggled",
self.toggle_plugin_state)
self.core.register_event("plugin-list-changed",
self._update_plugin_model)
self._update_plugin_model()
return True
def teardown(self):
if self.gui:
self.plugin_window.hide()
self.core.unregister_event("plugin-list-changed",
self._update_plugin_model)
def toggle_plugin_window(self, widget=None, value=None, action=None):
toggle_plugin_button = self.gui.get_object("TogglePluginWindow")
checkbox_state = toggle_plugin_button.get_active()
if value is None:
new_state = checkbox_state
else:
if action is None:
new_state = value
else:
new_state = action
if new_state:
self.plugin_window.show()
else:
self.plugin_window.hide()
toggle_plugin_button.set_active(new_state)
# don't destroy the window with a "destroy" event
return True
def _update_plugin_model(self):
manager = self.core.get("plugin-manager")
names = manager.get_plugin_names()
model = self._treemodel
model.clear()
for name in names:
plugin = manager.get_plugin(name)
enabled = manager.get_plugin_state(name)
depends_missing = manager.get_plugin_missing_dependencies(name)
is_required = manager.is_plugin_required(name)
satisfied = not (bool(depends_missing) or is_required)
# never disable the manager
if plugin == self:
satisfied = False
depends_markup = []
for depend in plugin.DEPENDS:
if depend in depends_missing:
depends_markup.append(
'<span foreground="red">%s</span>' % depend)
else:
depends_markup.append(depend)
model.append((name, "Beschreibung", enabled,
os.linesep.join(depends_markup), satisfied,
str(plugin.__class__)))
self.gui.get_object("PluginsDescriptionColumn").queue_resize()
self.gui.get_object("PluginsTable").queue_resize()
def toggle_plugin_state(self, cell, path):
plugin_name = self._treemodel[int(path)][self.COLUMN_NAME]
manager = self.core.get("plugin-manager")
enabled = manager.get_plugin_state(plugin_name)
if enabled:
manager.disable_plugin(plugin_name)
else:
manager.enable_plugin(plugin_name)
self._update_plugin_model()
......@@ -105,6 +105,10 @@ class Processes(pycam.Plugins.ListPluginBase):
def teardown(self):
if self.gui:
self.core.unregister_ui("main", self.gui.get_object("ProcessBox"))
self.core.unregister_event("process-selection-changed",
self._process_switch)
self.core.unregister_event("process-changed",
self._store_process_settings)
self.core.set("processes", None)
return True
......
......@@ -38,12 +38,16 @@ class ProgressBar(pycam.Plugins.PluginBase):
self.core.register_ui("main_window", "Progress", box, 50)
self.core.add_item("progress", lambda: ProgressGTK(self.core, self.gui))
show_progress_button = self.gui.get_object("ShowToolpathProgressButton")
# TODO: move this setting somewhere else or rename it
self.core.add_item("show_drill_progress",
show_progress_button.get_active,
show_progress_button.set_active)
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("main_window",
self.gui.get_object("ProgressBox"))
self.core.set("progress", None)
......
......@@ -119,6 +119,15 @@ class Tasks(pycam.Plugins.ListPluginBase):
self.core.set("tasks", self)
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("main", self.gui.get_object("TaskBox"))
self.core.unregister_event("task-selection-changed",
self._switch_task)
self.core.unregister_event("task-selection-changed",
self._switch_task)
self.core.unregister_event("task-changed", self._store_task)
def _get_modelview_and_content(self, category):
model = {None: self._taskview,
"tool": self.gui.get_object("ToolSelector"),
......
......@@ -36,6 +36,7 @@ TODO:
class ToolpathCrop(pycam.Plugins.PluginBase):
UI_FILE = "toolpath_crop.ui"
DEPENDS = ["Toolpaths"]
def setup(self):
if self.gui:
......
......@@ -37,6 +37,9 @@ class ToolpathGrid(pycam.Plugins.PluginBase):
# TODO: add a button to the toolpath action UI
return True
def teardown(self):
pass
def update_toolpath_grid_window(self, widget=None):
data = self._toolpath_for_grid_data
x_dim = data["maxx"] - data["minx"]
......
......@@ -60,6 +60,9 @@ class ToolpathSimulation(pycam.Plugins.PluginBase):
sim_detail_obj.get_value, sim_detail_obj.set_value)
return True
def teardown(self):
pass
def finish_toolpath_simulation(self, widget=None, data=None):
# hide the simulation tab
self.simulation_window.hide()
......
......@@ -68,13 +68,12 @@ class Toolpaths(pycam.Plugins.ListPluginBase):
self.register_gtk_accelerator("toolpaths", export_all,
"<Control><Shift>e", "ExportGCodeAll")
export_all.connect("activate", self.save_toolpath, False)
export_visible = self.gui.get_object("ExportGCodeSelected")
self.register_gtk_accelerator("toolpaths", export_visible,
export_selected = self.gui.get_object("ExportGCodeSelected")
self.register_gtk_accelerator("toolpaths", export_selected,
None, "ExportGCodeSelected")
export_visible.connect("activate", self.save_toolpath, True)
export_selected.connect("activate", self.save_toolpath, True)
# model handling
def update_model():
print "UPDATE"
if not hasattr(self, "_model_cache"):
self._model_cache = {}
cache = self._model_cache
......@@ -96,8 +95,15 @@ class Toolpaths(pycam.Plugins.ListPluginBase):
return True
def teardown(self):
if self.gui:
self.core.unregister_ui("main", self.gui.get_object("ToolpathsBox"))
self.unregister_gtk_accelerator("toolpaths",
self.gui.get_object("ExportGCodeAll"))
self.unregister_gtk_accelerator("toolpaths",
self.gui.get_object("ExportGCodeSelected"))
self.core.unregister_event("toolpath-list-changed",
self._update_widgets)
self.core.set("toolpaths", None)
return True
def get_selected(self):
return self._get_selected(self._modelview, force_list=True)
......@@ -152,8 +158,8 @@ class Toolpaths(pycam.Plugins.ListPluginBase):
self.core.get("gcode_safety_height")))
cell.set_property("text", text)
def save_toolpath(self, widget=None, only_visible=False):
if only_visible:
def save_toolpath(self, widget=None, only_selected=False):
if only_selected:
toolpaths = self.get_selected()
else:
toolpaths = self
......
......@@ -100,6 +100,10 @@ class Tools(pycam.Plugins.ListPluginBase):
def teardown(self):
if self.gui:
self.core.unregister_ui("main", self.gui.get_object("ToolBox"))
self.core.unregister_event("tool-selection-changed",
self._tool_change)
self.core.unregister_event("tool-changed",
self._update_tool_controls)
self.core.set("tools", None)
return True
......
......@@ -51,8 +51,10 @@ class Toolpaths(pycam.Plugins.PluginBase):
return True
def teardown(self):
self.core.unregister_ui("preferences_general",
self.gui.get_object("UnitPrefBox"))
if self.gui:
self.core.unregister_ui("preferences_general",
self.gui.get_object("UnitPrefBox"))
# TODO: reset setting "unit" back to a default value?
def change_unit_init(self, widget=None):
new_unit = self.gui.get_object("unit_control").get_active_text()
......
......@@ -70,6 +70,7 @@ class PluginBase(object):
else:
self.log.debug("Failed to locate icon: %s" % self.ICONS[key])
self.ICONS[key] = None
self.enabled = True
def setup(self):
raise NotImplementedError(("Module %s (%s) does not implement " + \
......@@ -96,12 +97,19 @@ class PluginBase(object):
actiongroup.add_action(action)
self.core.get("gtk-uimanager").insert_action_group(actiongroup, pos=-1)
def unregister_gtk_accelerator(self, groupname, action):
actiongroup = gtk.ActionGroup(groupname)
actiongroup.remove_action(action)
if len(actiongroup.list_actions()) == 0:
self.core.get("gtk-uimanager").remove_action_group(actiongroup)
class PluginManager(object):
def __init__(self, core):
self.core = core
self.modules = {}
self.core.set("plugin-manager", self)
def import_plugins(self, directory=None):
if directory is None:
......@@ -163,10 +171,75 @@ class PluginManager(object):
_log.info("Failed to setup plugin '%s'" % str(plugin_name))
else:
self.modules[plugin_name] = new_plugin
self.core.emit_event("plugin-list-changed")
except NotImplementedError, err_msg:
_log.info("Skipping incomplete plugin '%s': %s" % \
(plugin_name, err_msg))
def get_plugin(self, name):
long_name = "%s.%s" % (name, name)
if name in self.modules:
return self.modules[name]
elif long_name in self.modules:
return self.modules[long_name]
else:
raise KeyError("Plugin '%s' is not available" % name)
def enable_plugin(self, name):
plugin = self.get_plugin(name)
if plugin.enabled:
self.log.debug("Refused to enable an active plugin: %s" % name)
return
else:
plugin.enabled = plugin.setup()
def disable_plugin(self, name):
plugin = self.get_plugin(name)
if not plugin.enabled:
self.log.debug("Refused to disable an active plugin: %s" % name)
return
else:
plugin.teardown()
plugin.enabled = False
def get_plugin_state(self, name):
plugin = self.get_plugin(name)
return plugin.enabled
def get_plugins(self):
return list(self.modules.values())
def get_plugin_names(self):
names = self.modules.keys()
names.sort()
return names
def is_plugin_required(self, name):
long_name = "%s.%s." % (name, name)
for plugin in self.modules.values():
if not plugin.enabled:
continue
if (name in plugin.DEPENDS) or \
(long_name in plugin.DEPENDS):
break
else:
return False
return True
def get_plugin_missing_dependencies(self, name):
plugin = self.get_plugin(name)
missing = []
for depend in plugin.DEPENDS:
long_depend = "%s.%s" % (depend, depend)
if (depend in self.modules) and self.modules[depend].enabled:
continue
elif (long_depend in self.modules) and \
(self.modules[long_depend].enabled):
continue
else:
missing.append(depend)
return missing
class ListPluginBase(PluginBase, list):
......
......@@ -23,5 +23,5 @@ along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
__all__ = ["Cutters", "Exporters", "Geometry", "Gui", "Importers",
"PathGenerators", "PathProcessors", "Utils"]
VERSION = "0.5.1"
VERSION = "0.6-svn"
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