<?xml version="1.0" encoding="utf-8" ?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:dc="http://purl.org/dc/elements/1.1/"
         xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
         xmlns="http://purl.org/rss/1.0/">




    



<channel rdf:about="http://www.plomino.net/recent-changes/RSS">
  <title>Recent changes</title>
  <link>http://www.plomino.net</link>

  <description>
    
      
    
  </description>

  

  
            <syn:updatePeriod>daily</syn:updatePeriod>
            <syn:updateFrequency>1</syn:updateFrequency>
            <syn:updateBase>2010-05-28T12:51:26Z</syn:updateBase>
        

  <image rdf:resource="http://www.plomino.net/logo.png"/>

  <items>
    <rdf:Seq>
      
        <rdf:li rdf:resource="http://www.plomino.net/how-to/produce-printable-documents"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/samples/printable-documents"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/how-to/use-cache-to-improve-performances"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/how-to/export-documents-data-as-csv-or-xls"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/samples/csv-export-sample"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/how-to/dynamic-search-results-with-jquery"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/samples/jquery-example"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/how-to/auto-increment-chrono"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/how-to/multilingual-applications"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/first-steps/tutorial-screencast"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/first-steps/beginners-guide-screencast"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/how-to/advanced/provide-a-custom-plomino-field-type-as-a-plugin"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/samples/dynamic-hiding"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/how-to/restrict-access-to-documents"/>
      
      
        <rdf:li rdf:resource="http://www.plomino.net/samples/charts-example"/>
      
    </rdf:Seq>
  </items>

</channel>


  <item rdf:about="http://www.plomino.net/how-to/produce-printable-documents">
    <title>Produce printable documents</title>
    <link>http://www.plomino.net/how-to/produce-printable-documents</link>
    <description></description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>If you want your users to be able to print Plomino documents, you can just let them use the Plone print function.</p>
<p>Note: if this function is not visible in your Plone site, go to ZMI /  portal_actions / document_actions / print, check Visible, and save. The  Print action will be displayed in the bottom-right corner of the  content area.</p>
<p>The Plone print function allows to print the current page and as  Plone provides some print-specific CSS, the rendering is correct  (navigation, portlets, background, etc., are all removed, so the printed  document only contains the content itself).</p>
<p>Nevertheless in some cases, you might need to change the document  content itself for printing (for instance, if some parts of the Plomino  documents are dynamic, or you prefer to hide some of the fields, etc.).</p>
<p>To do so, you need to create a Plomino form that will produce the  print-specific layout. You can create it from scratch (and then just  make sure you create fields having the very same ids as the fields from  the original form), or you can just copy/paste your original form (go to  your database contents tab, and then copy/paste the form) and then  change its layout and/or its fields settings.</p>
<p>Let's assume your regular form is frmEmployee, and your print-specific form is frmEmployeePrint.</p>
<p>If you open an employee document using its regular url, like this:</p>
<pre><a class="external-link" href="../samples/printable-documents/plomino_documents/eric-brehault">http://www.plomino.net/samples/printable-documents/plomino_documents/eric-brehault</a></pre>
<p>it is displayed using the form it has been created with, in our case: frmEmployee.</p>
<p>If you want to display it with the frmEmployeePrint form, you can use the openwithform url parameter:</p>
<pre><a class="external-link" href="../samples/printable-documents/plomino_documents/eric-brehault?openwithform=frmEmployeePrint">http://www.plomino.net/samples/printable-documents/plomino_documents/eric-brehault?openwithform=frmEmployeePrint</a></pre>
<p>As you can see, it does display the same document but the layout is the one implemented by frmEmployeePrint.</p>
<p>So, to provide access to the printable version of a document, we need to generate such alink into the frmEmployee form.</p>
<p>We do it using a computed for display rich text field having the following formula:</p>
<pre>html="""&lt;a href="%s?openwithform=frmEmployeePrint" target="_new"&gt;Print&lt;/a&gt;""" % context.doc_url()<br />return html</pre>
<p>Note: we add target="_new" so the resulting page is opened in a new tab in the user web browser.</p>
<p>And now you just need to make sure the web browser print function is called as soon as the user open this page.</p>
<p>You do it by adding a computed for display rich text field in frmEmployeePrint:</p>
<pre>html="""&lt;script&gt;<br />this.print();<br />&lt;/script&gt;"""<br />return html</pre>
<p>Note: the resulting print uses the Plone print-specific CSS, but if  you do not want that, you can use the /OpenBareDocument directive that  will only return the Plomino form layout only:</p>
<pre><a class="external-link" href="../samples/printable-documents/plomino_documents/eric-brehault/OpenBareDocument?openwithform=frmEmployeePrint">http://www.plomino.net/samples/printable-documents/plomino_documents/eric-brehault/OpenBareDocument?openwithform=frmEmployeePrint</a></pre>
<p>This way you can control entirely the print layout independently from Plone.</p>
<p>The sample can be downloaded <a class="external-link" href="../samples/download-samples/printable.xml/at_download/file">here</a>.</p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2012-03-02T20:59:30Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/samples/printable-documents">
    <title>Printable documents</title>
    <link>http://www.plomino.net/samples/printable-documents</link>
    <description></description>
    
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2012-03-02T20:37:45Z</dc:date>
    <dc:type>PlominoDatabase</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/how-to/use-cache-to-improve-performances">
    <title>Use cache to improve performances</title>
    <link>http://www.plomino.net/how-to/use-cache-to-improve-performances</link>
    <description>Plomino 1.13 provides a cache mechanism.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>If your Plomino application contain some time consumming formulas, you speed up the page display using the new cache API provided by Plomino 1.13.</p>
