Ferramentas Pessoais
Você está aqui: Página Inicial Downloads Skin Generator 1.0

Skin Generator 1.0

Skin Generator é um pequeno aplicativo de código aberto que cria uma skin para Plone 3 de forma rápida e automatizada.

SkinGenerator.py — Python Source, 56Kb

Conteúdo do arquivo

# -*- coding: utf-8 -*-

# GNU General Public License (GPL)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
#

import os, base64

# Criação: 08/11/2008
# Última Atualização: 09/11/2008

project_version = '1.0'

project_creditos = \
"""  Autor: Herson Rodrigues
  E-mail: hersonrodrigues@gmail.com
  Versão: %s\n"""%project_version

project_license = '  GNU General Public License (GPL)\n'

class createSkin:
    """Classe de criação"""

    def __init__(self):
        self.container = []

    def setContainer(self, nome):
        """Cria uma pasta container"""
        os.system('mkdir ' + nome)
        self.container = nome
        print 'Criado a pasta %s' %nome
        
    def getContainer(self, nome):
        """Retorna a pasta container"""
        if self.container:
            return self.container
        self.setContainer(nome)
        return nome
       
    def cria_pasta(self, nome, diretorio):
        """Cria uma pasta"""
        os.system('mkdir ' + diretorio + '/' + nome)
        print 'Criado a pasta %s' %nome
        return diretorio + '/' + nome
        
    def cria_arquivo(self, nome, diretorio, texto):
        """Cria um arquivo"""
        f = open(diretorio +'/'+ nome, 'w')
        f.write(texto)
        f.close()
        print 'Criado o arquivo %s' %nome 


###############################################################################
               
skin = createSkin()

print '\n\n\n\n  #### SKIN GENERATOR #### \n'
print project_creditos
print project_license
              
project_name = raw_input(">>> Digite o nome da sua skin: ")
    
if not project_name:
    print 'Não foi digitado um nome válido, o programa está sendo finalizado'
