Skip to content

Commit

Permalink
Merge pull request #136 from mpsonntag/nixvalues
Browse files Browse the repository at this point in the history
Implementing nixstyle values core odml library changes

LGTM
  • Loading branch information
achilleas-k authored Nov 24, 2018
2 parents 9dc79b0 + fe766d4 commit e8b026a
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 23 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ until the next release.

# Latest changes in master

...

# Version 1.4.2

## Implementing core odml library changes
The core odml library deprecated `Property.value` in favor of
the newly added attribute `Property.values`. These changes
have been introduced in odml-ui as well.

## Edit terminology values fixes

In some cases the values of terminology loaded Properties could not
Expand All @@ -19,6 +28,7 @@ are checked and modified in case the "pseudo_value" attribute is missing.
properly deactivated. See #90.
- The PropertyView is now properly reset when the last Section is removed from a
Document making sure there are no stale leftover Properties on display.
- Fixes errors on 'Undo' and 'Redo' when adding or removing Values.

# Version 1.4.1

Expand Down
8 changes: 8 additions & 0 deletions odmlui/Editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1099,11 +1099,19 @@ def enable_redo(self, enable=True):
def undo(self, action):
self.current_tab.command_manager.undo()

# Reset model and view in case a value has been tampered with
# to avoid Model and View being out of sync.
self._property_tv.reset_value_view(None)

@gui_action("Redo", tooltip="Redo an undone editing action", stock_id=gtk.STOCK_REDO,
label="_Redo", accelerator="<control>Y")
def redo(self, action):
self.current_tab.command_manager.redo()

# Reset model and view in case a value has been tampered with
# to avoid Model and View being out of sync.
self._property_tv.reset_value_view(None)

def command_error(self, cmd, error):
self._info_bar.show_info("Editing failed: %s" % error)

Expand Down
8 changes: 4 additions & 4 deletions odmlui/Helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,18 @@ def handle_property_import(prop):
:param prop: imported odml.BaseProperty
"""
if len(prop._value) < 1:
if len(prop.values) < 1:
if prop.dtype:
prop._value = [default_values(prop.dtype)]
prop.values = [default_values(prop.dtype)]
else:
prop._value = [default_values('string')]
prop.values = [default_values('string')]

create_pseudo_values([prop])


def create_pseudo_values(odml_properties):
for prop in odml_properties:
values = prop.value
values = prop.values
new_values = []
for index in range(len(values)):
val = ValueModel.Value(prop, index)
Expand Down
28 changes: 22 additions & 6 deletions odmlui/PropertyView.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from odml import DType
from odml.property import BaseProperty

from odmlui.treemodel.nodes import Property as TreeModelProperty

from . import commands
from . import TextEditor
from .DragProvider import DragProvider
Expand Down Expand Up @@ -116,7 +118,7 @@ def on_selection_change(self, tree_selection):
self.on_property_select(obj)

# Always expand multi value properties when selected
is_multi_value = isinstance(obj, BaseProperty) and len(obj.value) > 1
is_multi_value = isinstance(obj, BaseProperty) and len(obj.values) > 1
if is_multi_value:
tree_selection.get_tree_view().expand_row(model.get_path(tree_iter), False)

Expand Down Expand Up @@ -204,12 +206,12 @@ def get_popup_menu_items(self):
if hasattr(obj, "_property"): # we care about the properties only
prop = obj._property

value_filter = lambda prop: [val for val in prop.values if val.value is not None and val.value != ""]
value_filter = lambda prop: [val for val in prop.values if val.values is not None and val.values != ""]
for item in self.create_popup_menu_items("Add Value", "Empty Value", prop, self.add_value,
value_filter, lambda val: val.value, stock="odml-add-Value"):
value_filter, lambda val: val.values, stock="odml-add-Value"):
menu_items.append(item)
for item in self.create_popup_menu_items("Set Value", "Empty Value", prop, self.set_value,
value_filter, lambda val: val.value):
value_filter, lambda val: val.values):
if item.get_submenu() is None:
continue # don't want a sole Set Value item
menu_items.append(item)
Expand Down Expand Up @@ -286,7 +288,7 @@ def add_value(self, widget, obj_value_pair):
self.execute(cmd)

# Reset model if the Value changes from "normal" to MultiValue.
if self.model and len(obj.value) > 1:
if self.model and len(obj.values) > 1:
self.model.destroy()
self.model = PropertyModel.PropertyModel(obj.parent)

Expand All @@ -304,7 +306,7 @@ def add_property(self, widget, obj_prop_pair):
name = self.get_new_obj_name(obj.properties, prefix='Unnamed Property')
prop = odml.Property(name=name, dtype='string')
# The default value part should be put in odML core library
prop._value = [dtypes.default_values('string')]
prop.values = [dtypes.default_values('string')]
create_pseudo_values([prop])
else:
prefix = prop.name
Expand All @@ -315,6 +317,20 @@ def add_property(self, widget, obj_prop_pair):
cmd = commands.AppendValue(obj=obj, val=prop)
self.execute(cmd)

def reset_value_view(self, widget):
"""
Reset the view if the value model has changed e.g. after an undo or a redo.
"""
obj = self.get_selected_object()
if obj is None or not isinstance(obj, TreeModelProperty):
return

self.model.destroy()
self.model = PropertyModel.PropertyModel(obj.parent)

# Reselect updated object to update view.
self.select_object(obj)

# Maybe define a generic Combo Box column creator ?
def create_odml_types_col(self, id, name, propname):

Expand Down
39 changes: 30 additions & 9 deletions odmlui/treemodel/ValueModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Value(BaseObject, ValueNode, event.ModificationNotifier):
A list of objects from this class is added as an additional attribute to
the original `odml.Property` node, as `pseudo_values`. All interactions
from the Editor interact with these pseudo_values, and internally, these
pseudo-values update the original property._value list.
pseudo-values update the original property.values list.
"""
_Changed = event.Event("value")
Expand All @@ -43,22 +43,40 @@ def __init__(self, parent, index=None):