<p>Here is an example:</p>
<pre>result = db.getCache('my_cache_key')
if not result:
    result = make_something_which_cost_CPU(stuff)
db.setCache('my_cache_key', result)</pre>
<p class=" ">The first time the formula will be called, the make_something_which_cost_CPU function will executed, and the result will be put into the cache.</p>
<p class=" ">Next time the formula is called, the result is directly read from the cache.</p>
<p class=" ">As the cache key is a constant ('my_cache_key'), it will be the same in all the cases (for all the users, in all the pages, etc.).</p>
<p class=" ">But of course, the make_something_which_cost_CPU function might return a different value depending on the context. If so, you need the produce a cache key that will reflect this context accurately.</p>
<p class=" ">For instance, if the result is different according the use, an accurate cache key could be:</p>
<pre class=" ">cache_key = "result_for_"+context.getCurrentUser().getMemberId()</pre>
<p class=" ">or depending on the document:</p>
<pre class=" ">cache_key = "result_for_"+context.id</pre>
<p class=" ">or anything you might need.</p>
<p class=" ">Another use case is the repeated usage of a same formula in the same page: sometimes, when rendering a document using a form, several computed fields make the same computing (typical example: you display a table of values, and also a bar chart based on those values).</p>
<p>The code itself can be factorized using a script library in the /resources folder, but it will be run twice anyway when rendering the page.</p>
<p>And it might impact the performances.</p>
<p>Unfortunately, setCache and getCache might not be relevant because you want the formula to be re-evaluated everytime a user displays the page. In that case, you can use setRequestCache and getRequestCache, so the cache will be associated with the current request, and will only last as long as the request will:</p>
<pre>result = db.getRequestCache('my_cache_key')
if not result:
    result = make_something_which_cost_CPU(stuff)
db.setRequestCache('my_cache_key', result)</pre>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-12-01T21:04:15Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/how-to/export-documents-data-as-csv-or-xls">
    <title>Export documents data as CSV or XLS</title>
    <link>http://www.plomino.net/how-to/export-documents-data-as-csv-or-xls</link>
    <description>Different ways to produce a CSV or XLS output.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>An CSV (or XLS) export can be done in two ways:</p>
