web/views/plots.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 22 Jun 2011 18:53:38 +0200
changeset 7553 935423529f45
parent 7460 2455cdbeadca
child 7569 02c338197322
permissions -rw-r--r--
[datafeed cw parser] refactor: split logic that was in the parser into: * an "item builder" component, turning an etree xml node into a specific python dictionnary representing an entity * "action" components, selected given an entity, a relation and its role in the relation, and responsible to link the entity to given related items (eg dictionnary) This changes make it easy to add new action or to override existing one's behaviour according to the entity, the relation, etc... Also refactor the xml view so one can also override what's included in the tag used to mark the entity as used by a relation, hopefully allowing to reduce the number of http requests needed for a full datafeed import.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7393
diff changeset
     1
# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     2
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     3
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     4
# This file is part of CubicWeb.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     5
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     6
# CubicWeb is free software: you can redistribute it and/or modify it under the
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     7
# terms of the GNU Lesser General Public License as published by the Free
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     8
# Software Foundation, either version 2.1 of the License, or (at your option)
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
     9
# any later version.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    10
#
5424
8ecbcbff9777 replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5421
diff changeset
    11
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT
5421
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    12
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    13
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    14
# details.
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    15
#
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    16
# You should have received a copy of the GNU Lesser General Public License along
8167de96c523 proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5389
diff changeset
    17
# with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
6582
8eb7883b4223 [pylint] fix a bug of pylint detected errors and i18n pb (calling builtins._ instead of req._)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5940
diff changeset
    18
"""basic plot views"""
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
    19
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
    20
__docformat__ = "restructuredtext en"
6582
8eb7883b4223 [pylint] fix a bug of pylint detected errors and i18n pb (calling builtins._ instead of req._)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5940
diff changeset
    21
_ = unicode
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
    22
4466
8b0ca7904820 moved generic datetime manipulation function to lgc
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4459
diff changeset
    23
from logilab.common.date import datetime2ticks
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2161
diff changeset
    24
from logilab.mtconverter import xml_escape
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    25
5940
0e3ae19b181a [uilib] refactor json_dumps code organization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5424
diff changeset
    26
from cubicweb.utils import UStringIO, json_dumps
2657
de974465d381 [appobject] kill VObject class, move base selector classes to appobject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2312
diff changeset
    27
from cubicweb.appobject import objectify_selector
4320
4efd4c306746 closes #345410: two_lines_rset, two_cols_rset, two_etypes_rset are badly named
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
    28
from cubicweb.selectors import multi_columns_rset
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    29
from cubicweb.web.views import baseviews
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    30
742
99115e029dca replaced most of __selectors__ assignments with __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 0
diff changeset
    31
@objectify_selector
2161
200481e7b156 prepare time where it won't be mandatory to give rset to select()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2009
diff changeset
    32
def all_columns_are_numbers(cls, req, rset=None, *args, **kwargs):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    33
    """accept result set with at least one line and two columns of result
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    34
    all columns after second must be of numerical types"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    35
    for etype in rset.description[0]:
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7393
diff changeset
    36
        if etype not in ('Int', 'BigInt', 'Float'):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    37
            return 0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    38
    return 1
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    39
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
    40
@objectify_selector
2161
200481e7b156 prepare time where it won't be mandatory to give rset to select()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2009
diff changeset
    41
def second_column_is_number(cls, req, rset=None, *args, **kwargs):
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
    42
    etype = rset.description[0][1]
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7393
diff changeset
    43
    if etype not  in ('Int', 'BigInt', 'Float'):
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
    44
        return 0
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
    45
    return 1
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
    46
1888
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    47
@objectify_selector
2161
200481e7b156 prepare time where it won't be mandatory to give rset to select()
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2009
diff changeset
    48
def columns_are_date_then_numbers(cls, req, rset=None, *args, **kwargs):
1888
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    49
    etypes = rset.description[0]
7166
dde161937d3e [time zone] support for TZDatetime and TZTime data type
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 6582
diff changeset
    50
    if etypes[0] not in ('Date', 'Datetime', 'TZDatetime'):
1888
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    51
        return 0
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    52
    for etype in etypes[1:]:
7460
2455cdbeadca [schema] support for BigInt type. Closes #1720995
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7393
diff changeset
    53
        if etype not in ('Int', 'BigInt', 'Float'):
1888
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    54
            return 0
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    55
    return 1
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    56
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    57
1888
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    58
def filterout_nulls(abscissa, plot):
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    59
    filtered = []
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    60
    for x, y in zip(abscissa, plot):
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    61
        if x is None or y is None:
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    62
            continue
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    63
        filtered.append( (x, y) )
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
    64
    return sorted(filtered)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    65
1892
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    66
class PlotWidget(object):
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    67
    # XXX refactor with cubicweb.web.views.htmlwidgets.HtmlWidget
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    68
    def _initialize_stream(self, w=None):
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    69
        if w:
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    70
            self.w = w
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    71
        else:
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    72
            self._stream = UStringIO()
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    73
            self.w = self._stream.write
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    74
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    75
    def render(self, *args, **kwargs):
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    76
        w = kwargs.pop('w', None)
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    77
        self._initialize_stream(w)
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    78
        self._render(*args, **kwargs)
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    79
        if w is None:
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    80
            return self._stream.getvalue()
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    81
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    82
class FlotPlotWidget(PlotWidget):
1891
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
    83
    """PlotRenderer widget using Flot"""
4209
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    84
    onload = u"""
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    85
var fig = jQuery("#%(figid)s");
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    86
if (fig.attr('cubicweb:type') != 'prepared-plot') {
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    87
    %(plotdefs)s
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    88
    jQuery.plot(jQuery("#%(figid)s"), [%(plotdata)s],
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    89
        {points: {show: true},
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    90
         lines: {show: true},
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    91
         grid: {hoverable: true},
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    92
         xaxis: {mode: %(mode)s}});
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    93
    jQuery("#%(figid)s").bind("plothover", onPlotHover);
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    94
    fig.attr('cubicweb:type','prepared-plot');
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    95
}
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
    96