else:

    project_site = raw_input(">>> Digite o nome do Site: ")

    if not project_site:
        project_site = 'Defina um nome para o site no arquivo properties.xml'

    
    # Portlets
    project_portlets = raw_input(">>> Quantos portlets gostaria de criar?: ")
    
    if not project_portlets:
        project_portlets = 0
        project_portlets_items = 0    
    else:
        project_portlets = int(project_portlets)
        project_portlets_items = []
        for i in range(project_portlets):
            contador = str(i+1)
            portlet = \
            raw_input(">>> Qual o nome do portlet número "+contador+"?: ")
            
            if not portlet:
                portlet = 'Indefinido'+str(i)
                
            position = \
            raw_input(">>> Qual a posição do portlet "+portlet+" [D/E]?: ")
            
            if position.upper() == 'E':
                position = 'left'
            else:
                position = 'right'        
                        
            project_portlets_items.append({'portlet'  : portlet, 
                                           'position' : position})    
           
    # Cria a raiz da skin 
    skin.getContainer(project_name)
    container = skin.getContainer(project_name)
    containerlower = container.lower()
    icontainer = container[0].upper()+container[1:]
    # Arquivo configure.zcml
    texto = \
    """<configure xmlns="http://namespaces.zope.org/zope">
    <include package=".browser" />
    <include file="profiles.zcml" />
</configure>
            """
    skin.cria_arquivo('configure.zcml', container, texto)
    
    # Arquivo profiles.zcml
    texto = \
    """<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
    i18n_domain="%s">

  <genericsetup:registerProfile
      name="default"
      title="%s"
      directory="profiles/default"
      description="Extension profile for %s."
      provides="Products.GenericSetup.interfaces.EXTENSION"
      />

</configure>"""%(containerlower, container, container)

    skin.cria_arquivo('profiles.zcml', container, texto)
    
    
    
    # Arquivo __init__.py
    texto = \
    """from Products.CMFCore.DirectoryView import registerDirectory

GLOBALS = globals()
registerDirectory('skins', GLOBALS)"""

    skin.cria_arquivo('__init__.py', container, texto)    


    # Arquivo AUTOR
    texto = \
    """Autor: Herson Rodrigues Santos
Página: http://herson.objectis.net
E-mail: hersonrodrigues@gmail.com
    """

    skin.cria_arquivo('AUTOR', container, texto)


    # Arquivo LICENSE

    texto = \
    """		    GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For %s, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

			    NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

		     END OF TERMS AND CONDITIONS"""   
		      
    skin.cria_arquivo('LICENSE', container, texto)
    
    # Pasta Skins
    
    pasta_skins = skin.cria_pasta('skins', container)

    # Pasta Styles    
    pasta_skins_styles = skin.cria_pasta(containerlower+'_styles', 
                                         pasta_skins)

    # Pasta Imagens     
    pasta_skins_imagens = skin.cria_pasta(containerlower+'_imagens', 
                                          pasta_skins)

    # Pasta Templates     
    pasta_skins_templates = skin.cria_pasta(containerlower+'_templates', 
                                            pasta_skins)
                                            

    texto = \
    "title:string="+container+"'s color, font, logo and border \
    defaults\n plone_skin:string="+container + """
logoName:string=logo.jpg

fontFamily:string="Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif
fontBaseSize:string=69%
fontColor:string=Black
fontSmallSize:string=85%

backgroundColor:string=White

linkColor:string=#436976
linkActiveColor:string=Red
linkVisitedColor:string=Purple

borderWidth:string=1px
borderStyle:string=solid
borderStyleAnnotations:string=dashed

globalBorderColor:string=#8cacbb
globalBackgroundColor:string=#dee7ec
globalFontColor:string=#436976

headingFontFamily:string="Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif

contentViewBorderColor:string=#74ae0b
contentViewBackgroundColor:string=#cde2a7
contentViewFontColor:string=#578308

inputFontColor:string=Black

textTransform:string=lowercase

evenRowBackgroundColor:string=#eef3f5 
oddRowBackgroundColor:string=transparent

notifyBorderColor:string=#ffa500
notifyBackgroundColor:string=#ffce7b

discreetColor:string=#76797c
helpBackgroundColor:string=#ffffe1

portalMinWidth:string=70em
columnOneWidth:string=16em
columnTwoWidth:string=16em"""

    # Arquivo base_properties.props                                      
    skin.cria_arquivo('base_properties.props', 
                       pasta_skins_styles, 
                       texto)                                            



    # Arquivo SeuArquivo.css.dtml
    
    texto = "/* INICIO DO CSS */\n\n\n\n/* FINAL DO CSS */" 
       
    skin.cria_arquivo(container+'.css.dtml', 
                       pasta_skins_styles, 
                       texto)                                              


    # Arquivo SeuArquivo.js
    
    texto = """// INICIO DO JAVASCRIPT \n\n \
    // Jquery\njq(document).ready(function(){\n\n\n\n});
    // Jquery Fim\n\n// FINAL DO JAVASCRIPT """
       
    skin.cria_arquivo(container+'.js', 
                       pasta_skins_styles, 
                       texto)                                               
                                            
    # Arquivo pagina_inicial.pt
    texto = \
    """<html xmlns="http://www.w3.org/1999/xhtml"
      xml:lang="en"
      lang="en"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal"
      xmlns:i18n="http://xml.zope.org/namespaces/i18n"
      metal:use-macro="here/main_template/macros/master"
      i18n:domain="plone">
      
  <head>
    <title tal:content="template/title">The title</title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">

  </head>
  <body metal:fill-slot="main">

	<h1 tal:content="context/Title">Titulo</h1>
    
    <div>
        Coloque aqui suas div's e estruturas htmls
    </div>

</body>
</html>"""

    skin.cria_arquivo('pagina_inicial.pt', 
                       pasta_skins_templates, 
                       texto)                                              
                                                

    # Arquivo logo.jpg
    # Serializado com: base64.encodestring(open(logo.jpg,"rb").read())
    
    texto = \