<ul>
<li>either by using the Plomino API to export the content of any PlominoView,</li>
<li>either by producing your own CSV content using a PlominoAgent.</li>
</ul>
<p>Let's consider a <a class="external-link" href="../samples/csv-export-sample">database</a> where documents have the following items: employee name, country, and age.</p>
<p>If you call <a class="external-link" href="../samples/csv-export-sample/allfrmEmployee/exportCSV">/exportCSV</a> or <a class="external-link" href="../samples/csv-export-sample/allfrmEmployee/exportCSV">/exportXLS</a> on view's URL, you get the actual content of the view as CSV or XLS.</p>
<p>If you want to provide a button to your users, just create a Redirect action into the view to produce the URL:</p>
<pre>context.absolute_url()+"/exportCSV"</pre>
<p>Now, let's imagine you want to process the data before producing the output. For instance, instead of exporting the age value, you want to export "Senior" or "Junior" depending on the age is higher or lower than 40.</p>
<p>To do that, we create an agent which will collect the data into an array, and then return the array content as CSV:</p>
<pre>db = context.getParentDatabase()<br />all = db.getAllDocuments()<br />results = []<br />for doc in all:<br /> age = doc.age<br /> if age &gt;= 40:<br /> age_range = "Senior"<br /> else:<br /> age_range = "Junior"<br /> results.append([doc.employee, doc.country, age_range])<br /><br />context.REQUEST.RESPONSE.setHeader('content-type', 'text/csv; charset=utf-8')<br />context.REQUEST.RESPONSE.setHeader("Content-Disposition", "attachment; filename=my_special_export.csv")<br />context.REQUEST.RESPONSE.setBody(array_to_csv(results))</pre>
<p>To produce an XLS export, do not return a CSV content but an HTML table, and just change the content-type header to 'application/vnd.ms-excel; charset=utf-8', to pretend it is an actual Excel content, so your browser will launch the appropriate application to display it (that is basically what the exportXLS Plomino method does: <a class="external-link" href="https://github.com/plomino/Plomino/blob/1.12/Products/CMFPlomino/PlominoView.py#L479">see source code</a>)</p>
<p>Note: of course in that very simple case, we could also have create an extra view with a column displaying Senior or Junior, and then export that view.</p>
<p>And here again you can provide a redirect acgion to call the agent url more easily:</p>
<pre>context.getParentDatabase().absolute_url()+"/export_csv/runAgent"</pre>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-10-04T22:18:30Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/samples/csv-export-sample">
    <title>CSV export sample</title>
    <link>http://www.plomino.net/samples/csv-export-sample</link>
    <description></description>
    
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-10-04T18:57:00Z</dc:date>
    <dc:type>PlominoDatabase</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/how-to/dynamic-search-results-with-jquery">
    <title>Dynamic search results with JQuery</title>
    <link>http://www.plomino.net/how-to/dynamic-search-results-with-jquery</link>
    <description>How to refresh search results automatically every time the user checks a criteria.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h3>Context</h3>
<p>We want to do a dynamic search form like <a class="external-link" href="../samples/jquery-example">that</a>.</p>
<p>Let's assume we have built a basic database to post job descriptions. Our frmJob form contains the following fields:</p>
<ul>
<li>job_title (text)</li>
<li>job_location (a selection list)</li>
<li>job_skills (a selection list)</li>
<li>job_description (text)</li>
</ul>
<p>Let's make sure they are indexed so we can query the Plomino index on those fields.</p>
<h3>Principle</h3>
<p>To provide our search feature, we will not create a single Dynamic page form containing the criteria fields, a submit button and a computed field to display the results.</p>
<p>We need to split it in two different forms:</p>
<ul>
<li>the search form (named 'dynamicSearch' in the sample db), containing the editable criteria fields,</li>
<li>the result form (named 'filtredResults' in the sample db), able to read the submitted criteria and to produce the results.</li>
</ul>
<p>And, most importantly, we will add some JQuery code into the search form in order get the current values of the criteria, submit them to the result form, extract the produced results and insert them dynamically into the search form.</p>
<h3>The result form</h3>
<p>The result form contains only one field named 'results'. It is a computed for display rich text field.</p>
<p>Its formula reads the criteria values submitted in the request, performs the search and format the results as HTML:</p>
<pre>db = context.getParentDatabase()

query = {'Form': 'frmJob'}

# read submitted criteria
any_criteria = False
job_location = context.REQUEST.get("job_location")
if job_location:
  any_criteria = True
  query['job_location']=job_location

job_skills = context.REQUEST.get("job_skills")
if job_skills:
  any_criteria = True
  query['job_skills']=job_skills

# perform the search
if any_criteria:
  search_results = db.getIndex().dbsearch(query)
else:
  return """Please select at least one criteria..."""
search_results_cnt = len(search_results)

