Projet

Général

Profil

0001-admin-style-workflow-graph-with-colours-7708.patch

Frédéric Péters, 30 juin 2015 14:28

Télécharger (8,1 ko)

Voir les différences:

Subject: [PATCH] admin: style workflow graph with colours (#7708)

 wcs/admin/workflows.py              | 82 +++++++++++++++++++++++--------------
 wcs/qommon/static/css/dc2/admin.css | 19 ++++-----
 2 files changed, 58 insertions(+), 43 deletions(-)
wcs/admin/workflows.py
59 59
        del node.attrib[att]
60 60

  
61 61

  
62
def remove_style(node, top):
62
def remove_style(node, top, colours, white_text=False):
63 63
    remove_tag(node, TITLE)
64 64
    if node.get('fill') == 'white' and node.get('stroke') == 'white':
65 65
        # this is the general white background, wipe it to be transparent
66 66
        node.attrib['fill'] = 'transparent'
67 67
        node.attrib['stroke'] = 'transparent'
68
    if node.tag == svg('text') and white_text:
69
        node.attrib['fill'] = 'white'
68 70
    for child in node:
69 71
        remove_attribute(child, XLINK_TITLE)
70
        style = child.get('style', None)
71
        # Beware ! HACK ! salmon is matched and converted to class="page-subject"
72
        if style:
73
            m = re.search('(?:stroke|fill):salmon', style)
74
            if m:
75
                top.set('class', top.get('class','') + ' page-subject')
76
        if child.get('fill') == 'salmon':
77
            top.set('class', top.get('class', '') + ' page-subject')
72
        if child.get('fill') in colours:
73
            matching_hexa = colours.get(child.get('fill'))
74
            child.attrib['fill'] = '#' + matching_hexa
75
            del child.attrib['stroke']
76
            if misc.get_foreground_colour(matching_hexa) == 'white':
77
                white_text = True
78 78
        if child.get('font-family'):
79 79
            del child.attrib['font-family']
80 80
        if child.get('font-size'):
81 81
            child.attrib['font-size'] = str(float(child.attrib['font-size'])*0.8)
82 82
        remove_attribute(child, 'style')
83
        remove_style(child, top)
83
        remove_style(child, top, colours, white_text=white_text)
84 84

  
85
def graphviz_post_treatment(content):
85
def graphviz_post_treatment(content, colours):
86 86
    ''' Remove all svg:title and top-level svg:polygon nodes, remove style
87 87
        attributes and xlink:title attributes.
88 88

  
......
90 90
        part on as class selector on the top level svg:g element.
91 91
    '''
92 92
    tree = ET.fromstring(content)
93
    style = ET.SubElement(tree, svg('style'))
94
    style.attrib['type'] = 'text/css'
95
    css_url = '%s%s%s' % (get_publisher().get_root_url(),
96
            get_publisher().qommon_static_dir,
97
            get_publisher().qommon_admin_css)
98
    style.text = '@import url(%s);' % css_url
93 99

  
94 100
    for root in tree:
95 101
        remove_tag(root, TITLE)
96 102
        # remove_tag(root, POLYGON)
97 103
        for child in root:
98
            remove_style(child, child)
104
            remove_style(child, child, colours)
99 105
    return ET.tostring(tree)
100 106

  
101 107
def graphviz(workflow, url_prefix='', select=None, svg=True,
102 108
        include=False):
103 109
    out = StringIO()
110
    # a list of colours known to graphviz, they will serve as key to get back
111
    # to the colours defined in wcs.
112
    graphviz_colours = [
113
        'aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure', 'beige',
114
        'bisque', 'black', 'blanchedalmond', 'blue', 'blueviolet', 'brown',
115
        'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral',
116
        'cornflowerblue', 'cornsilk', 'crimson', 'cyan', 'darkblue',
117
        'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkgrey',
118
        'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange',
119
        'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue',
120
        'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet',
121
        'deeppink', 'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue',
122
        'firebrick', 'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro',
123
        'ghostwhite', 'gold', 'goldenrod', 'gray', 'grey', 'green',
124
        'greenyellow', 'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory',
125
        'khaki', 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon',
126
        'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow',
127
        'lightgray', 'lightgreen', 'lightgrey', 'lightpink', ]
128

  
129
    colours = {}
130
    revert_colours = {}
104 131
    print >>out, 'digraph main {'
105 132
    # print >>out, 'graph [ rankdir=LR ];'
106 133
    print >>out, 'node [shape=box,style=filled];'
......
110 137
        print >>out, 'status%s' % i,
111 138
        print >>out, '[label="%s"' % status.name,
112 139
        if select == str(i):
113
            print >>out, ',color=salmon'
140
            print >>out, ',id=current_status'
141
        if status.colour:
142
            if status.colour not in colours:
143
                colours[status.colour] = graphviz_colours.pop()
144
                revert_colours[colours[status.colour]] = status.colour
145
            print >>out, ',color=%s' % colours[status.colour]
114 146
        print >>out, ' URL="%sstatus/%s/"];' % (url_prefix, i)
115 147

  
116 148
    for status in workflow.possible_status:
......
118 150
        for item in status.items:
119 151
            next_status_ids = [x.id for x in item.get_target_status()]
120 152
            if not next_status_ids:
121
                next_status_ids = [status.id]
153
                continue
122 154
            for next_id in next_status_ids:
123 155
                print >>out, 'status%s -> status%s' % (i, next_id)
156
                if item.key == 'timeout' or (item.key == 'jump' and (
157
                        item.condition or item.trigger or item.timeout)):
158
                    print >> out, ' [style=dotted]'
124 159
            url = 'status/%s/items/%s/' % (i, item.id)
125
            if getattr(item, 'label', None):
126
                label = item.label
127
                if getattr(item, 'by', None):
128
                    roles = workflow.render_list_of_roles(item.by)
129
                    label += ' %s %s' % (_('by'), roles)
130
            else:
131
                label = item.render_as_line()
132
            label = label.replace('"', '\\"')
133
            label = label.decode('utf8')
134
            label = textwrap.fill(label, 20, break_long_words=False)
135
            label = label.encode('utf8')
136
            label = label.replace('\n', '\\n')
137
            print >>out, '[label="%s"' % label,
138
            if select == '%s-%s' % (i, item.id):
139
                print >>out, ',color=salmon'
140
            print >>out, ',URL="%s%s"]' % (url_prefix, url)
160
            continue
141 161
    print >>out, '}'
142 162
    out = out.getvalue()
143 163
    if svg:
......
146 166
            out, err = process.communicate(out)
147 167
        except OSError:
148 168
            return ''
169
        out = graphviz_post_treatment(out, revert_colours)
149 170
        if include:
150
            out = graphviz_post_treatment(out)
151 171
            # It seems webkit refuse to accept SVG when using its proper namespace,
152 172
            # and xlink namespace prefix must be xlink: to be acceptable
153 173
            out = out.replace('ns0:', '')
wcs/qommon/static/css/dc2/admin.css
720 720
	width: 100%;
721 721
	height: 100%;
722 722
	margin: auto;
723
	font-family: sans-serif;
723 724
}
724 725

  
725 726
svg .node polygon {
726
	stroke:black;
727
	fill:#EEE;
727
	stroke: #444;
728
	stroke-width: 1px;
728 729
}
729 730

  
730 731
svg .node path {
731
	fill:none;
732
	fill: none;
732 733
	stroke: black;
733 734
}
734 735

  
735 736
svg .edge path {
736 737
	fill:none;
737 738
	stroke: black;
739
	stroke: #666;
738 740
}
739 741
svg .edge polygon {
740 742
	stroke: black;
......
745 747
svg .edge text {
746 748
	font-size: 60%;
747 749
}
748
svg .page-subject.edge text {
749
	fill: #91a9b2;
750
}
751
svg .page-subject polygon {
752
	fill: #91a9b2;
753
	stroke: #91a9b2;
754
}
755
svg .page-subject path {
756
	stroke: #91a9b2;
750
svg #current_status polygon {
751
	stroke-width: 2px;
757 752
}
758 753

  
759 754
.foldable {
760
-