"""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
cBxxxwHHHHA//9k=
"""
    # Deserializando
    texto = base64.b64decode(texto)      
    skin.cria_arquivo('logo.jpg', 
                       pasta_skins_imagens, 
                       texto)           


    # Pasta Profiles
    
    pasta_profiles = skin.cria_pasta('profiles', container)                       


    # Pasta Default
    
    pasta_profiles_default = skin.cria_pasta('default', pasta_profiles)                     
    
    
    # Arquivo cssregistry.xml
    texto = \
    """<?xml version="1.0"?>
<object name="portal_css">

 <stylesheet id="%s.css"
    title="" cacheable="True" compression="safe" cookable="True"
    enabled="1" expression=""  media="all"
    rel="stylesheet" rendering="import"/>
    
</object>
    """%container
    
    skin.cria_arquivo('cssregistry.xml', 
                       pasta_profiles_default, 
                       texto)       
    

    # Arquivo jsregistry.xml
    texto = \
    """<?xml version="1.0"?>
<object name="portal_javascripts">

 <javascript id="%s.js"
    cacheable="False" compression="safe" cookable="False"
    enabled="True" expression="" inline="False"/>

</object>"""%container

    skin.cria_arquivo('jsregistry.xml', 
                       pasta_profiles_default, 
                       texto)  


    # Arquivo properties.xml
    texto = \
    """<?xml version="1.0"?>
<site>
 <property name="title">%s</property>
 <property name="description"></property>
 <property name="default_page" type="string">pagina_inicial</property>
 <property name="selectable_views" type="lines">
  <element value="folder_listing"/>
  <element value="news_listing"/>
 </property>
 <property name="email_from_address" type="string"></property>
 <property name="email_from_name" type="string">Administração - %s</property>
 <property name="validate_email" type="boolean">False</property>
 <property name="email_charset" type="string">utf-8</property>
 <property name="enable_permalink" type="boolean">False</property>
</site>"""%(project_site, project_site)

    skin.cria_arquivo('properties.xml', 
                       pasta_profiles_default, 
                       texto)  




    texto_skin = \
    """<?xml version="1.0"?>
<object name="portal_skins" allow_any="False" cookie_persistence="False"
        default_skin="%s" request_varname="plone_skin"> 
 <object name="%s"
    meta_type="Filesystem Directory View"
    directory="Products.%s:%s/%s"/>
 <object name="%s"
    meta_type="Filesystem Directory View"
    directory="Products.%s:%s/%s"/>
 <object name="%s"
    meta_type="Filesystem Directory View"
    directory="Products.%s:%s/%s"/>
 <skin-path name="%s" based-on="Plone Default">
 
  <layer name="%s"
     insert-after="custom"/>
  <layer name="%s"
     insert-after="%s"/>
  <layer name="%s"
     insert-after="%s"/>
     
 </skin-path>
</object>
    """%(container,
         pasta_skins_imagens.split('/')[-1], 
         container, 
         pasta_skins_imagens.split('/')[-2],
         pasta_skins_imagens.split('/')[-1],
         pasta_skins_styles.split('/')[-1], 
         container, 
         pasta_skins_styles.split('/')[-2],
         pasta_skins_styles.split('/')[-1],
         pasta_skins_templates.split('/')[-1], 
         container, 
         pasta_skins_templates.split('/')[-2],
         pasta_skins_templates.split('/')[-1],
         container,
         pasta_skins_styles.split('/')[-1],
         pasta_skins_imagens.split('/')[-1],
         pasta_skins_styles.split('/')[-1],
         pasta_skins_templates.split('/')[-1],
         pasta_skins_imagens.split('/')[-1])
    
    skin.cria_arquivo('skins.xml', 
                       pasta_profiles_default, 
                       texto_skin)


    # Arquivo properties.xml
    texto = \
    """<metadata>
  <description>%s - %s</description>
  <version>1.0</version>
<!--
  <dependencies>
    <dependency>profile-Products.NomeDoProduto:default</dependency>  
  </dependencies>    
-->
</metadata>"""%(container, project_site)

    skin.cria_arquivo('metadata.xml', 
                       pasta_profiles_default, 
                       texto)  

    # Arquivo catalog.xml

    texto = \
    """<?xml version="1.0"?>
<object name="portal_catalog" meta_type="Plone Catalog Tool">
  
  <!-- Exemplo de criação de indice, veja como pegar os icones dos tipos do plone
  <index name="icon" 
         meta_type="FieldIndex">
    <indexed_attr value="icon"/>
  </index>

  <column value="icon"/>
  -->
  
  <!-- Exemplo de criação de indice, este pega o texto das páginas e notícias
  <index name="getText" 
         meta_type="FieldIndex">
    <indexed_attr value="getText"/>
  </index>

  <column value="getText"/>
  -->  

</object>
    """
    skin.cria_arquivo('catalog.xml', 
                       pasta_profiles_default, 
                       texto)
                           

    if project_portlets_items:
        # Arquivo portlets.xml
        texto_main = ''
        texto_main_colum = ''
        texto_header = \
        """<?xml version="1.0"?>
<portlets>

 """
        for item in project_portlets_items:

            portletlower = item['portlet'].lower()+'_portlet'
            portletname = item['portlet']
            portletpos = item['position']
            
            texto_main = texto_main + """ <portlet
     addview="%s"
     title="%s"
     description=""
     />    
"""%(portletlower, portletname)

            texto_main_colum = texto_main_colum + """      
 <assignment name="%s" category="context" key="/"
    manager="plone.%scolumn" type="%s"/>
    
"""%(portletname, portletpos, portletlower) 
    
        texto_footer = \
        """         
</portlets> """
        texto = texto_header + texto_main + texto_main_colum + texto_footer

        skin.cria_arquivo('portlets.xml', 
                           pasta_profiles_default, 
                           texto)    
    
    
    
                                   
    # Pasta Browser
    
    pasta_browser = skin.cria_pasta('browser', container)  
        
    # Arquivo __init__.py   
    texto = '#'
    skin.cria_arquivo('__init__.py', 
                       pasta_browser, 
                       texto)
                       
    # Arquivo interfaces.py   
    texto = \
    """from plone.theme.interfaces import IDefaultPloneLayer

class I%s(IDefaultPloneLayer):
    \"\"\"Marcador que define uma interface Zope 3\"\"\"
    """%(icontainer)
    
    skin.cria_arquivo('interfaces.py', 
                       pasta_browser, 
                       texto)                             

    # Arquivo configure.zcml
    if project_portlets_items:
    
        texto_main = ''
        
        texto_header = \
        """<configure
        xmlns="http://namespaces.zope.org/zope"
        xmlns:browser="http://namespaces.zope.org/browser"
        xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
        xmlns:plone="http://namespaces.plone.org/plone" 
        i18n_domain="%s">

        <interface
            interface=".interfaces.I%s"
            type="zope.publisher.interfaces.browser.IBrowserSkinType"
            name="%s"
            />
            
        """%(containerlower, icontainer, container)
     
        for item in project_portlets_items:

            portletlower = item['portlet'].lower()+'_portlet'
            portletname = item['portlet']
            portletpos = item['position']
            
            texto_main = texto_main + """<!-- Portlet - %s -->
    <plone:portlet
        name="%s"
        interface=".portlets.I%sPortlet"
        assignment=".portlets.%sAssignment"
        view_permission="zope2.View"
        edit_permission="cmf.ManagePortal"
        renderer=".portlets.%sRenderer"
        addview=".portlets.%sAddForm"
        editview=".portlets.%sEditForm"
        />
        
        """%(portletname, portletlower, portletname, 
               portletname, portletname, portletname, portletname)

    
        texto_footer = \
        """         
</configure> """
        texto = texto_header + texto_main + texto_footer
                    
    else:
                                     
        texto = \
        """<configure
        xmlns="http://namespaces.zope.org/zope"
        xmlns:browser="http://namespaces.zope.org/browser"
        i18n_domain="%s">

        <interface
            interface=".interfaces.I%s"
            type="zope.publisher.interfaces.browser.IBrowserSkinType"
            name="%s"
            />

    </configure>
        """%(containerlower, icontainer, container)
        
    
    skin.cria_arquivo('configure.zcml', 
                       pasta_browser, 
                       texto)



    if project_portlets_items:
           
        # Pasta Templates
        pasta_templates = skin.cria_pasta('templates', pasta_browser) 
        
        # Pasta Portlets
        pasta_portlets = skin.cria_pasta('portlets', pasta_templates)
        
        # Portlet Templates
        for item in project_portlets_items:     
            portletname = item['portlet']
            texto = \