# format the output
html = u''
html += """ %(found)d result(s) found...&lt;br /&gt;""" % { 'found': search_results_cnt}
html += "&lt;ul&gt;"
for result in search_results:
  doc = result.getObject()
  html += """&lt;li&gt;&lt;a href="%(link)s"&gt;%(title)s&lt;/a&gt; (%(location)s)
&lt;p&gt;&lt;span class="discreet"&gt;%(description)s&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Skills: %(skills)s&lt;/p&gt;&lt;/li&gt;
""" % {'link': doc.absolute_url_path(),
'title': doc.getItem('job_title'),
'description': doc.getItem('job_description'),
'location': doc.getRenderedItem('job_location'),
'skills': doc.getRenderedItem('job_skills'),
}
html += "&lt;/ul&gt;"
return html</pre>
<p>So if we call an url like this:</p>
<p><a class="external-link" href="../samples/jquery-example/filteredResults?job_location=Africa">http://www.plomino.net/samples/jquery-example/filteredResults?job_location=Africa</a></p>
<p class=" ">we get the list of all jobs located in Africa.</p>
<p class=" ">But, actually, we are not interested in the entire Plone layout (navigation, portlets, etc.), and as we plan to load this page via an AJAX call just to extract the results list, we might prefer to load a smaller page.</p>
<p class=" ">An url like that will be more accurate:</p>
<p class=" "><a class="external-link" href="../samples/jquery-example/filteredResults/OpenBareForm?job_location=Africa">http://www.plomino.net/samples/jquery-example/filteredResults/OpenBareForm?job_location=Africa</a></p>
<p class=" ">Note: direct access to /filteredResults makes an implicit call to /filteredResults/OpenForm, here we explicitly calls /filteredResults/OpenBareForm.</p>
<h3>The search form</h3>
<p>The search form contains editable fields for criterias (in the sample: job_skills and job_location).</p>
<p>It also contains a computed for display rich text field, named 'display_results' producing two elements:</p>
<ul>
<li>an empty &lt;div id="result_list"&gt; tag which content will be loaded by a JQuery call,</li>
<li>a &lt;script&gt; tag containing the javascript code.</li>
</ul>
<p>This javascript code defines a function which serializes the form's inputs current values to produce the accurate query on /filteredResults/OpenBareForm (using JQuery.serialize()), then calls the resulting url, extracts the content, and inserts it in the target div tag (using JQuery.load()).</p>
<p>Then we bind the form's onChange event to this function. We also insert the spinner.gif image <img src="spinner.gif" /> into the target div, so the user knows the results are loading.</p>
<pre>searchurl = context.getParentDatabase().absolute_url_path() +"/filteredResults/OpenBareForm?"
html="""
&lt;script&gt;
function get_results() {
    criteria = jq('#plomino_form').serialize();
    jq('#result_list').load("%s"+criteria+" #plomino_form");
}
jq(document).ready(function() {
  jq('#plomino_form input').change(function() {
  jq('#result_list').html("&lt;img src='spinner.gif' /&gt;");
  get_results();
  });

  get_results();
});
&lt;/script&gt;
&lt;div id="result_list"&gt;&lt;/div&gt;
""" % searchurl

return html</pre>
<p>The entire sample can be downloaded <a class="internal-link" href="../samples/download-samples/jquery-example.xml">here</a> so you can import into your own Plone site (or on plomino.com) and play with it.</p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    
      <dc:subject>jquery</dc:subject>
    
    <dc:date>2012-03-06T19:02:33Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/samples/jquery-example">
    <title>JQuery example</title>
    <link>http://www.plomino.net/samples/jquery-example</link>
    <description></description>
    
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-09-28T20:23:51Z</dc:date>
    <dc:type>PlominoDatabase</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/how-to/auto-increment-chrono">
    <title>Auto-increment chrono</title>
    <link>http://www.plomino.net/how-to/auto-increment-chrono</link>
    <description>How to produce a unique auto-increment chrono for your documents.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>If you have a corporate document naming convention, you probably need your document to contain a Reference ID like that: "A0-ACME-001", "A0-ACME-002", "A0-ACME-003", etc.</p>
