Skip to content

Commit

Permalink
Merge pull request #336 from gaphor/namespace-show-all
Browse files Browse the repository at this point in the history
Namespace show all
  • Loading branch information
amolenaar committed Jun 4, 2020
2 parents ec2d2c8 + edd6a43 commit 23f6219
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 156 deletions.
15 changes: 15 additions & 0 deletions gaphor/UML/tests/test_umllex.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,21 @@ def test_parse_association_end_derived_end(factory):
assert not p.defaultValue


def test_parse_association_end_with_type(factory):
"""Test parsing of association end, type is ignored
"""
a = factory.create(UML.Association)
p = factory.create(UML.Property)
p.association = a

UML.parse(p, "end: TypeVal")
assert "end" == p.name
assert not p.typeValue
assert not p.lowerValue
assert not p.upperValue
assert not p.defaultValue


def test_parse_operation(factory):
"""Test parsing simple operation
"""
Expand Down
11 changes: 5 additions & 6 deletions gaphor/UML/umlfmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,8 @@ def format_attribute(
will not give you the same result.
"""
name = el.name
if not name:
return name

if no_render_pat.match(name):
if name and no_render_pat.match(name):
return name

# Render all fields if they all are set to False
Expand All @@ -71,14 +69,15 @@ def format_attribute(

s = []

if visibility:
if name and visibility:
s.append(vis_map[el.visibility])
s.append(" ")

if is_derived and el.isDerived:
if name and is_derived and el.isDerived:
s.append("/")

s.append(name)
if name:
s.append(name)

if type and el.typeValue:
s.append(f": {el.typeValue}")
Expand Down
12 changes: 8 additions & 4 deletions gaphor/UML/umllex.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ def parse(el, text):
# name (required) ::= name
name_subpat = r"\s*(?P<name>[a-zA-Z_]\w*)"

# Multiplicity (added to type_subpat) ::= '[' [mult_l ..] mult_u ']'
# Multiplicity ::= '[' [mult_l ..] mult_u ']'
mult_subpat = r"\s*(\[\s*((?P<mult_l>[0-9]+)\s*\.\.)?\s*(?P<mult_u>([0-9]+|\*))\s*\])?"
multa_subpat = r"\s*(\[?((?P<mult_l>[0-9]+)\s*\.\.)?\s*(?P<mult_u>([0-9]+|\*))\]?)?"

# Type and multiplicity (optional) ::= ':' type [mult]
type_subpat = r"\s*(:\s*(?P<type>\w+)\s*" + mult_subpat + r")?"
# Type and multiplicity (optional) ::= ':' type
type_subpat = r"\s*(:\s*(?P<type>\w+))?"

# default value (optional) ::= '=' default
default_subpat = r"\s*(=\s*(?P<default>\S+))?"
Expand Down Expand Up @@ -72,6 +72,7 @@ def compile(regex):
+ derived_subpat
+ name_subpat
+ type_subpat
+ mult_subpat
+ default_subpat
+ tags_subpat
+ garbage_subpat
Expand All @@ -85,6 +86,7 @@ def compile(regex):
+ vis_subpat
+ derived_subpat
+ name_subpat
+ type_subpat
+ mult_subpat
+ ")?"
+ tags_subpat
Expand All @@ -103,6 +105,7 @@ def compile(regex):
+ name_subpat
+ params_subpat
+ type_subpat
+ mult_subpat
+ tags_subpat
+ garbage_subpat
)
Expand All @@ -114,14 +117,15 @@ def compile(regex):
+ dir_subpat
+ name_subpat
+ type_subpat
+ mult_subpat
+ default_subpat
+ tags_subpat
+ rest_subpat
)

# Lifeline:
# [name] [: type]
lifeline_pat = compile("^" + name_subpat + type_subpat + garbage_subpat)
lifeline_pat = compile("^" + name_subpat + type_subpat + mult_subpat + garbage_subpat)


def _set_visibility(el: uml.Feature, vis: str):
Expand Down
63 changes: 28 additions & 35 deletions gaphor/ui/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,13 @@
from gaphor.ui.actiongroup import create_action_group
from gaphor.ui.event import DiagramOpened
from gaphor.ui.iconname import get_icon_name
from gaphor.UML.umlfmt import format_attribute, format_operation
from gaphor.UML.umllex import parse

if TYPE_CHECKING:
from gaphor.core.modeling import ElementFactory
from gaphor.core.eventmanager import EventManager

# The following items will be shown in the treeview, although they
# are UML.Namespace elements.
_default_filter_list = (
UML.Class,
UML.Interface,
UML.Package,
UML.Component,
UML.Device,
UML.Node,
UML.Artifact,
UML.Interaction,
UML.UseCase,
UML.Actor,
Diagram,
UML.Profile,
UML.Stereotype,
UML.Property,
UML.Operation,
)


log = logging.getLogger(__name__)

Expand Down Expand Up @@ -120,10 +102,15 @@ def expand_root_nodes(self):
def _set_pixbuf(self, column, cell, model, iter, data):
element = model.get_value(iter, 0)

icon_name = get_icon_name(element)
if isinstance(element, (UML.Property, UML.Operation)):
cell.set_property("icon-name", None)
cell.set_property("visible", False)
else:
icon_name = get_icon_name(element)
cell.set_property("visible", True)

if icon_name:
cell.set_property("icon-name", icon_name)
if icon_name:
cell.set_property("icon-name", icon_name)

def _set_text(self, column, cell, model, iter, data):
"""
Expand All @@ -138,6 +125,10 @@ def _set_text(self, column, cell, model, iter, data):
isinstance(element, UML.Classifier) or isinstance(element, UML.Operation)
) and element.isAbstract:
text = f"<i>{text}</i>"
elif isinstance(element, UML.Property):
text = format_attribute(element) or "&lt;None&gt;"
elif isinstance(element, UML.Operation):
text = format_operation(element)