"""
1892
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
    97
1891
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
    98
    def __init__(self, labels, plots, timemode=False):
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
    99
        self.labels = labels
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   100
        self.plots = plots # list of list of couples
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   101
        self.timemode = timemode
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   102
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   103
    def dump_plot(self, plot):
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   104
        # XXX for now, the only way that we have to customize properly
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   105
        #     datetime labels on tooltips is to insert an additional column
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   106
        #     cf. function onPlotHover in cubicweb.flot.js
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   107
        if self.timemode:
4721
8f63691ccb7f pylint style fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4719
diff changeset
   108
            plot = [(datetime2ticks(x), y, datetime2ticks(x)) for x, y in plot]
5940
0e3ae19b181a [uilib] refactor json_dumps code organization
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 5424
diff changeset
   109
        return json_dumps(plot)
1892
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   110
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   111
    def _render(self, req, width=500, height=400):
4209
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
   112
        if req.ie_browser():
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
   113
            req.add_js('excanvas.js')
8712d699beb2 do not recompute the plot on subsequent onload events #615338
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents: 3785
diff changeset
   114
        req.add_js(('jquery.flot.js', 'cubicweb.flot.js'))
3338
cd137d90f896 can't use anymore make_uid to generate a valid js var name
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 3097
diff changeset
   115
        figid = u'figure%s' % req.varmaker.next()
1891
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   116
        plotdefs = []
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   117
        plotdata = []
1892
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   118
        self.w(u'<div id="%s" style="width: %spx; height: %spx;"></div>' %
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   119
               (figid, width, height))
1891
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   120
        for idx, (label, plot) in enumerate(zip(self.labels, self.plots)):
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   121
            plotid = '%s_%s' % (figid, idx)
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   122
            plotdefs.append('var %s = %s;' % (plotid, self.dump_plot(plot)))
3714
3cb7dcd9ae77 ugly workaround to javascript serialisation problem #481437 (not considered fixed by this changeset)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3689
diff changeset
   123
            # XXX ugly but required in order to not crash my demo
3cb7dcd9ae77 ugly workaround to javascript serialisation problem #481437 (not considered fixed by this changeset)
Alexandre Fayolle <alexandre.fayolle@logilab.fr>
parents: 3689
diff changeset
   124
            plotdata.append("{label: '%s', data: %s}" % (label.replace(u'&', u''), plotid))
1891
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   125
        req.html_headers.add_onload(self.onload %
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   126
                                    {'plotdefs': '\n'.join(plotdefs),
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   127
                                     'figid': figid,
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   128
                                     'plotdata': ','.join(plotdata),
5041
ebdab53b0c45 [cleanup] remove 3.7 deprecation warning
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4721
diff changeset
   129
                                     'mode': self.timemode and "'time'" or 'null'})
1892
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   130
1891
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   131
1888
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
   132
class PlotView(baseviews.AnyRsetView):
3408
c92170fca813 [api] use __regid__ instead of deprecated id
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3338
diff changeset
   133
    __regid__ = 'plot'
1888
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
   134
    title = _('generic plot')
4320
4efd4c306746 closes #345410: two_lines_rset, two_cols_rset, two_etypes_rset are badly named
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   135
    __select__ = multi_columns_rset() & all_columns_are_numbers()
1891
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   136
    timemode = False
7390
be2fffc9ec17 [plot views] don't paginate
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7166
diff changeset
   137
    paginable = False
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   138
1888
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
   139
    def call(self, width=500, height=400):
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
   140
        # prepare data
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3408
diff changeset
   141
        rqlst = self.cw_rset.syntax_tree()
1888
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
   142
        # XXX try to make it work with unions
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
   143
        varnames = [var.name for var in rqlst.children[0].get_selected_variables()][1:]
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3408
diff changeset
   144
        abscissa = [row[0] for row in self.cw_rset]
1891
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   145
        plots = []
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3408
diff changeset
   146
        nbcols = len(self.cw_rset.rows[0])
1891
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   147
        for col in xrange(1, nbcols):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3408
diff changeset
   148
            data = [row[col] for row in self.cw_rset]
1991
8a9d8f1ee100 bugfix for plots
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 1977
diff changeset
   149
            plots.append(filterout_nulls(abscissa, data))
1891
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   150
        plotwidget = FlotPlotWidget(varnames, plots, timemode=self.timemode)
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3408
diff changeset
   151
        plotwidget.render(self._cw, width, height, w=self.w)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   152
1888
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
   153
f36d43f00f32 [views] plot with flot and get rid of matplotlib
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1886
diff changeset
   154
class TimeSeriePlotView(PlotView):
4320
4efd4c306746 closes #345410: two_lines_rset, two_cols_rset, two_etypes_rset are badly named
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   155
    __select__ = multi_columns_rset() & columns_are_date_then_numbers()
1891
dd7c1d7715e7 [views][plots] extract the plotting mechanism in an HTMLWidget to make mit more re-usable
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1888
diff changeset
   156
    timemode = True
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   157
1892
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   158
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   159
try:
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   160
    from GChartWrapper import Pie, Pie3D
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   161
except ImportError:
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   162
    pass
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   163
else:
1892
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   164
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   165
    class PieChartWidget(PlotWidget):
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   166
        def __init__(self, labels, values, pieclass=Pie, title=None):
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   167
            self.labels = labels
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   168
            self.values = values
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   169
            self.pieclass = pieclass
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   170
            self.title = title
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   171
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   172
        def _render(self, width=None, height=None):
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   173
            piechart = self.pieclass(self.values)
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   174
            piechart.label(*self.labels)
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   175
            if width is not None:
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   176
                height = height or width
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   177
                piechart.size(width, height)
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   178
            if self.title:
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   179
                piechart.title(self.title)
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2161
diff changeset
   180
            self.w(u'<img src="%s" />' % xml_escape(piechart.url))
1892
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   181
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   182
    class PieChartView(baseviews.AnyRsetView):
3408
c92170fca813 [api] use __regid__ instead of deprecated id
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3338
diff changeset
   183
        __regid__ = 'piechart'
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   184
        pieclass = Pie
7390
be2fffc9ec17 [plot views] don't paginate
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7166
diff changeset
   185
        paginable = False
1892
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   186
4320
4efd4c306746 closes #345410: two_lines_rset, two_cols_rset, two_etypes_rset are badly named
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 4252
diff changeset
   187
        __select__ = multi_columns_rset() & second_column_is_number()
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   188
1956
9865daa96cd7 [views][plot] piechart view now accepts either final or non final entities in the first column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1911
diff changeset
   189
        def _guess_vid(self, row):
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3408
diff changeset
   190
            etype = self.cw_rset.description[row][0]
4045
f4a52abb6f4f cw 3.6 api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents: 3890
diff changeset
   191
            if self._cw.vreg.schema.eschema(etype).final:
1956
9865daa96cd7 [views][plot] piechart view now accepts either final or non final entities in the first column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1911
diff changeset
   192
                return 'final'
9865daa96cd7 [views][plot] piechart view now accepts either final or non final entities in the first column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1911
diff changeset
   193
            return 'textincontext'
9865daa96cd7 [views][plot] piechart view now accepts either final or non final entities in the first column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1911
diff changeset
   194
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   195
        def call(self, title=None, width=None, height=None):
1956
9865daa96cd7 [views][plot] piechart view now accepts either final or non final entities in the first column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1911
diff changeset
   196
            labels = []
9865daa96cd7 [views][plot] piechart view now accepts either final or non final entities in the first column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1911
diff changeset
   197
            values = []
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3408
diff changeset
   198
            for rowidx, (_, value) in enumerate(self.cw_rset):
1956
9865daa96cd7 [views][plot] piechart view now accepts either final or non final entities in the first column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1911
diff changeset
   199
                if value is not None:
9865daa96cd7 [views][plot] piechart view now accepts either final or non final entities in the first column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1911
diff changeset
   200
                    vid = self._guess_vid(rowidx)
7393
7824d61f41a2 fix some deprecation warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 7390
diff changeset
   201
                    label = '%s: %s' % (self._cw.view(vid, self.cw_rset, row=rowidx, col=0),
1956
9865daa96cd7 [views][plot] piechart view now accepts either final or non final entities in the first column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1911
diff changeset
   202
                                        value)
3451
6b46d73823f5 [api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3408
diff changeset
   203
                    labels.append(label.encode(self._cw.encoding))
1956
9865daa96cd7 [views][plot] piechart view now accepts either final or non final entities in the first column
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1911
diff changeset
   204
                    values.append(value)
1892
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   205
            pie = PieChartWidget(labels, values, pieclass=self.pieclass,
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   206
                                 title=title)
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   207
            if width is not None:
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   208
                height = height or width
1892
fb80d9c434e5 [views] extract a PieWidget from pie views
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1891
diff changeset
   209
            pie.render(width, height, w=self.w)
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   210
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   211
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   212
    class PieChart3DView(PieChartView):
3408
c92170fca813 [api] use __regid__ instead of deprecated id
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 3338
diff changeset
   213
        __regid__ = 'piechart3D'
1886
f0e28ddba7c5 [views] add pie chart views with google chart / GChartWrapper
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1133
diff changeset
   214
        pieclass = Pie3D