self._property = parent
if index is None: # Instantiate a new odML value
index = len(self._property.value)
index = len(self._property.values)
dtype = self.parent.dtype
default_value = dtypes.default_values(dtype)
# property.value returns a copy: we therefore need an in between step
# property.values returns a copy: we therefore need an in between step
# to append a new value and reassign the modified value to the parent
# property.value.
val_cp = self.parent.value
# property.values.
val_cp = self.parent.values
val_cp.append(default_value)
self.parent.value = val_cp
self.parent.values = val_cp

assert(isinstance(index, int))
self._index = index

def __repr__(self):
return "PseudoValue <%s>" % str(self.pseudo_values)

def __eq__(self, obj):
"""
Make sure all relevant attributes are properly compared.
:param obj: odmlui PseudoValue
:return: Boolean
"""
if not isinstance(obj, self.__class__):
return False

if not self.parent == obj.parent:
return False

if not self.pseudo_values == obj.pseudo_values:
return False

return True

@property
def parent(self):
"""the property containing this value"""
Expand All @@ -76,7 +94,7 @@ def pseudo_values(self):
"""
Return a single element from the parent property's value list.
"""
return self.parent._value[self._index]
return self.parent._values[self._index]

@pseudo_values.setter
def pseudo_values(self, new_string):
Expand All @@ -86,7 +104,10 @@ def pseudo_values(self, new_string):
"""
prop_dtype = self.parent.dtype
new_value = dtypes.get(new_string, prop_dtype)
self.parent._value[self._index] = new_value

set_values = self.parent.values
set_values[self._index] = new_value
self.parent.values = set_values

@property
def value(self):
Expand Down Expand Up @@ -132,7 +153,7 @@ def get_display(self, max_length=-1):
return "(%d bytes)" % len(self._value)

def reorder(self, new_index):
return self._reorder(self.parent.value, new_index)
return self._reorder(self.parent.values, new_index)

def clone(self):
obj = BaseObject.clone(self)
Expand Down
6 changes: 3 additions & 3 deletions odmlui/treemodel/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,11 @@ def remove_value(prop, pseudo):
for pval in prop.pseudo_values[pseudo._index:]:
pval._index = pval._index - 1
# Finally remove the actual value from the property value list.
# Property.value always returns a copy so we need to modify and reassign
# Property.values always returns a copy so we need to modify and reassign
# the affected values.
cp_val = prop.value
cp_val = prop.values
del cp_val[pseudo._index]
prop._value = cp_val
prop.values = cp_val

# create a separate global Event listeners for each class
# and provide ModificationNotifier Capabilities
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class PackageNotFoundError(Exception):
'odmlui.treemodel'
]

install_req = ["odml>=1.4.*"]
install_req = ["odml>=1.4.2"]

data_files = [('share/pixmaps', glob.glob(os.path.join("images", "*"))),
('share/odmlui', ['LICENSE'])]
Expand Down

0 comments on commit e8b026a

Please sign in to comment.