"""<html xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal"
      i18n:domain="plone">
<body>
<div metal:define-macro="portlet">

<dl class="portlet %s">

    <dt class="portletHeader">
        <span class="portletTopLeft"/>
            <span>
               %s
            </span>
        <span class="portletTopRight"/>
    </dt>

    <dd class="portletItem odd">
        
    <p>
       Escreva aqui o conteúdo do portlet
    </p>

    </dd>
    
    <dd class="portletFooter">
        <span class="portletBottomLeft"/>
        <span>
           <a href="#">Veja Mais</a>
        </span>
        <span class="portletBottomRight"/>
    </dd>

</dl>

</div>
</body>
</html>
"""%(portletname, portletname)

            skin.cria_arquivo(portletname+'.pt', 
                               pasta_portlets, 
                               texto) 
                               
                                          
        if project_portlets_items:
          
            # Arquivo porlets.py
            texto_main = ''
            
            texto_header = \
            """from zope.interface import Interface
from zope.interface import implements
from zope import schema
from zope.formlib import form

from plone.portlets.interfaces import IPortletDataProvider
from plone.app.portlets.portlets import base

from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile

    """
            for item in project_portlets_items:

                portletlower = item['portlet'].lower()+'_portlet'
                portletname = item['portlet']
                portletpos = item['position']
                
                texto_main = texto_main + """# Portlet %s 
class I%sPortlet(IPortletDataProvider):
    \"\"\"A portlet
    
    It inherits from IPortletDataProvider because for this portlet, the
    data that is being rendered and the portlet assignment itself are the
    same.
    \"\"\"

class %sAssignment(base.Assignment):
    \"\"\"Portlet assignment.

    This is what is actually managed through the portlets UI and associated
    with columns.
    \"\"\"

    implements(I%sPortlet)

    def __init__(self):
        pass

    @property
    def title(self):
        \"\"\"This property is used to give the title of the portlet in the
        \"manage portlets\" screen.
        \"\"\"
        return "%s"

class %sRenderer(base.Renderer):
    \"\"\"Portlet renderer.

    This is registered in configure.zcml. The referenced page template is
    rendered, and the implicit variable 'view' will refer to an instance
    of this class. Other methods can be added and referenced in the template.
    \"\"\"

    render = ViewPageTemplateFile('%s/%s.pt')


class %sAddForm(base.AddForm):
    \"\"\"Portlet add form.

    This is registered in configure.zcml. The form_fields variable tells
    zope.formlib which fields to display. The create() method actually
    constructs the assignment that is being added.
    \"\"\"
    form_fields = form.Fields(I%sPortlet)

    def create(self, data):
        return %sAssignment(**data)


class %sEditForm(base.EditForm):
    \"\"\"Portlet edit form.

    This is registered with configure.zcml. The form_fields variable tells
    zope.formlib which fields to display.
    \"\"\"
    form_fields = form.Fields(I%sPortlet)
            
            """%(portletname, portletname, 
                 portletname, portletname, 
                 portletname, portletname, 
                 '/'.join(pasta_portlets.split('/')[2:]), 
                 portletname, portletname, 
                 portletname, portletname, 
                 portletname, portletname)
        
        texto = texto_header + texto_main
        
        skin.cria_arquivo('portlets.py', 
                           pasta_browser, 
                           texto)                     
                                           
Ações do documento
« Abril 2024 »
Abril
SeTeQuQuSeSaDo
1234567
891011121314
15161718192021
22232425262728
2930

Python Logo

       Zope Logo

 

      Novo Logo do Plone