cell.set_property("markup", text)

Expand All @@ -152,7 +143,10 @@ def _text_edited(self, cell, path_str, new_text):
model = self.get_property("model")
iter = model.get_iter_from_string(path_str)
element = model.get_value(iter, 0)
element.name = new_text
if isinstance(element, (UML.Property, UML.Operation)):
parse(element, new_text)
else:
element.name = new_text
except Exception:
log.error(f'Could not create path from string "{path_str}"')

Expand Down Expand Up @@ -213,7 +207,7 @@ def on_drag_data_received(self, context, x, y, selection, info, time):
element = self.element_factory.lookup(element_id)
assert isinstance(
element, (Diagram, UML.Package, UML.Type)
), f"Element with id {element_id} is not part of the model"
), f"Element {element} can not be moved"
path, position = drop_info
iter = model.get_iter(path)
dest_element = model.get_value(iter, 0)
Expand Down Expand Up @@ -259,7 +253,6 @@ def __init__(self, event_manager: EventManager, element_factory: ElementFactory)
self.element_factory = element_factory
self._namespace: Optional[NamespaceView] = None
self.model = Gtk.TreeStore.new([object])
self.toplevel_types = _default_filter_list

def open(self):
em = self.event_manager
Expand Down Expand Up @@ -406,10 +399,11 @@ def iter_for_element(self, element, old_namespace=0):
return None

def _visible(self, element):
# Special case: Non-navigable properties
return type(element) in self.toplevel_types and not (
isinstance(element, UML.Property) and element.namespace is None
)
""" Special case: Non-navigable properties. """
return (
(isinstance(element, UML.NamedElement) and element.namespace)
or isinstance(element, UML.PackageableElement)
) and not isinstance(element, (UML.InstanceSpecification, UML.Relationship))

def _add(self, element, iter=None):
if self._visible(element):
Expand All @@ -431,13 +425,12 @@ def _on_model_ready(self, event=None):
self.model.clear()

toplevel = self.element_factory.select(
lambda e: isinstance(e, UML.NamedElement)
and type(e) in self.toplevel_types
and not e.namespace
lambda e: isinstance(e, UML.PackageableElement) and not e.namespace
)

for element in toplevel:
self._add(element)
if self._visible(element):
self._add(element)

# Expand all root elements:
if self._namespace: # None for testing
Expand All @@ -458,7 +451,7 @@ def _on_element_create(self, event: ElementCreated):
@event_handler(ElementDeleted)
def _on_element_delete(self, event: ElementDeleted):
element = event.element
if type(element) in self.toplevel_types:
if isinstance(element, UML.NamedElement):
iter = self.iter_for_element(element)
# iter should be here, unless we try to delete an element who's
# parent element is already deleted, so let's be lenient.
Expand Down
2 changes: 1 addition & 1 deletion gaphor/ui/tests/test_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_root_element(namespace, element_factory):


def test_should_not_add_non_namespace_element(namespace, element_factory):
element_factory.create(UML.Activity)
element_factory.create(UML.Action)

assert namespace.model.iter_n_children(None) == 0

Expand Down

0 comments on commit 23f6219

Please sign in to comment.