Projet

Général

Profil

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

Frédéric Péters, 30 juin 2015 17:35

Télécharger (7,38 ko)

Voir les différences:

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

 wcs/admin/workflows.py              | 65 +++++++++++++++++++++++++++----------
 wcs/qommon/static/css/dc2/admin.css | 19 ++++-------
 2 files changed, 55 insertions(+), 29 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:
117 149
        i = status.id
118 150
        for item in status.items:
119
            next_status_ids = [x.id for x in item.get_target_status()]
151
            next_status_ids = [x.id for x in item.get_target_status() if x.id != status.id]
120 152
            if not next_status_ids:
121 153
                next_status_ids = [status.id]
122 154
            for next_id in next_status_ids:
......
135 167
            label = label.encode('utf8')
136 168
            label = label.replace('\n', '\\n')
137 169
            print >>out, '[label="%s"' % label,
138
            if select == '%s-%s' % (i, item.id):
139
                print >>out, ',color=salmon'
140 170
            print >>out, ',URL="%s%s"]' % (url_prefix, url)
171

  
141 172
    print >>out, '}'
142 173
    out = out.getvalue()
143 174
    if svg:
......
146 177
            out, err = process.communicate(out)
147 178
        except OSError:
148 179
            return ''
180
        out = graphviz_post_treatment(out, revert_colours)
149 181
        if include:
150
            out = graphviz_post_treatment(out)
151 182
            # It seems webkit refuse to accept SVG when using its proper namespace,
152 183
            # and xlink namespace prefix must be xlink: to be acceptable
153 184
            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
-