diff --git a/product/ERP5Form/ListBox.py b/product/ERP5Form/ListBox.py index 5072ad22782c2e202b57f927124033842f893328..b9b0fa56102147894b67ea8261b75dbccda591c9 100755 --- a/product/ERP5Form/ListBox.py +++ b/product/ERP5Form/ListBox.py @@ -34,7 +34,7 @@ from Products.Formulator.Field import ZMIField from Products.Formulator.Form import BasicForm from Products.Formulator.Errors import FormValidationError, ValidationError from Products.Formulator.MethodField import BoundMethod -from Selection import Selection +from Selection import Selection, DomainSelection from DateTime import DateTime from Products.ERP5Type.Utils import getPath from Products.ERP5Type.Document import newTempBase @@ -45,65 +45,152 @@ from Acquisition import aq_base, aq_inner, aq_parent, aq_self from zLOG import LOG import random -import md5 - +import md5 + def getAsList(a): l = [] for e in a: l.append(e) return l -def makeTreeBody(root, depth, total_depth, unfolded_list, form_id, selection_name): - +def makeTreeBody(form, root_dict, domain_path, depth, total_depth, unfolded_list, form_id, selection_name): + """ + This method builds a report tree + + domain_path -- ('region', 'skill', 'group', 'group', 'region') + + root -- {'region': <instance>, 'group'; instance} + + """ + LOG('makeTreeBody root_dict', 0, str(root_dict)) + LOG('makeTreeBody domain_path', 0, str(domain_path)) + LOG('makeTreeBody unfolded_list', 0, str(unfolded_list)) + + if total_depth is None: + total_depth = max(1, len(unfolded_list)) + + if type(domain_path) is type('a'): domain_path = domain_path.split('/') + + portal_categories = getattr(form, 'portal_categories', None) + portal_domains = getattr(form, 'portal_domains', None) + portal_object = form.portal_url.getPortalObject() + + if len(domain_path): + base_category = domain_path[0] + else: + base_category = None + + if root_dict is None: + root_dict = {} + + is_empty_level = 1 + while is_empty_level: + if not root_dict.has_key(base_category): + root = None + if portal_categories is not None: + if base_category in portal_categories.objectIds(): + root = root_dict[base_category] = root_dict[None] = portal_categories[base_category] + domain_path = domain_path[1:] + if root is None and portal_domains is not None: + if base_category in portal_domains.objectIds(): + root = root_dict[base_category] = root_dict[None] = portal_domains[base_category] + domain_path = domain_path[1:] + if root is None: + try: + root = root_dict[None] = portal_object.unrestrictedTraverse(domain_path) + except KeyError: + root = None + domain_path = () + else: + root = root_dict[None] = root_dict[base_category] + if len(domain_path) >= 1: + domain_path = domain_path[1:] + else: + domain_path = () + is_empty_level = (len(root.objectIds()) == 0) and (domain_path is not ()) + if is_empty_level: base_category = domain_path[0] + tree_body = '' - unfolded_ids = [] - for t in unfolded_list: - if len(t) > 0: - unfolded_ids += [t[0]] + if root is None: return tree_body for o in root.objectValues(): tree_body += '<TR>' + '<TD WIDTH="16" NOWRAP>' * depth - if o.id in unfolded_ids: + if o.getRelativeUrl() in unfolded_list: tree_body += """<TD NOWRAP VALIGN="TOP" ALIGN="LEFT" COLSPAN="%s"> -<a href="portal_selections/setDomainList?domain_list_url=%s&form_id=%s&list_selection_name=%s" >- <b>%s</b></a> -</TD>""" % (total_depth - depth + 1, o.getUrl() , form_id, selection_name, o.id) - new_unfolded_list = [] - for t in unfolded_list: - if len(t) > 0: - if t[0] == o.id: - new_unfolded_list += [t[1:]] - tree_body += makeTreeBody(o, depth + 1, total_depth, new_unfolded_list, form_id, selection_name) +<a href="portal_selections/foldDomain?domain_url=%s&form_id=%s&list_selection_name=%s&domain_depth:int=%s" >- <b>%s</b></a> +</TD>""" % (total_depth - depth + 1, o.getRelativeUrl() , form_id, selection_name, depth, o.id) + new_root_dict = root_dict.copy() + new_root_dict[None] = new_root_dict[base_category] = o + tree_body += makeTreeBody(form, new_root_dict, domain_path, depth + 1, total_depth, unfolded_list, form_id, selection_name) else: tree_body += """<TD NOWRAP VALIGN="TOP" ALIGN="LEFT" COLSPAN="%s"> -<a href="portal_selections/setDomainList?domain_list_url=%s&form_id=%s&list_selection_name=%s" >+ %s</a> -</TD>""" % (total_depth - depth + 1, o.getUrl() , form_id, selection_name, o.id) +<a href="portal_selections/unfoldDomain?domain_url=%s&form_id=%s&list_selection_name=%s&domain_depth:int=%s" >+ %s</a> +</TD>""" % (total_depth - depth + 1, o.getRelativeUrl() , form_id, selection_name, depth, o.id) return tree_body -def makeTreeList(root, depth, total_depth, unfolded_list, form_id, selection_name): +def makeTreeList(form, root_dict, report_path, depth, unfolded_list, form_id, selection_name, report_depth): """ - (object, is_pure_summary, depth, is_open) + (object, is_pure_summary, depth, is_open, select_domain_dict) + + select_domain_dict is a dictionary of associative list of (id, domain) """ - + if type(report_path) is type('a'): report_path = report_path.split('/') + + portal_categories = getattr(form, 'portal_categories', None) + portal_domains = getattr(form, 'portal_domains', None) + portal_object = form.portal_url.getPortalObject() + + if len(report_path): + base_category = report_path[0] + else: + base_category = None + + if root_dict is None: + root_dict = {} + + is_empty_level = 1 + while is_empty_level: + if not root_dict.has_key(base_category): + root = None + if portal_categories is not None: + if base_category in portal_categories.objectIds(): + root = root_dict[base_category] = root_dict[None] = portal_categories[base_category] + report_path = report_path[1:] + if root is None and portal_domains is not None: + if base_category in portal_domains.objectIds(): + root = root_dict[base_category] = root_dict[None] = portal_domains[base_category] + report_path = report_path[1:] + if root is None: + try: + root = root_dict[None] = portal_object.unrestrictedTraverse(report_path) + except KeyError: + root = None + report_path = () + else: + root = root_dict[None] = root_dict[base_category] + if len(report_path) >= 1: + report_path = report_path[1:] + else: + report_path = () + is_empty_level = 0 # Stop infinite loop + is_empty_level = (len(root.objectIds()) == 0) and (report_path is not ()) + if is_empty_level: base_category = report_path[0] + tree_list = [] - unfolded_ids = [] - for t in unfolded_list: - if len(t) > 0: - unfolded_ids += [t[0]] + if root is None: return tree_list for o in root.objectValues(): - if o.id in unfolded_ids: - tree_list += [(o, 1, depth, 1)] - new_unfolded_list = [] - for t in unfolded_list: - if len(t) > 0: - if t[0] == o.id: - new_unfolded_list += [t[1:]] - tree_list += [(o, 0, depth, 0)] - tree_list += makeTreeList(o, depth + 1, total_depth, new_unfolded_list, form_id, selection_name) + new_root_dict = root_dict.copy() + new_root_dict[None] = new_root_dict[base_category] = o + selection_domain = DomainSelection(domain_dict = new_root_dict) + if (report_depth is not None and depth <= (report_depth - 1)) or o.getRelativeUrl() in unfolded_list: + tree_list += [(o, 1, depth, 1, selection_domain)] # Summary (open) + tree_list += [(o, 0, depth, 0, selection_domain)] # List (contents, closed, must be strict selection) + tree_list += makeTreeList(form, new_root_dict, report_path, depth + 1, unfolded_list, form_id, selection_name, report_depth) else: - tree_list += [(o, 1, depth, 0)] - + tree_list += [(o, 1, depth, 0, selection_domain)] # Summary (closed) + return tree_list @@ -358,10 +445,15 @@ class ListBoxWidget(Widget.Widget): selection_index = REQUEST.get('selection_index') selection_name = field.get_value('selection_name') portal_url_string = getToolByName(here, 'portal_url')() + portal_categories = getattr(form, 'portal_categories', None) + portal_domains = getattr(form, 'portal_domains', None) + portal_object = form.portal_url.getPortalObject() #selection_name = REQUEST.get('selection_name',None) #if selection_name is None: # selection_name = str(random.randrange(1,2147483600)) current_selection_name = REQUEST.get('selection_name','default') + current_selection_index = REQUEST.get('selection_index', 0) + report_depth = REQUEST.get('report_depth', None) list_action = here.absolute_url() + '/' + field.get_value('list_action') + '?reset=1' object_list = [] @@ -423,28 +515,28 @@ class ListBoxWidget(Widget.Widget): fix_sort = 1 if fix_sort: selection.selection_sort_on = sort_list - if not hasattr(selection, 'selection_flat_list_mode'): + if not hasattr(selection, 'flat_list_mode'): selection.edit(flat_list_mode=(not (domain_tree or report_tree)),domain_tree_mode=domain_tree,report_tree_mode= report_tree) #LOG('ListBox', 0, 'sort = %s, selection.selection_sort_on = %s' % (repr(sort), repr(selection.selection_sort_on))) # Selection - #LOG("Selection",0,str(selection.__dict__)) + LOG("Selection",0,str(selection.__dict__)) # Display choosen by the user if selection.selection_flat_list_mode is not None: - if selection.selection_flat_list_mode == 1: + if selection.flat_list_mode == 1: domain_tree = 0 report_tree = 0 - elif selection.selection_domain_tree_mode == 1: + elif selection.domain_tree_mode == 1: domain_tree = 1 report_tree = 0 - elif selection.selection_report_tree_mode == 1: + elif selection.report_tree_mode == 1: domain_tree = 0 report_tree = 1 - checked_uids = selection.getSelectionCheckedUids() + checked_uids = selection.getCheckedUids() columns = here.portal_selections.getSelectionColumns(selection_name, columns=columns, REQUEST=REQUEST) @@ -465,7 +557,7 @@ class ListBoxWidget(Widget.Widget): filtered_portal_types = None # Combine default values, selection values and REQUEST - params = selection.getSelectionParams() + params = selection.getParams() if list_method not in (None, ''): # Only update params if list_method is defined # (ie. do not update params in listboxed intended to show a previously defined selection @@ -603,19 +695,32 @@ class ListBoxWidget(Widget.Widget): else: stat_method = here.portal_catalog.countResults - #LOG('ListBox', 0, 'domain_tree = %s, selection.getSelectionDomainPath() = %s, selection.getSelectionDomainList() = %s' % (repr(domain_tree), repr(selection.getSelectionDomainPath()), repr(selection.getSelectionDomainList()))) + #LOG('ListBox', 0, 'domain_tree = %s, selection.getDomainPath() = %s, selection.getDomainList() = %s' % (repr(domain_tree), repr(selection.getDomainPath()), repr(selection.getDomainList()))) if domain_tree: - selection_domain_path = selection.getSelectionDomainPath() - selection_domain_current = selection.getSelectionDomainList() + selection_domain_path = selection.getDomainPath() + selection_domain_current = selection.getDomainList() if len(selection_domain_current) > 0: - try: - kw['query'] = here.unrestrictedTraverse(selection_domain_path).unrestrictedTraverse( - selection_domain_current[0]).asSqlExpression() - except: - "The selection does not exist" - pass - - + root_dict = {} + for domain in selection_domain_current: + root = None + base_category = domain.split('/')[0] + if portal_categories is not None: + if base_category in portal_categories.objectIds(): + root = root_dict[base_category] = portal_categories.restrictedTraverse(domain) + if root is None and portal_domains is not None: + if base_category in portal_domains.objectIds(): + root = root_dict[base_category] = portal_domains.restrictedTraverse(domain) + if root is None: + try: + root_dict[None] = portal_object.restrictedTraverse(domain) + except KeyError: + root = None + LOG('domain_tree root aq_parent', 0, str(root_dict[base_category].aq_parent)) + selection.edit(domain = DomainSelection(domain_dict = root_dict)) + LOG('selection.domain', 0, str(selection.domain.__dict__)) + else: + selection.edit(domain = None) + #LOG('ListBox', 0, 'list_method = %s, list_method.__dict__ = %s' % (repr(list_method), repr((list_method.__dict__)))) ############################################################### @@ -658,33 +763,32 @@ class ListBoxWidget(Widget.Widget): # (section_id, is_summary, depth, object_list, object_list_size, is_open) # ############################################################### - report_query = '' if report_tree: - original_query = kw.get('query') - selection_report_path = selection.getSelectionReportPath() - selection_report_current = selection.getSelectionReportList() - report_tree_list = makeTreeList(here.unrestrictedTraverse(selection_report_path), - 0, max(map(lambda x: len(x), selection_report_current)), - selection_report_current, form.id, selection_name ) + selection_report_path = selection.getReportPath() + if report_depth is not None: + selection_report_current = () + else: + selection_report_current = selection.getReportList() + report_tree_list = makeTreeList(form, None, selection_report_path, + 0, selection_report_current, form.id, selection_name, report_depth ) + + # Update report list if report_depth was specified + if report_depth is not None: + report_list = map(lambda s:s[0].getRelativeUrl(), report_tree_list) + selection.edit(report_list=report_list) + report_sections = [] #LOG("Report Tree",0,str(report_tree_list)) for s in report_tree_list: + # Prepare query + selection.edit(report = s[4]) if s[1]: - # Prepare query - if domain_tree: - # This will not work at present XXX - # Because we can combine AND queries on the same table - kw['query'] = '(%s AND %s)' % (original_query, - s[0].asSqlExpression(strict_membership=0)) - else: - kw['query'] = s[0].asSqlExpression(strict_membership=0) - # Push new select_expression original_select_expression = kw.get('select_expression') kw['select_expression'] = select_expression selection.edit( params = kw ) #LOG('ListBox 569', 0, str((selection_name, selection.__dict__))) - stat_temp = selection(selection_method = stat_method, + stat_temp = selection(method = stat_method, context=here, REQUEST=REQUEST) # Pop new select_expression if original_select_expression is None: @@ -710,36 +814,26 @@ class ListBoxWidget(Widget.Widget): stat_context = s[0].asContext(**stat_result) stat_context.absolute_url = lambda x: s[0].absolute_url() - stat_context.domain_url = s[0].getUrl() - report_sections += [(s[0].id, 1, s[2], [stat_context], 1, s[3])] + stat_context.domain_url = s[0].getRelativeUrl() + report_sections += [(s[0].id, 1, s[2], [stat_context], 1, s[3], s[4])] else: # Prepare query - if domain_tree: - # This will not work at present XXX - # Because we can combine AND queries on the same table - kw['query'] = '(%s AND %s)' % (original_query, - s[0].asSqlExpression(strict_membership=1)) - else: - kw['query'] = s[0].asSqlExpression(strict_membership=1) - report_query += kw['query'] selection.edit( params = kw ) if list_method not in (None, ''): - object_list = selection(selection_method = list_method, context=here, REQUEST=REQUEST) + object_list = selection(method = list_method, context=here, REQUEST=REQUEST) else: # If list_method is None, use already selected values. object_list = here.portal_selections.getSelectionValueList(selection_name, context=here, REQUEST=REQUEST) # # PERFORMANCE ? is len(object_list) fast enough ? - report_sections += [ (None, 0, s[2], object_list, len(object_list), s[3]) ] - if original_query is not None: - kw['query'] = original_query - else: - del kw['query'] - + report_sections += [ (None, 0, s[2], object_list, len(object_list), s[3], s[4]) ] + + # Reset original value + selection.edit(report = None) else: - selection.edit( params = kw ) + selection.edit( params = kw, report = None ) #LOG('ListBox 612', 0, str((selection_name, selection.__dict__))) if list_method not in (None, ''): - object_list = selection(selection_method = list_method, context=here, REQUEST=REQUEST) + object_list = selection(method = list_method, context=here, REQUEST=REQUEST) else: # If list_method is None, use already selected values. object_list = here.portal_selections.getSelectionValueList(selection_name, context=here, REQUEST=REQUEST) @@ -1006,7 +1100,12 @@ onChange="submitAction(this.form,'%s/portal_selections/setReportRoot')"> if search: # Add empty column for report if report_tree: - report_search = """<td class="Data" width="50" align="left" valign="middle"> <a href="">1</a> <a href="">2</a> <a href=""><u>3</u></a> </td>""" + depth_selector = '' + for i in range(0,6): + # XXX We may lose previous list information + depth_selector += """ <a href="%s/%s?selection_name=%s&selection_index=%s&report_depth:int=%s">%s</a>""" % \ + (here.absolute_url(), form.id, current_selection_name, current_selection_index , i, i) + report_search = """<td class="Data" width="50" align="left" valign="middle">%s</td>""" % depth_selector else: report_search = "" @@ -1056,230 +1155,237 @@ onChange="submitAction(this.form,'%s/portal_selections/setReportRoot')"> if render_format == 'list': list_result = [c_name_list] # Create initial list for list render format section_index = 0 current_section_base_index = 0 - current_section = report_sections[section_index] - current_section_size = current_section[4] - object_list = current_section[3] - for i in range(start,end): - # Set the selection index. - selection.edit(index = i) - - # Make sure we go to the right section - while current_section_base_index + current_section_size <= i: - current_section_base_index += current_section[4] - section_index += 1 - current_section = report_sections[section_index] - current_section_size = current_section[4] - object_list = current_section[3] - - is_summary = current_section[1] # Update summary type - - list_body = list_body + '<tr>' - o = object_list[i - current_section_base_index] # FASTER PERFORMANCE - real_o = None - - # Define the CSS - if not (i - start) % 2: - td_css = 'DataA' - else: - td_css = 'DataB' - - list_body = list_body + \ -"""<input type="hidden" value="%s" name="%s_uid:list"/> -""" % ( getattr(o, 'uid', '') , field.id ) # What happens if we list instances which are not instances of Base XXX - - section_char = '' - if render_format == 'list': list_result_item = [] # Start a new item for list render format - if report_tree: - if is_summary: - # This is a summary - section_name = current_section[0] - else: - section_name = '' - if current_section[5]: - if section_name != '': - section_char = '-' - list_body = list_body + \ -"""<td class="%s" align="left" valign="middle"><a href="portal_selections/foldReport?report_url=%s&form_id=%s&list_selection_name=%s">%s%s%s</a></td> -""" % (td_css, getattr(current_section[3][0],'domain_url',''), form.id, selection_name, ' ' * current_section[2], section_char, section_name) - if render_format == 'list': list_result_item.append(section_name) - else: - if section_name != '': - section_char = '+' - list_body = list_body + \ -"""<td class="%s" align="left" valign="middle"><a href="portal_selections/unfoldReport?report_url=%s&form_id=%s&list_selection_name=%s">%s%s%s</a></td> -""" % (td_css, getattr(current_section[3][0],'domain_url',''), form.id, selection_name, ' ' * current_section[2], section_char, section_name) - if render_format == 'list': list_result_item.append(section_name) - - if select: - if o.uid in checked_uids: - selected = 'checked' - else: - selected = '' - if section_char != '': - list_body = list_body + \ -"""<td class="%s" width="50" align="center" valign="middle"> </td> -""" % (td_css, ) + if len(report_sections) > section_index: + current_section = report_sections[section_index] + elif len(report_sections): + current_section = report_sections[0] + else: + current_section = None + if current_section is not None: + current_section_size = current_section[4] + object_list = current_section[3] + #if current_section is not None: + for i in range(start,end): + # Set the selection index. + selection.edit(index = i) + + # Make sure we go to the right section + while current_section_base_index + current_section_size <= i: + current_section_base_index += current_section[4] + section_index += 1 + current_section = report_sections[section_index] + current_section_size = current_section[4] + object_list = current_section[3] + + is_summary = current_section[1] # Update summary type + + list_body = list_body + '<tr>' + o = object_list[i - current_section_base_index] # FASTER PERFORMANCE + real_o = None + + # Define the CSS + if not (i - start) % 2: + td_css = 'DataA' else: - list_body = list_body + \ -"""<td class="%s" width="50" align="center" valign="middle"> -<input type="checkbox" %s value="%s" id="cb_%s" name="uids:list"/></td> -""" % (td_css, selected, o.uid , o.uid) - error_list = [] - for cname in extended_columns: - sql = cname[0] # (sql, title, alias) - alias = cname[2] # (sql, title, alias) - if '.' in sql: - property_id = '.'.join(sql.split('.')[1:]) # Only take trailing part - else: - property_id = alias -# attribute_value = getattr(o, cname_id) # FUTURE WAY OF DOING TGW Brains - my_field = None - tales_expr = None - if form.has_field('%s_%s' % (field.id, alias) ) and not is_summary: - my_field_id = '%s_%s' % (field.id, alias) - my_field = form.get_field(my_field_id) - tales_expr = my_field.tales.get('default', "") - if tales_expr: - # - real_o = o - if hasattr(o,'getObject'): # we have a line of sql result - real_o = o.getObject() - field_kw = {'cell':real_o} - attribute_value = my_field.__of__(real_o).get_value('default',**field_kw) - else: - # Prepare stat_column is this is a summary + td_css = 'DataB' + + list_body = list_body + \ + """<input type="hidden" value="%s" name="%s_uid:list"/> + """ % ( getattr(o, 'uid', '') , field.id ) # What happens if we list instances which are not instances of Base XXX + + section_char = '' + if render_format == 'list': list_result_item = [] # Start a new item for list render format + if report_tree: if is_summary: - # Use stat method to find value - for stat_column in stat_columns: - if stat_column[0] == sql: - break - else: - stat_column = None - if hasattr(aq_self(o),alias) and (not is_summary or stat_column is None or stat_column[0] == stat_column[1]): # Block acquisition to reduce risks - # First take the indexed value - attribute_value = getattr(o,alias) # We may need acquisition in case of method call - elif is_summary: - attribute_value = getattr(here, stat_column[1]) - #LOG('ListBox', 0, 'column = %s, value = %s' % (repr(column), repr(value))) - if callable(attribute_value): - try: - params = dict(kw) - #params['operator'] = stats[n] - attribute_value=attribute_value(**params) - except: - LOG('ListBox', 0, 'WARNING: Could not call %s with %s: ' % (repr(attribute_value), repr(params)), error=sys.exc_info()) - pass + # This is a summary + section_name = current_section[0] else: - # MUST IMPROVE FOR PERFORMANCE REASON - # attribute_value = 'Does not exist' - if real_o is None: - try: - real_o = o.getObject() - except: - pass - if real_o is not None: - try: + section_name = '' + if current_section[5]: + if section_name != '': + section_char = '-' + list_body = list_body + \ + """<td class="%s" align="left" valign="middle"><a href="portal_selections/foldReport?report_url=%s&form_id=%s&list_selection_name=%s">%s%s%s</a></td> + """ % (td_css, getattr(current_section[3][0],'domain_url',''), form.id, selection_name, ' ' * current_section[2], section_char, section_name) + if render_format == 'list': list_result_item.append(section_name) + else: + if section_name != '': + section_char = '+' + list_body = list_body + \ + """<td class="%s" align="left" valign="middle"><a href="portal_selections/unfoldReport?report_url=%s&form_id=%s&list_selection_name=%s">%s%s%s</a></td> + """ % (td_css, getattr(current_section[3][0],'domain_url',''), form.id, selection_name, ' ' * current_section[2], section_char, section_name) + if render_format == 'list': list_result_item.append(section_name) + + if select: + if o.uid in checked_uids: + selected = 'checked' + else: + selected = '' + if section_char != '': + list_body = list_body + \ + """<td class="%s" width="50" align="center" valign="middle"> </td> + """ % (td_css, ) + else: + list_body = list_body + \ + """<td class="%s" width="50" align="center" valign="middle"> + <input type="checkbox" %s value="%s" id="cb_%s" name="uids:list"/></td> + """ % (td_css, selected, o.uid , o.uid) + error_list = [] + for cname in extended_columns: + sql = cname[0] # (sql, title, alias) + alias = cname[2] # (sql, title, alias) + if '.' in sql: + property_id = '.'.join(sql.split('.')[1:]) # Only take trailing part + else: + property_id = alias + # attribute_value = getattr(o, cname_id) # FUTURE WAY OF DOING TGW Brains + my_field = None + tales_expr = None + if form.has_field('%s_%s' % (field.id, alias) ) and not is_summary: + my_field_id = '%s_%s' % (field.id, alias) + my_field = form.get_field(my_field_id) + tales_expr = my_field.tales.get('default', "") + if tales_expr: + # + real_o = o + if hasattr(o,'getObject'): # we have a line of sql result + real_o = o.getObject() + field_kw = {'cell':real_o} + attribute_value = my_field.__of__(real_o).get_value('default',**field_kw) + else: + # Prepare stat_column is this is a summary + if is_summary: + # Use stat method to find value + for stat_column in stat_columns: + if stat_column[0] == sql: + break + else: + stat_column = None + if hasattr(aq_self(o),alias) and (not is_summary or stat_column is None or stat_column[0] == stat_column[1]): # Block acquisition to reduce risks + # First take the indexed value + attribute_value = getattr(o,alias) # We may need acquisition in case of method call + elif is_summary: + attribute_value = getattr(here, stat_column[1]) + #LOG('ListBox', 0, 'column = %s, value = %s' % (repr(column), repr(value))) + if callable(attribute_value): try: - attribute_value = getattr(real_o,property_id, None) - #LOG('Look up attribute %s' % cname_id,0,str(attribute_value)) - if not callable(attribute_value): - #LOG('Look up accessor %s' % cname_id,0,'') - attribute_value = real_o.getProperty(property_id) - #LOG('Look up accessor %s' % cname_id,0,str(attribute_value)) + params = dict(kw) + #params['operator'] = stats[n] + attribute_value=attribute_value(**params) except: - attribute_value = getattr(real_o,property_id) - #LOG('Fallback to attribute %s' % cname_id,0,str(attribute_value)) - except: - attribute_value = 'Can not evaluate attribute: %s' % sql + LOG('ListBox', 0, 'WARNING: Could not call %s with %s: ' % (repr(attribute_value), repr(params)), error=sys.exc_info()) + pass else: - attribute_value = 'Object does not exist' - if callable(attribute_value): - try: - try: - attribute_value = attribute_value(brain = o, selection = selection) - except TypeError: - attribute_value = attribute_value() - except: - LOG('ListBox', 0, 'Could not evaluate', error=sys.exc_info()) - attribute_value = "Could not evaluate" - #LOG('ListBox', 0, 'o = %s' % repr(dir(o))) - if type(attribute_value) is type(0.0): - if sql in editable_column_ids and form.has_field('%s_%s' % (field.id, alias) ): - # Do not truncate if editable - pass - else: - attribute_value = "%.2f" % attribute_value - td_align = "right" - elif type(attribute_value) is type(1): - td_align = "right" - else: - td_align = "left" - if sql in editable_column_ids and form.has_field('%s_%s' % (field.id, alias) ): - key = my_field.id + '_%s' % o.uid - if field_errors.has_key(key): - error_css = 'Error' - error_message = "<br/>%s" % field_errors[key].error_text # XXX localization needed - # Display previous value (in case of error - error_list.append(field_errors.get(key)) - display_value = REQUEST.get('field_%s' % key, attribute_value) - else: - error_css = '' - error_message = '' - #display_value = REQUEST.get('field_%s' % key, attribute_value) - display_value = attribute_value # XXX Make sure this is ok - cell_body = my_field.render(value = display_value, REQUEST = o, key = key) - # We use REQUEST which is not so good here - # This prevents from using standard display process - list_body = list_body + \ - ('<td class=\"%s%s\">%s%s</td>' % (td_css, error_css, cell_body, error_message)) - # Add item to list_result_item for list render format - if render_format == 'list': - list_result_item.append(my_field._get_default(self.generate_field_key(), display_value, o)) - else: - # Check if url_columns defines a method to retrieve the URL. - url_method = None - for column in url_columns: - if sql == column[0]: - url_method = getattr(o, column[1], '') - break - if url_method is not None: + # MUST IMPROVE FOR PERFORMANCE REASON + # attribute_value = 'Does not exist' + if real_o is None: + try: + real_o = o.getObject() + except: + pass + if real_o is not None: + try: + try: + attribute_value = getattr(real_o,property_id, None) + #LOG('Look up attribute %s' % cname_id,0,str(attribute_value)) + if not callable(attribute_value): + #LOG('Look up accessor %s' % cname_id,0,'') + attribute_value = real_o.getProperty(property_id) + #LOG('Look up accessor %s' % cname_id,0,str(attribute_value)) + except: + attribute_value = getattr(real_o,property_id) + #LOG('Fallback to attribute %s' % cname_id,0,str(attribute_value)) + except: + attribute_value = 'Can not evaluate attribute: %s' % sql + else: + attribute_value = 'Object does not exist' + if callable(attribute_value): try: - object_url = url_method(brain = o, selection = selection) - list_body = list_body + \ - ("<td class=\"%s\" align=\"%s\"><a href=\"%s\">%s</a></td>" % - (td_css, td_align, object_url, attribute_value)) + try: + attribute_value = attribute_value(brain = o, selection = selection) + except TypeError: + attribute_value = attribute_value() except: - LOG('ListBox', 0, 'Could not evaluate url_method %s' % column[1], error=sys.exc_info()) - list_body = list_body + \ - ("<td class=\"%s\" align=\"%s\">%s</td>" % (td_css, td_align, attribute_value) ) + LOG('ListBox', 0, 'Could not evaluate', error=sys.exc_info()) + attribute_value = "Could not evaluate" + #LOG('ListBox', 0, 'o = %s' % repr(dir(o))) + if type(attribute_value) is type(0.0): + if sql in editable_column_ids and form.has_field('%s_%s' % (field.id, alias) ): + # Do not truncate if editable + pass + else: + attribute_value = "%.2f" % attribute_value + td_align = "right" + elif type(attribute_value) is type(1): + td_align = "right" else: - # Check if this object provides a specific URL method - url_method = getattr(o, 'getListItemUrl', None) - if url_method is None: - try: - object_url = o.absolute_url() + \ - '/view?selection_index=%s&selection_name=%s&reset=1' % (i, selection_name) - list_body = list_body + \ - ("<td class=\"%s\" align=\"%s\"><a href=\"%s\">%s</a></td>" % - (td_css, td_align, object_url, attribute_value)) - except: - list_body = list_body + \ - ("<td class=\"%s\" align=\"%s\">%s</td>" % (td_css, td_align, attribute_value) ) + td_align = "left" + if sql in editable_column_ids and form.has_field('%s_%s' % (field.id, alias) ): + key = my_field.id + '_%s' % o.uid + if field_errors.has_key(key): + error_css = 'Error' + error_message = "<br/>%s" % field_errors[key].error_text # XXX localization needed + # Display previous value (in case of error + error_list.append(field_errors.get(key)) + display_value = REQUEST.get('field_%s' % key, attribute_value) else: + error_css = '' + error_message = '' + #display_value = REQUEST.get('field_%s' % key, attribute_value) + display_value = attribute_value # XXX Make sure this is ok + cell_body = my_field.render(value = display_value, REQUEST = o, key = key) + # We use REQUEST which is not so good here + # This prevents from using standard display process + list_body = list_body + \ + ('<td class=\"%s%s\">%s%s</td>' % (td_css, error_css, cell_body, error_message)) + # Add item to list_result_item for list render format + if render_format == 'list': + list_result_item.append(my_field._get_default(self.generate_field_key(), display_value, o)) + else: + # Check if url_columns defines a method to retrieve the URL. + url_method = None + for column in url_columns: + if sql == column[0]: + url_method = getattr(o, column[1], '') + break + if url_method is not None: try: - object_url = url_method(alias, i, selection_name) + object_url = url_method(brain = o, selection = selection) list_body = list_body + \ ("<td class=\"%s\" align=\"%s\"><a href=\"%s\">%s</a></td>" % (td_css, td_align, object_url, attribute_value)) except: + LOG('ListBox', 0, 'Could not evaluate url_method %s' % column[1], error=sys.exc_info()) list_body = list_body + \ ("<td class=\"%s\" align=\"%s\">%s</td>" % (td_css, td_align, attribute_value) ) - # Add item to list_result_item for list render format - if render_format == 'list': list_result_item.append(attribute_value) - - list_body = list_body + '</tr>' - if render_format == 'list': - list_result.append(list_result_item) + else: + # Check if this object provides a specific URL method + url_method = getattr(o, 'getListItemUrl', None) + if url_method is None: + try: + object_url = o.absolute_url() + \ + '/view?selection_index=%s&selection_name=%s&reset=1' % (i, selection_name) + list_body = list_body + \ + ("<td class=\"%s\" align=\"%s\"><a href=\"%s\">%s</a></td>" % + (td_css, td_align, object_url, attribute_value)) + except: + list_body = list_body + \ + ("<td class=\"%s\" align=\"%s\">%s</td>" % (td_css, td_align, attribute_value) ) + else: + try: + object_url = url_method(alias, i, selection_name) + list_body = list_body + \ + ("<td class=\"%s\" align=\"%s\"><a href=\"%s\">%s</a></td>" % + (td_css, td_align, object_url, attribute_value)) + except: + list_body = list_body + \ + ("<td class=\"%s\" align=\"%s\">%s</td>" % (td_css, td_align, attribute_value) ) + # Add item to list_result_item for list render format + if render_format == 'list': list_result_item.append(attribute_value) + + list_body = list_body + '</tr>' + if render_format == 'list': + list_result.append(list_result_item) ############################################################### # @@ -1293,7 +1399,7 @@ onChange="submitAction(this.form,'%s/portal_selections/setReportRoot')"> kw['select_expression'] = select_expression selection.edit( params = kw ) - count_results = selection(selection_method = stat_method, + count_results = selection(method = stat_method, context=here, REQUEST=REQUEST) list_body = list_body + '<tr>' if render_format == 'list': list_result_item = [] @@ -1358,8 +1464,8 @@ onChange="submitAction(this.form,'%s/portal_selections/setDomainRoot')"> %s</select>""" % (here.getUrl(),select_tree_options) try: - select_tree_body = makeTreeBody(here.unrestrictedTraverse(selection_domain_path), - 0, max(map(lambda x: len(x), selection_domain_current)), selection_domain_current, form.id, selection_name ) + select_tree_body = makeTreeBody(form, None, selection_domain_path, + 0, None, selection_domain_current, form.id, selection_name ) except KeyError: select_tree_body = '' @@ -1401,7 +1507,7 @@ class ListBoxValidator(Validator.Validator): selection_name = field.get_value('selection_name') #LOG('ListBoxValidator', 0, 'field = %s, selection_name = %s' % (repr(field), repr(selection_name))) selection = here.portal_selections.getSelectionFor(selection_name, REQUEST=REQUEST) - params = selection.getSelectionParams() + params = selection.getParams() portal_url = getToolByName(here, 'portal_url') portal = portal_url.getPortalObject() diff --git a/product/ERP5Form/Selection.py b/product/ERP5Form/Selection.py index bf5c09f3a25d1a46a350dc3634cd70a44d992e65..2cbe40365fe83b7baa01de2ac6b3519dcfecf086 100755 --- a/product/ERP5Form/Selection.py +++ b/product/ERP5Form/Selection.py @@ -27,12 +27,18 @@ ############################################################################## from Globals import InitializeClass, Persistent, Acquisition +from Acquisition import aq_base, aq_inner, aq_parent, aq_self from OFS.SimpleItem import SimpleItem from OFS.Traversable import Traversable from AccessControl import ClassSecurityInfo from Products.ERP5Type import Permissions as ERP5Permissions +from Products.PythonScripts.Utility import allow_class import string +# Put a try in front XXX +from Products.CMFCategory.Category import Category +from Products.ERP5.Document.Domain import Domain + from zLOG import LOG class Selection(Acquisition.Implicit, Traversable, Persistent): @@ -45,42 +51,75 @@ class Selection(Acquisition.Implicit, Traversable, Persistent): Selection uses the following control variables - - selection_method -- a method which will be used + - method -- a method which will be used to select objects - - selection_params -- a dictionnary of parameters to call the + - params -- a dictionnary of parameters to call the method with - - selection_sort_on -- a dictionnary of parameters to sort + - sort_on -- a dictionnary of parameters to sort the selection - - selection_uids -- a list of object uids which defines the + - uids -- a list of object uids which defines the selection - - selection_invert_mode -- defines the mode of the selection + - invert_mode -- defines the mode of the selection if mode is 1, then only show the ob - - selection_list_url -- the URL to go back to list mode + - list_url -- the URL to go back to list mode - - selection_checked_uids -- a list of uids checked + - checked_uids -- a list of uids checked - - selection_domain_path -- the path to the root of the selection tree + - domain_path -- the path to the root of the selection tree - - selection_domain_list -- the relative path of the current selected domain + - domain_list -- the relative path of the current selected domain + XXX this will have to be updated for cartesion product - - selection_report_path -- the report path + - report_path -- the report path - - selection_report_list -- list of open report nodes + - report_list -- list of open report nodes + XXX this will have to be updated for cartesion product + + - domain -- a DomainSelection instance + + - report -- a DomainSelection instance + - flat_list_mode -- + + - domain_tree_mode -- + + - report_tree_mode -- + """ - + + method_path=None + params={} + sort_on=() + default_sort_on=None + uids=() + invert_mode=0 + list_url='' + columns=() + checked_uids=() + name=None + index=None + domain_path = ('portal_categories',) + domain_list = ((),) + report_path = ('portal_categories',) + report_list = ((),) + domain=None + report=None + security = ClassSecurityInfo() - security.declareObjectProtected(ERP5Permissions.View) + security.declareObjectPublic() + security.declarePublic('domain') + security.declarePublic('report') + def __init__(self, method_path=None, params=None, sort_on=None, default_sort_on=None, - uids=None, invert_mode=0, list_url='', + uids=None, invert_mode=0, list_url='', domain=None, report=None, columns=None, checked_uids=None, name=None, index=None): if params is None: params = {} if sort_on is None: sort_on = [] @@ -91,50 +130,53 @@ class Selection(Acquisition.Implicit, Traversable, Persistent): # Shouldn't Zope automatically does this conversion? -yo if type(method_path) is type(u'a'): method_path = method_path.encode('ascii') - self.selection_method_path = method_path - self.selection_params = params - self.selection_uids = uids - self.selection_invert_mode = invert_mode - self.selection_list_url = list_url - self.selection_columns = columns - self.selection_sort_on = sort_on - self.selection_default_sort_on = default_sort_on - self.selection_checked_uids = checked_uids - self.selection_name = name - self.selection_index = index - self.selection_domain_path = ('portal_categories',) - self.selection_domain_list = ((),) - self.selection_report_path = ('portal_categories',) - self.selection_report_list = ((),) - + self.method_path = method_path + self.params = params + self.uids = uids + self.invert_mode = invert_mode + self.list_url = list_url + self.columns = columns + self.sort_on = sort_on + self.default_sort_on = default_sort_on + self.checked_uids = checked_uids + self.name = name + self.index = index + self.domain_path = ('portal_categories',) + self.domain_list = ((),) + self.report_path = ('portal_categories',) + self.report_list = ((),) + self.domain = None + self.report = None + + security.declarePrivate('edit') def edit(self, params=None, **kw): if params is not None: - self.selection_params = {} + self.params = {} for key in params.keys(): # We should only keep params which do not start with field_ # in order to make sure we do not collect unwanted params # resulting form the REQUEST generated by an ERP5Form submit if key[0:6] != 'field_': - self.selection_params[key] = params[key] + self.params[key] = params[key] if kw is not None: for k,v in kw.items(): - if v is not None: + if k in ('domain', 'report') or v is not None: # XXX Because method_path is an URI, it must be in ASCII. # Shouldn't Zope automatically does this conversion? -yo if k == 'method_path' and type(v) is type(u'a'): v = v.encode('ascii') - setattr(self, 'selection_%s' % k, v) + setattr(self, k, v) - def __call__(self, selection_method = None, context=None, REQUEST=None): + def __call__(self, method = None, context=None, REQUEST=None): #LOG("Selection", 0, str(self.__dict__)) - #LOG("Selection", 0, str(selection_method)) - #LOG('Selection', 0, "self.selection_invert_mode = %s" % repr(self.selection_invert_mode)) - if self.selection_invert_mode is 0: - if selection_method is None: - selection_method = context.unrestrictedTraverse(self.selection_method_path) - sort_on = getattr(self, 'selection_sort_on', []) + #LOG("Selection", 0, str(method)) + #LOG('Selection', 0, "self.invert_mode = %s" % repr(self.invert_mode)) + if self.invert_mode is 0: + if method is None: + method = context.unrestrictedTraverse(self.method_path) + sort_on = getattr(self, 'sort_on', []) if len(sort_on) == 0: - sort_on = getattr(self, 'selection_default_sort_on', []) + sort_on = getattr(self, 'default_sort_on', []) if len(sort_on) > 0: new_sort_index = [] for (k , v) in sort_on: @@ -143,83 +185,185 @@ class Selection(Acquisition.Implicit, Traversable, Persistent): else: new_sort_index += ['%s' % k] sort_order_string = string.join(new_sort_index,',') - self.selection_params['sort_on'] = sort_order_string - elif self.selection_params.has_key('sort_on'): - del self.selection_params['sort_on'] - if selection_method is not None: - if callable(selection_method): - #LOG('Selection', 0, "self.selection_params = %s" % repr(self.selection_params)) - return selection_method(**self.selection_params) + self.params['sort_on'] = sort_order_string + elif self.params.has_key('sort_on'): + del self.params['sort_on'] + if method is not None: + if callable(method): + #LOG('Selection', 0, "self.params = %s" % repr(self.params)) + if self.domain is not None and self.report is not None: + result = method(selection_domain = self.domain, + selection_report = self.report, selection=self, **self.params) + elif self.domain is not None: + result = method(selection_domain = self.domain, selection=self, **self.params) + elif self.report is not None: + result = method(selection_report = self.report, selection=self, **self.params) + else: + result = method(selection=self, **self.params) + return result else: return [] else: return [] else: # We sould try to allow more filtering - return context.portal_catalog(uid = self.selection_uids) + return context.portal_catalog(uid = self.uids) def __getitem__(self, index, REQUEST=None): return self(REQUEST)[index] - security.declarePublic('getSelectionName') - def getSelectionName(self): + security.declarePublic('getName') + def getName(self): """ Get the name of this selection. """ - return self.selection_name + return self.name - security.declarePublic('getSelectionIndex') - def getSelectionIndex(self): + security.declarePublic('getIndex') + def getIndex(self): """ Get the index of this selection. """ - return self.selection_index + return self.index - security.declarePublic('getSelectionParams') - def getSelectionParams(self): + security.declarePublic('getDomain') + def getDomain(self): + """ + Get the domain selection of this selection. + """ + return self.domain + + security.declarePublic('getParams') + def getParams(self): """ Get a dictionary of parameters in this selection. """ - LOG('getSelectionParams',0,'selection_params: %s' % str(self.selection_params)) - if self.selection_params is None: - self.selection_params = {} - if type(self.selection_params) != type({}): - self.selection_params = {} - return self.selection_params - - def getSelectionListUrl(self): + LOG('getParams',0,'params: %s' % str(self.params)) + if self.params is None: + self.params = {} + if type(self.params) != type({}): + self.params = {} + return self.params + + security.declarePublic('getListUrl') + def getListUrl(self): result = '' - LOG('getSelectionListUrl', 0, 'selection_list_url = %s' % str(self.selection_list_url)) - if self.selection_list_url is None: - self.selection_list_url = '' + LOG('getListUrl', 0, 'list_url = %s' % str(self.list_url)) + if self.list_url is None: + self.list_url = '' else: - result = self.selection_list_url + result = self.list_url return result - def getSelectionCheckedUids(self): - if not hasattr(self, 'selection_checked_uids'): - self.selection_checked_uids = [] - elif self.selection_checked_uids is None: - self.selection_checked_uids = [] - return self.selection_checked_uids - - def getSelectionDomainPath(self): - if self.selection_domain_path is None: - self.selection_domain_path = self.getSelectionDomainList()[0] - return self.selection_domain_path - - def getSelectionDomainList(self): - if self.selection_domain_list is None: - self.selection_domain_list = (('portal_categories',),) - return self.selection_domain_list - - def getSelectionReportPath(self): - if self.selection_report_path is None: - self.selection_report_path = ('portal_categories') - return self.selection_report_path - - def getSelectionReportList(self): - if self.selection_report_list is None: - self.selection_report_list = (('portal_categories',),) - return self.selection_report_list - + security.declarePublic('getCheckedUids') + def getCheckedUids(self): + if not hasattr(self, 'checked_uids'): + self.checked_uids = [] + elif self.checked_uids is None: + self.checked_uids = [] + return self.checked_uids + + security.declarePublic('getDomainPath') + def getDomainPath(self): + if self.domain_path is None: + self.domain_path = self.getDomainList()[0] + return self.domain_path + + security.declarePublic('getDomainList') + def getDomainList(self): + if self.domain_list is None: + self.domain_list = (('portal_categories',),) + return self.domain_list + + security.declarePublic('getReportPath') + def getReportPath(self): + if self.report_path is None: + self.report_path = ('portal_categories') + return self.report_path + + security.declarePublic('getReportList') + def getReportList(self): + if self.report_list is None: + self.report_list = (('portal_categories',),) + return self.report_list + +InitializeClass(Selection) +allow_class(Selection) + +class DomainSelection(Acquisition.Implicit, Traversable, Persistent): + """ + A class to store a selection of domains which defines a report + section. + + Example 1: (hand coded) + + <dtml-if selection.domain.eip> + <dtml-in "selection.domain.eip.getCategoryChildUidList()">uid = <dtml-sqlvar sequence-item type="int"></dtml-in> + </dtml-if> + + Example 2: (auto generated) + + <dtml-var "selection.domain.asSqlExpression(table_map=(('eip','movement'), ('group', 'catalog')))"> + <dtml-var "selection.domain.asSqlJoinExpression(table_map=(('eip','movement'), ('group', 'catalog')))"> + + Example 3: (mixed) + + <dtml-var "selection.domain.eip.asSqlExpresion(table="resource_category")"> + + """ + + security = ClassSecurityInfo() + security.declareObjectPublic() + + def __init__(self, domain_dict = None): + if domain_dict is not None: + self.domain_dict = domain_dict + for k,v in domain_dict.items(): + if k is not None: + setattr(self, k, v) + + def __len__(self): + return len(self.domain_dict) + + security.declarePublic('getCategoryList') + def getCategoryList(self): + return + + security.declarePublic('asSqlExpression') + def asSqlExpression(self, table_map=None, domain_id=None, exclude_domain_id=None, strict_membership=0): + join_expression = [] + for k, d in self.domain_dict.items(): + if k is not None and getattr(aq_base(d), 'isCategory', 0): + # This is a category, we must join + join_expression.append('catalog.uid = %s_category.uid' % k) + join_expression.append(d.asSqlExpression(table = '%s_category' % k, strict_membership=strict_membership)) + result = "( %s )" % ' AND '.join(join_expression) + LOG('asSqlExpression', 0, str(result)) + return result + + security.declarePublic('asSqlJoinExpression') + def asSqlJoinExpression(self, domain_id=None, exclude_domain_id=None): + join_expression = [] + for k, d in self.domain_dict.items(): + if k is not None and getattr(aq_base(d), 'isCategory', 0): + # This is a category, we must join + join_expression.append('category AS %s_category' % k) + result = "%s" % ' , '.join(join_expression) + LOG('asSqlJoinExpression', 0, str(result)) + return result + + security.declarePublic('asDomainDict') + def asDomainDict(self, domain_id=None, exclude_domain_id=None): + pass + + security.declarePublic('asDomainItemDict') + def asDomainItemDict(self, domain_id=None, exclude_domain_id=None): + pass + + security.declarePublic('updateDomain') + def updateDomain(self, domain): + pass + +InitializeClass(DomainSelection) +allow_class(DomainSelection) + \ No newline at end of file diff --git a/product/ERP5Form/SelectionTool.py b/product/ERP5Form/SelectionTool.py index 674f698f39deba73ccc07cdf1e2e00aec725d5b8..3c4417e9584564201c5ecf4192084c760449a418 100755 --- a/product/ERP5Form/SelectionTool.py +++ b/product/ERP5Form/SelectionTool.py @@ -156,8 +156,8 @@ class SelectionTool( UniqueObject, SimpleItem ): if params is None: params = {} selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) if selection is not None: - if len(selection.selection_params) > 0: - return selection.getSelectionParams() + if len(selection.params) > 0: + return selection.getParams() else: return params else: @@ -206,7 +206,7 @@ class SelectionTool( UniqueObject, SimpleItem ): selection_object = self.getSelectionFor(selection_name, REQUEST) if selection_object: #return selection_object.selection_checked_uids - return selection_object.getSelectionCheckedUids() + return selection_object.getCheckedUids() return [] security.declareProtected(ERP5Permissions.View, 'checkAll') @@ -217,10 +217,13 @@ class SelectionTool( UniqueObject, SimpleItem ): selection_object = self.getSelectionFor(selection_name, REQUEST) if selection_object: selection_uid_dict = {} - for uid in selection_object.selection_checked_uids: + for uid in selection_object.checked_uids: selection_uid_dict[uid] = 1 for uid in listbox_uid: - selection_uid_dict[int(uid)] = 1 + try: + selection_uid_dict[int(uid)] = 1 + except ValueError: + pass # this can happen in report self.setSelectionCheckedUidsFor(selection_name, selection_uid_dict.keys(), REQUEST=REQUEST) request = REQUEST if request: @@ -237,10 +240,13 @@ class SelectionTool( UniqueObject, SimpleItem ): selection_object = self.getSelectionFor(selection_name, REQUEST) if selection_object: selection_uid_dict = {} - for uid in selection_object.selection_checked_uids: + for uid in selection_object.checked_uids: selection_uid_dict[uid] = 1 for uid in listbox_uid: - if selection_uid_dict.has_key(int(uid)): del selection_uid_dict[int(uid)] + try: + if selection_uid_dict.has_key(int(uid)): del selection_uid_dict[int(uid)] + except ValueError: + pass # This happens in report mode self.setSelectionCheckedUidsFor(selection_name, selection_uid_dict.keys(), REQUEST=REQUEST) request = REQUEST if request: @@ -256,7 +262,7 @@ class SelectionTool( UniqueObject, SimpleItem ): """ selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) if selection: - return selection.getSelectionListUrl() + return selection.getListUrl() else: return None @@ -326,7 +332,7 @@ class SelectionTool( UniqueObject, SimpleItem ): """ selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) if selection is None: return () - return selection.selection_sort_on + return selection.sort_on security.declareProtected(ERP5Permissions.View, 'setSelectionColumns') def setSelectionColumns(self, selection_name, columns, REQUEST=None): @@ -344,8 +350,8 @@ class SelectionTool( UniqueObject, SimpleItem ): if columns is None: columns = [] selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) if selection is not None: - if len(selection.selection_columns) > 0: - return selection.selection_columns + if len(selection.columns) > 0: + return selection.columns return columns @@ -365,9 +371,9 @@ class SelectionTool( UniqueObject, SimpleItem ): selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) if selection is not None: try: - return selection.selection_stats + return selection.stats except: - return stats + return stats # That is really bad programming XXX else: return stats @@ -381,8 +387,8 @@ class SelectionTool( UniqueObject, SimpleItem ): REQUEST = get_request() selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) if selection: - method = self.unrestrictedTraverse(selection.selection_method_path) - selection = selection(selection_method = method, context=self, REQUEST=REQUEST) + method = self.unrestrictedTraverse(selection.method_path) + selection = selection(method = method, context=self, REQUEST=REQUEST) o = selection[0] url = o.absolute_url() else: @@ -399,8 +405,8 @@ class SelectionTool( UniqueObject, SimpleItem ): REQUEST = get_request() selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) if selection: - method = self.unrestrictedTraverse(selection.selection_method_path) - selection = selection(selection_method = method, context=self, REQUEST=REQUEST) + method = self.unrestrictedTraverse(selection.method_path) + selection = selection(method = method, context=self, REQUEST=REQUEST) o = selection[-1] url = o.absolute_url() else: @@ -417,8 +423,8 @@ class SelectionTool( UniqueObject, SimpleItem ): REQUEST = get_request() selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) if selection: - method = self.unrestrictedTraverse(selection.selection_method_path) - selection = selection(selection_method = method, context=self, REQUEST=REQUEST) + method = self.unrestrictedTraverse(selection.method_path) + selection = selection(method = method, context=self, REQUEST=REQUEST) o = selection[(int(selection_index) + 1) % len(selection)] url = o.absolute_url() else: @@ -435,8 +441,8 @@ class SelectionTool( UniqueObject, SimpleItem ): REQUEST = get_request() selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) if selection: - method = self.unrestrictedTraverse(selection.selection_method_path) - selection = selection(selection_method = method, context=self, REQUEST=REQUEST) + method = self.unrestrictedTraverse(selection.method_path) + selection = selection(method = method, context=self, REQUEST=REQUEST) o = selection[(int(selection_index) - 1) % len(selection)] url = o.absolute_url() else: @@ -456,7 +462,7 @@ class SelectionTool( UniqueObject, SimpleItem ): form_id = request.form_id selection_name = request.list_selection_name selection = self.getSelectionFor(selection_name, REQUEST) - params = selection.getSelectionParams() + params = selection.getParams() lines = params.get('list_lines',0) start = params.get('list_start', 0) params['list_start'] = int(start) + int(lines) @@ -475,11 +481,11 @@ class SelectionTool( UniqueObject, SimpleItem ): form_id = request.form_id selection_name = request.list_selection_name selection = self.getSelectionFor(selection_name, REQUEST) - params = selection.getSelectionParams() + params = selection.getParams() lines = params.get('list_lines',0) start = params.get('list_start', 0) params['list_start'] = max(int(start) - int(lines), 0) - selection.edit(params= selection.selection_params) + selection.edit(params= selection.params) self.uncheckAll(selection_name, listbox_uid) return self.checkAll(selection_name, uids, REQUEST=REQUEST) @@ -495,12 +501,12 @@ class SelectionTool( UniqueObject, SimpleItem ): selection_name = request.list_selection_name selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) if selection is not None: - params = selection.getSelectionParams() + params = selection.getParams() lines = params.get('list_lines',0) start = request.form.get('list_start',0) params['list_start'] = start - selection.edit(params= selection.selection_params) + selection.edit(params= selection.params) self.uncheckAll(selection_name, listbox_uid) return self.checkAll(selection_name, uids, REQUEST=REQUEST) @@ -515,12 +521,12 @@ class SelectionTool( UniqueObject, SimpleItem ): selection_name = request.list_selection_name selection = self.getSelectionFor(selection_name, REQUEST) root_url = request.form.get('domain_root_url','portal_categories') - selection.edit(domain_path=root_url, domain_list=((),)) + selection.edit(domain_path=root_url, domain_list=()) return request.RESPONSE.redirect(request['HTTP_REFERER']) - security.declareProtected(ERP5Permissions.View, 'setDomainList') - def setDomainList(self, REQUEST): + security.declareProtected(ERP5Permissions.View, 'unfoldDomain') + def unfoldDomain(self, REQUEST): """ Sets the root domain for the current selection """ @@ -528,14 +534,33 @@ class SelectionTool( UniqueObject, SimpleItem ): form_id = request.form_id selection_name = request.list_selection_name selection = self.getSelectionFor(selection_name, REQUEST) - domain_list_url = request.form.get('domain_list_url','portal_categories') - if type(domain_list_url) == type('a'): - domain = self.unrestrictedTraverse(domain_list_url) - domain_root = self.unrestrictedTraverse(selection.getSelectionDomainPath()) - selection.edit(domain_list=(domain.getPhysicalPath()[len(domain_root.getPhysicalPath()):],)) + domain_url = request.form.get('domain_url',None) + domain_depth = request.form.get('domain_depth',0) + domain_list = list(selection.getDomainList()) + domain_list = domain_list[0:min(domain_depth, len(domain_list))] + if type(domain_url) == type('a'): + selection.edit(domain_list = domain_list + [domain_url]) return request.RESPONSE.redirect(request['HTTP_REFERER']) + security.declareProtected(ERP5Permissions.View, 'foldDomain') + def foldDomain(self, REQUEST): + """ + Sets the root domain for the current selection + """ + request = REQUEST + form_id = request.form_id + selection_name = request.list_selection_name + selection = self.getSelectionFor(selection_name, REQUEST) + domain_url = request.form.get('domain_url',None) + domain_depth = request.form.get('domain_depth',0) + domain_list = list(selection.getDomainList()) + domain_list = domain_list[0:min(domain_depth, len(domain_list))] + selection.edit(domain_list=filter(lambda x:x != domain_url, domain_list)) + + return request.RESPONSE.redirect(request['HTTP_REFERER']) + + security.declareProtected(ERP5Permissions.View, 'setReportRoot') def setReportRoot(self, REQUEST): """ @@ -546,7 +571,7 @@ class SelectionTool( UniqueObject, SimpleItem ): selection_name = request.list_selection_name selection = self.getSelectionFor(selection_name, REQUEST) root_url = request.form.get('report_root_url','portal_categories') - selection.edit(report_path=root_url, report_list=((),)) + selection.edit(report_path=root_url, report_list=()) return request.RESPONSE.redirect(request['HTTP_REFERER']) @@ -555,19 +580,20 @@ class SelectionTool( UniqueObject, SimpleItem ): def unfoldReport(self, REQUEST): """ Sets the root domain for the current selection + + report_list is a list of relative_url of category, domain, etc. """ request = REQUEST form_id = request.form_id selection_name = request.list_selection_name selection = self.getSelectionFor(selection_name, REQUEST) - report_url = request.form.get('report_url','portal_categories') + report_url = request.form.get('report_url',None) if type(report_url) == type('a'): - report = self.unrestrictedTraverse(report_url) - report_root = self.unrestrictedTraverse(selection.getSelectionReportPath()) - selection.edit(report_list=list(selection.getSelectionReportList()) - + [report.getPhysicalPath()[len(report_root.getPhysicalPath()):],] ) + selection.edit(report_list=list(selection.getReportList()) + [report_url]) - return request.RESPONSE.redirect(request['HTTP_REFERER']) + referer = request['HTTP_REFERER'] + referer = referer.replace('report_depth:int=', 'noreport_depth:int=') + return request.RESPONSE.redirect(referer) security.declareProtected(ERP5Permissions.View, 'foldReport') def foldReport(self, REQUEST): @@ -578,20 +604,14 @@ class SelectionTool( UniqueObject, SimpleItem ): form_id = request.form_id selection_name = request.list_selection_name selection = self.getSelectionFor(selection_name, REQUEST) - report_url = request.form.get('report_url','portal_categories') + report_url = request.form.get('report_url',None) if type(report_url) == type('a'): - report = self.unrestrictedTraverse(report_url) - report_root = self.unrestrictedTraverse(selection.getSelectionReportPath()) - report_path = report.getPhysicalPath()[len(report_root.getPhysicalPath()):] - report_list = selection.getSelectionReportList() - new_report_list = [] - report_path_len = len(report_path) - for p in report_path: - if p[0:report_path_len] != report_path: - new_report_list += [p] - selection.edit(report_list=new_report_list) + report_list = selection.getReportList() + selection.edit(report_list=filter(lambda x:x != report_url, report_list)) - return request.RESPONSE.redirect(request['HTTP_REFERER']) + referer = request['HTTP_REFERER'] + referer = referer.replace('report_depth:int=', 'noreport_depth:int=') + return request.RESPONSE.redirect(referer) security.declareProtected(ERP5Permissions.View, 'setListboxDisplayMode') @@ -621,8 +641,8 @@ class SelectionTool( UniqueObject, SimpleItem ): report_tree_mode=report_tree_mode) # It is better to reset the query when changing the display mode. - params = selection.getSelectionParams() - if 'query' in params: del params['query'] + params = selection.getParams() + if 'where_expression' in params: del params['where_expression'] selection.edit(params = params) referer = request['HTTP_REFERER'] @@ -665,7 +685,7 @@ class SelectionTool( UniqueObject, SimpleItem ): selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) if selection is None: return [] - return selection(selection_method=selection_method, context=context, REQUEST=REQUEST) + return selection(method=selection_method, context=context, REQUEST=REQUEST) security.declareProtected(ERP5Permissions.View, 'getSelectionCheckedValueList') def getSelectionCheckedValueList(self, selection_name, REQUEST=None): @@ -675,7 +695,7 @@ class SelectionTool( UniqueObject, SimpleItem ): selection = self.getSelectionFor(selection_name, REQUEST=REQUEST) if selection is None: return [] - uid_list = selection.getSelectionCheckedUids() + uid_list = selection.getCheckedUids() value_list = self.portal_catalog.getObjectList(uid_list) return value_list @@ -686,7 +706,7 @@ class SelectionTool( UniqueObject, SimpleItem ): """ value_list = self.getSelectionCheckedValueList(selection_name, REQUEST=REQUEST) if len(value_list) == 0: - value_list = self.getSelectionSelectedValueList(selection_name, REQUEST=REQUEST, selection_method=selection_method, context=context) + value_list = self.getSelectionSelectedValueList(selection_name, REQUEST=REQUEST, method=selection_method, context=context) return value_list security.declareProtected(ERP5Permissions.View, 'getSelectionUidList')