<p>One part of this reference id being an auto-increment chrono, how to generate it ?</p>
<p>A basic approach could be to count the existing documents and add one to the result, but if some documents are deleted, it migh produce identical ids.</p>
<p>Another basic approach is to get the last numbered document, extract its chrono value, and add one.</p>
<p>But the cleaner approachto implement an auto-increment chrono is to create a specific form that will be use to create a unique document where we will store the current chrono value.</p>
<p>Let's create a form named frmChrono containing a number field named 'chrono'. You create only one doc with this form, and you enter the value 0 in the field.</p>
<p>Then, in your main form (where you need to handle the auto-incremented value), you create a Computed on creation number field (named ReferenceID for instance) with the following formula:</p>
<pre>db=plominoDocument.getParentDatabase()<br />searchchrono=db.getIndex().dbsearch({"Form": "frmChrono"})<br />chronodoc=searchchrono[0]<br />currentvalue=chronodoc.chrono<br />newvalue=currentvalue+1<br /># store back the new chrono in the chrono doc<br />chronodoc.setItem("chrono", newvalue)<br /># return the reference id properly formatted<br />return "A0-ACME-%03d" % newvalue</pre>
<p>Note: if you use Plomino &lt;1.11, line 3, you need to call getObject() to get the actual document:</p>
<pre>chronodoc=searchchrono[0].getObject()</pre>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-09-14T08:32:25Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/how-to/multilingual-applications">
    <title>Multilingual applications</title>
    <link>http://www.plomino.net/how-to/multilingual-applications</link>
    <description>How to build a Plomino application in a multilingual web site.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>You have a multilingual web site where you want to add a Plomino application.</p>
<p>If the data stored in the database must be translate, the immediate and obvious solution is to produce several distinct databases (one per language).</p>
<p>But if the data has not to be translated (figures, names, phone numbers, etc.), it is not an ideal solution because it  requires much more work to maintain an update the data.</p>
<p>In that case, the best way is to build a unique database and make sure the produced screens are translated.</p>
<p>There are several approaches.</p>
<h3>Distinct forms</h3>
<p>You can create distinct forms (one per language) where the layout will contain the appropriate labels and text according the language.</p>
<p>To open documents with the proper form, you use the Form formula in your views:</p>
<pre>lang = context.restrictedTraverse("@@plone_portal_state/language")()<br />return "frmhotel"+lang</pre>
<p>or you use ?openwithform parameter in Redirect actions formulas (or anywhere else you produce URLs):</p>
<pre>lang = context.restrictedTraverse("@@plone_portal_state/language")()<br />return context.doc_url()+"/EditDocument?openwithform=frmhotel"+lang</pre>
<h3>Unique form</h3>
<p>You can also create one unique form, and in its layout replace all labels and text with computed for display fields which will produce the appropriate labels:</p>
<pre>label = {'en': u"Title", 'es': u"Titulo", 'fr': u"Titre", 'nl': u"Titel"}<br />lang = context.restrictedTraverse("@@plone_portal_state/language")()<br />return label.get(lang, label['en'])</pre>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-09-14T08:19:54Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/first-steps/tutorial-screencast">
    <title>Tutorial (screencast)</title>
    <link>http://www.plomino.net/first-steps/tutorial-screencast</link>
    <description>Create a basic Plomino application.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Part 1</p>
<p>
<object data="http://www.youtube.com/v/7rwyLv_c56g?fs=1&amp;hl=fr_FR" height="390" type="application/x-shockwave-flash" width="640">
<param name="allowFullScreen" value="true">
<param name="allowscriptaccess" value="always">
<param name="src" value="http://www.youtube.com/v/7rwyLv_c56g?fs=1&amp;hl=fr_FR">
<param name="allowfullscreen" value="true">
</object>
</p>
<p>Part 2</p>
<p>
<object data="http://www.youtube.com/v/k_n-oNmCUFM?fs=1&amp;hl=fr_FR" height="510" type="application/x-shockwave-flash" width="640">
<param name="allowFullScreen" value="true">
<param name="allowscriptaccess" value="always">
<param name="src" value="http://www.youtube.com/v/k_n-oNmCUFM?fs=1&amp;hl=fr_FR">
<param name="allowfullscreen" value="true">
</object>
</p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-03-14T16:12:14Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/first-steps/beginners-guide-screencast">
    <title>Beginner's guide (screencast)</title>
    <link>http://www.plomino.net/first-steps/beginners-guide-screencast</link>
    <description>A beginner's guide to creating web applications on Plone 4 with Plomino</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h3>Part 1</h3>
