[hooks] don't delete composed of a composite where relation is being removed from the schema
"""basic plot views:organization: Logilab:copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses"""__docformat__="restructuredtext en"importosimporttimefromsimplejsonimportdumpsfromlogilab.commonimportflattenfromlogilab.mtconverterimportxml_escapefromcubicweb.utilsimportmake_uid,UStringIO,datetime2ticksfromcubicweb.appobjectimportobjectify_selectorfromcubicweb.web.viewsimportbaseviews@objectify_selectordefat_least_two_columns(cls,req,rset=None,*args,**kwargs):ifnotrset:return0returnlen(rset.rows[0])>=2@objectify_selectordefall_columns_are_numbers(cls,req,rset=None,*args,**kwargs):"""accept result set with at least one line and two columns of result all columns after second must be of numerical types"""foretypeinrset.description[0]:ifetypenotin('Int','Float'):return0return1@objectify_selectordefsecond_column_is_number(cls,req,rset=None,*args,**kwargs):etype=rset.description[0][1]ifetypenotin('Int','Float'):return0return1@objectify_selectordefcolumns_are_date_then_numbers(cls,req,rset=None,*args,**kwargs):etypes=rset.description[0]ifetypes[0]notin('Date','Datetime'):return0foretypeinetypes[1:]:ifetypenotin('Int','Float'):return0return1deffilterout_nulls(abscissa,plot):filtered=[]forx,yinzip(abscissa,plot):ifxisNoneoryisNone:continuefiltered.append((x,y))returnsorted(filtered)classPlotWidget(object):# XXX refactor with cubicweb.web.views.htmlwidgets.HtmlWidgetdef_initialize_stream(self,w=None):ifw:self.w=welse:self._stream=UStringIO()self.w=self._stream.writedefrender(self,*args,**kwargs):w=kwargs.pop('w',None)self._initialize_stream(w)self._render(*args,**kwargs)ifwisNone:returnself._stream.getvalue()classFlotPlotWidget(PlotWidget):"""PlotRenderer widget using Flot"""onload=u'''%(plotdefs)sjQuery.plot(jQuery("#%(figid)s"), [%(plotdata)s], {points: {show: true}, lines: {show: true}, grid: {hoverable: true}, xaxis: {mode: %(mode)s}});jQuery("#%(figid)s").bind("plothover", onPlotHover);'''def__init__(self,labels,plots,timemode=False):self.labels=labelsself.plots=plots# list of list of couplesself.timemode=timemodedefdump_plot(self,plot):# XXX for now, the only way that we have to customize properly# datetime labels on tooltips is to insert an additional column# cf. function onPlotHover in cubicweb.flot.jsifself.timemode:plot=[(datetime2ticks(x),y,datetime2ticks(x))forx,yinplot]returndumps(plot)def_render(self,req,width=500,height=400):# XXX IE requires excanvas.jsreq.add_js(('jquery.flot.js','cubicweb.flot.js','excanvas.js'))figid=u'figure%s'%req.varmaker.next()plotdefs=[]plotdata=[]self.w(u'<div id="%s" style="width: %spx; height: %spx;"></div>'%(figid,width,height))foridx,(label,plot)inenumerate(zip(self.labels,self.plots)):plotid='%s_%s'%(figid,idx)plotdefs.append('var %s = %s;'%(plotid,self.dump_plot(plot)))plotdata.append("{label: '%s', data: %s}"%(label,plotid))req.html_headers.add_onload(self.onload%{'plotdefs':'\n'.join(plotdefs),'figid':figid,'plotdata':','.join(plotdata),'mode':self.timemodeand"'time'"or'null'})classPlotView(baseviews.AnyRsetView):id='plot'title=_('generic plot')__select__=at_least_two_columns()&all_columns_are_numbers()timemode=Falsedefcall(self,width=500,height=400):# prepare datarqlst=self.rset.syntax_tree()# XXX try to make it work with unionsvarnames=[var.nameforvarinrqlst.children[0].get_selected_variables()][1:]abscissa=[row[0]forrowinself.rset]plots=[]nbcols=len(self.rset.rows[0])forcolinxrange(1,nbcols):data=[row[col]forrowinself.rset]plots.append(filterout_nulls(abscissa,data))plotwidget=FlotPlotWidget(varnames,plots,timemode=self.timemode)plotwidget.render(self.req,width,height,w=self.w)classTimeSeriePlotView(PlotView):__select__=at_least_two_columns()&columns_are_date_then_numbers()timemode=Truetry:fromGChartWrapperimportPie,Pie3DexceptImportError:passelse:classPieChartWidget(PlotWidget):def__init__(self,labels,values,pieclass=Pie,title=None):self.labels=labelsself.values=valuesself.pieclass=pieclassself.title=titledef_render(self,width=None,height=None):piechart=self.pieclass(self.values)piechart.label(*self.labels)ifwidthisnotNone:height=heightorwidthpiechart.size(width,height)ifself.title:piechart.title(self.title)self.w(u'<img src="%s" />'%xml_escape(piechart.url))classPieChartView(baseviews.AnyRsetView):id='piechart'pieclass=Pie__select__=at_least_two_columns()&second_column_is_number()def_guess_vid(self,row):etype=self.rset.description[row][0]ifself.schema.eschema(etype).is_final():return'final'return'textincontext'defcall(self,title=None,width=None,height=None):labels=[]values=[]forrowidx,(_,value)inenumerate(self.rset):ifvalueisnotNone:vid=self._guess_vid(rowidx)label='%s: %s'%(self.view(vid,self.rset,row=rowidx,col=0),value)labels.append(label.encode(self.req.encoding))values.append(value)pie=PieChartWidget(labels,values,pieclass=self.pieclass,title=title)ifwidthisnotNone:height=heightorwidthpie.render(width,height,w=self.w)classPieChart3DView(PieChartView):id='piechart3D'pieclass=Pie3D