1
|
|
|
# -*- coding: utf-8 -*- |
2
|
|
|
# |
3
|
|
|
# This file is part of SENAITE.CORE |
4
|
|
|
# |
5
|
|
|
# Copyright 2018 by it's authors. |
6
|
|
|
# Some rights reserved. See LICENSE.rst, CONTRIBUTORS.rst. |
7
|
|
|
|
8
|
|
|
from Products.CMFCore.utils import getToolByName |
9
|
|
|
from bika.lims import logger |
10
|
|
|
from bika.lims.interfaces import IATWidgetVisibility |
11
|
|
|
from types import DictType |
12
|
|
|
from plone import api |
13
|
|
|
from Acquisition import aq_base |
14
|
|
|
from zope.component import getAdapters |
15
|
|
|
|
16
|
|
|
_marker = [] |
17
|
|
|
|
18
|
|
|
# Products.Archetypes.Schema.Schemata#editableFields |
19
|
|
|
def editableFields(self, instance, visible_only=False): |
20
|
|
|
"""Returns a list of editable fields for the given instance |
21
|
|
|
""" |
22
|
|
|
ret = [] |
23
|
|
|
portal = getToolByName(instance, 'portal_url').getPortalObject() |
24
|
|
|
for field in self.fields(): |
25
|
|
|
if field.writeable(instance, debug=False) and \ |
26
|
|
|
(not visible_only or |
27
|
|
|
field.widget.isVisible( |
28
|
|
|
instance, mode='edit', field=field) != 'invisible') and \ |
29
|
|
|
field.widget.testCondition(instance.aq_parent, portal, instance): |
30
|
|
|
ret.append(field) |
31
|
|
|
return ret |
32
|
|
|
|
33
|
|
|
|
34
|
|
|
# Products.Archetypes.Widget.TypesWidget#isVisible |
35
|
|
|
def isVisible(self, instance, mode='view', default="visible", field=None): |
36
|
|
|
"""decide if a field is visible in a given mode -> 'state'. |
37
|
|
|
""" |
38
|
|
|
# Emulate Products.Archetypes.Widget.TypesWidget#isVisible first |
39
|
|
|
vis_dic = getattr(aq_base(self), 'visible', _marker) |
40
|
|
|
state = default |
41
|
|
|
if vis_dic is _marker: |
42
|
|
|
return state |
43
|
|
|
if type(vis_dic) is DictType: |
44
|
|
|
state = vis_dic.get(mode, state) |
45
|
|
|
elif not vis_dic: |
46
|
|
|
state = 'invisible' |
47
|
|
|
elif vis_dic < 0: |
48
|
|
|
state = 'hidden' |
49
|
|
|
|
50
|
|
|
# Our custom code starts here |
51
|
|
|
if not field: |
52
|
|
|
return state |
53
|
|
|
|
54
|
|
|
# Look for visibility from the adapters provided by IATWidgetVisibility |
55
|
|
|
adapters = sorted(getAdapters([instance], IATWidgetVisibility), |
56
|
|
|
key=lambda adapter: getattr(adapter[1], "sort", 1000), |
57
|
|
|
reverse=True) |
58
|
|
|
for adapter_name, adapter in adapters: |
59
|
|
|
if field.getName() not in getattr(adapter, "field_names", []): |
60
|
|
|
# Omit those adapters that are not suitable for this field |
61
|
|
|
continue |
62
|
|
|
adapter_state = adapter(instance, mode, field, state) |
63
|
|
|
adapter_name = adapter.__class__.__name__ |
64
|
|
|
logger.info("IATWidgetVisibility rule {} for {}.{} ({}): {} -> {}" |
65
|
|
|
.format(adapter_name, instance.id, field.getName(), mode, state, |
66
|
|
|
adapter_state)) |
67
|
|
|
if adapter_state == state: |
68
|
|
|
continue |
69
|
|
|
return adapter_state |
70
|
|
|
|
71
|
|
|
return state |
72
|
|
|
|