<p>
<object data="http://www.youtube.com/v/GLC-4XFi5XI?fs=1&amp;hl=fr_FR" height="340" type="application/x-shockwave-flash" width="560">
<param name="allowFullScreen" value="true">
<param name="allowscriptaccess" value="always">
<param name="src" value="http://www.youtube.com/v/GLC-4XFi5XI?fs=1&amp;hl=fr_FR">
<param name="allowfullscreen" value="true">
</object>
</p>
<h3>Part 2</h3>
<p>
<object data="http://www.youtube.com/v/JMTfsLfB07M?fs=1&amp;hl=fr_FR" height="340" type="application/x-shockwave-flash" width="560">
<param name="allowFullScreen" value="true">
<param name="allowscriptaccess" value="always">
<param name="src" value="http://www.youtube.com/v/JMTfsLfB07M?fs=1&amp;hl=fr_FR">
<param name="allowfullscreen" value="true">
</object>
</p>
<p>Thanks to Lloyd Person IV for contributing this screencast.</p>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-01-25T14:00:27Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/how-to/advanced/provide-a-custom-plomino-field-type-as-a-plugin">
    <title>Provide a custom Plomino field type as a plugin</title>
    <link>http://www.plomino.net/how-to/advanced/provide-a-custom-plomino-field-type-as-a-plugin</link>
    <description>You implement your own Plomino field types into a Python package and provide them to Plomino as Zope3 utility components.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p class=" ">Plomino provides a set of field types (text, number, richtext, datagrid, etc.).</p>
<p class=" ">But a custom Plomino field type can be declared to Plomino from a custom  package in order to extend the Plomino behavior.</p>
<p class=" ">Example:</p>
<pre class=" "> from zope.formlib import form<br /> from zope.interface import implements<br /> from zope import component<br /> from zope.pagetemplate.pagetemplatefile import PageTemplateFile<br /><br /> from zope.schema import getFields<br /> from zope.schema import Text, TextLine<br /><br /> from Products.Five.formlib.formbase import EditForm<br /><br /> from Products.CMFPlomino.interfaces import IPlominoField<br /> from Products.CMFPlomino.fields.dictionaryproperty import DictionaryProperty<br /><br /> from Products.CMFPlomino.fields.base import IBaseField, BaseField</pre>
<p class=" ">A Zope schema defines the field setting parameters.</p>
<pre class=" "><br /> class IRomanNumberField(IBaseField):<br />     """<br />     Roman number field schema<br />     """<br />     color = TextLine(title=u'Color',<br />                 description=u'Font color to apply to roman number display.',<br />                 required=False)<br />           </pre>
<p class=" ">A class derivated from BaseField will implement this interface.</p>
<p class=" ">It must mandatorily contain:</p>
<ul>
<li>plomino_field_parameters: it declares the field main parameters,</li>
<li>read_template: the PageTemplate in charge of rendering the field in read mode,</li>
<li>edit_template: the PageTemplate in charge of rendering the field in edit mode.</li>
</ul>
<p class=" ">It can also overwrite the different methods of BaseField, like processInput (in charge of converting the submitted value into the actual item value, or  validate (in charge of validating the submitted value before saving).</p>
<pre class=" "> class RomanNumberField(BaseField):<br />     """ This field stores integers as roman numerals<br />     """<br />     implements(IRomanNumberField)<br />     <br />     plomino_field_parameters = {'interface': IRomanNumberField,<br />                                 'label': "RomanNumber",<br />                                 'index_type': "FieldIndex"}<br />     <br />     read_template = PageTemplateFile('roman_read.pt')<br />     edit_template = PageTemplateFile('roman_edit.pt')<br />     <br />    def validate(self, strValue):<br />         """<br />         """<br />         errors=[]<br />         fieldname = self.context.id<br />         try:<br />             v = int(submittedValue)<br />         except:<br />             errors.append(fieldname + " must be an integer.")<br />         return errors<br />     <br />     def processInput(self, strValue):<br />         """ convert int to roman (example based on vegaseat code snippet)<br />         """<br />         number = int(strValue)<br />         numerals = { 1 : "I", 4 : "IV", 5 : "V", 9 : "IX", 10 : "X",<br />                      40 : "XL", 50 : "L", 90 : "XC", 100 : "C", 400 : "CD",<br />                      500 : "D", 900 : "CM", 1000 : "M" }<br />         result = ""<br />         for value, numeral in sorted(numerals.items(), reverse=True):<br />             while number &gt;= value:<br />                 result += numeral<br />                 number -= value<br />         return result</pre>
<p class=" ">The plugin field must be provided as an utility so Plomino can find it (the utility name must be in upper case):</p>
<pre class=" "> component.provideUtility(RomanNumberField, IPlominoField, 'ROMANNUMBER')</pre>
<p class=" ">And the SettingForm must built based on the field's schema: (no customization needed here)</p>
<pre class=" "> for f in getFields(IRomanNumberField).values():<br />     setattr(RomanNumberField, f.getName(),<br />             DictionaryProperty(f, 'parameters'))<br /><br /> class SettingForm(EditForm):<br />    """<br />    """<br />    form_fields = form.Fields(IRomanNumberField)</pre>
<p class=" "> </p>
<p class=" ">Then in configure.zcml, declare the field as adapter for PlominoField: (assuming that previous code is in romannumber.py)</p>
<pre class=" ">&lt;adapter<br />         for="Products.CMFPlomino.interfaces.IPlominoField"<br />         provides=".romannumber.IRomanNumberField"<br />         factory=".romannumber.RomanNumberField"         /&gt; </pre>
<p class=" ">and declare the settings form as a browser page (its name must be xxx+'settings' where xxx is the utility name in lowercase)</p>
<pre class=" ">&lt;browser:page<br />         name="romannumbersettings"<br />         for="Products.CMFPlomino.interfaces.IPlominoField"<br />         class=".romannumber.SettingForm"<br />         permission="plomino.DESIGN_PERMISSION"         /&gt;</pre>
<p class=" ">The 2 page templates can be based on the following examples:</p>
<p class=" ">roman_read.pt:</p>
<pre class=" ">&lt;tal:block tal:define="v options/fieldvalue"<br /> tal:content="python:str(v)"&gt;XXII&lt;/tal:block&gt;</pre>
<p class=" ">roman_edit.pt:</p>
<pre class=" ">&lt;span&gt;<br />    &lt;input type="text"<br />       tal:attributes="name options/fieldname;<br /> value options/fieldvalue" /&gt;<br />&lt;/span&gt;</pre>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2011-01-21T23:26:20Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/samples/dynamic-hiding">
    <title>Dynamic hiding</title>
    <link>http://www.plomino.net/samples/dynamic-hiding</link>
    <description>Hide-when formulas allow to hide or show some part of a form. Dynamic hide-when are applied on client side dynamically.</description>
    
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2012-01-16T20:28:33Z</dc:date>
    <dc:type>PlominoDatabase</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/how-to/restrict-access-to-documents">
    <title>Restrict access to documents</title>
    <link>http://www.plomino.net/how-to/restrict-access-to-documents</link>
    <description>How to allow or not to open a document depending on the current user.</description>
    <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Let's assume your form contains a Name field and you want to restrict access to documents according this field value.</p>
<p>This field would be named "employee" for instance</p>
<p>Note: if you want it to store the id of the user who creates the document just make it Computed on creation, with the following formula:</p>
<pre>plominoDocument.getCurrentUser().getMemberId()</pre>
<p>To restrict access to the document, we will use the onOpenDocument event: if this event formula returns anything false (False, None, 0, ""), the document opening is allowed, but if it returns a non-empty string, the opening is not allowed and the returned string is display to the user as error message.</p>
<p>So edit your form, and go to Events tab, and enter a formula like this in the On open document event:</p>
<pre>if plominoDocument.getCurrentUser().getMemberId()==plominoDocument.employee:<br />  return None<br />else:<br />  return "You are not allowed to view this document." </pre>
<p>If you also want to allow users having a given role (let's say [controller]), you would use a formula like this:</p>
<pre>if plominoDocument.getCurrentUser().getMemberId()==plominoDocument.employee:<br />  return None<br />roles=plominoDocument.getCurrentUserRoles()<br />if "[controller]" in roles:<br />  return None<br />return "You are not allowed to view this document." </pre>]]></content:encoded>
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2010-06-16T09:40:59Z</dc:date>
    <dc:type>Page</dc:type>
  </item>


  <item rdf:about="http://www.plomino.net/samples/charts-example">
    <title>Charts example</title>
    <link>http://www.plomino.net/samples/charts-example</link>
    <description></description>
    
    <dc:publisher>No publisher</dc:publisher>
    <dc:creator>Eric BREHAULT</dc:creator>
    <dc:rights></dc:rights>
    <dc:date>2012-01-16T20:27:57Z</dc:date>
    <dc:type>PlominoDatabase</dc:type>
  </item>





</rdf:RDF>

