]> SALOME platform Git repositories - modules/yacs.git/blob - src/AppQuickStart/app-quickstart.py
Salome HOME
Copyrights update 2015.
[modules/yacs.git] / src / AppQuickStart / app-quickstart.py
1 #! /usr/bin/env python
2 #  -*- coding: iso-8859-1 -*-
3 # Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
4 #
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License, or (at your option) any later version.
9 #
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #
21
22 import os
23 import shutil
24 import optparse
25
26 # Options of this script
27 def profileQuickStartParser() :
28
29     parser = optparse.OptionParser( usage = "usage: python app-quickstart.py [options]" )
30
31     parser.add_option('-p',
32                       "--prefix",
33                       metavar="</Path/to/the/sources/of/application>",
34                       type="string",
35                       action="store",
36                       dest="prefix",
37                       default='.',
38                       help="Where the application's sources will be generated. [Default : '.']")
39
40     parser.add_option('-m',
41                       "--modules",
42                       metavar="<module1,module2,...>",
43                       type="string",
44                       action="store",
45                       dest="modules",
46                       default='KERNEL,GUI',
47                       help="List of the application's modules. [Default : KERNEL,GUI]")
48
49     parser.add_option('-n',
50                       "--name",
51                       type="string",
52                       action="store",
53                       dest="name",
54                       help="Name of the application")
55
56     parser.add_option('-v',
57                       "--version",
58                       type="string",
59                       action="store",
60                       dest="version",
61                       default='1.0',
62                       help="Version of the application. [Default : 1.0]")
63
64     parser.add_option('-s',
65                       "--slogan",
66                       type="string",
67                       action="store",
68                       dest="slogan",
69                       default='',
70                       help="Slogan of the application.")
71
72     parser.add_option('-f',
73                       "--force",
74                       action="store_true",
75                       dest="force",
76                       help="Overwrites existing sources")
77
78     return parser
79
80
81
82 #Create the splash screen
83 def profileGenerateSplash( resources_dir, appname, version, subtext ):
84     import Image
85     import ImageDraw
86     import ImageFont
87
88     uname = unicode(appname, 'UTF-8')
89     uversion = unicode(version, 'UTF-8')
90
91     # fonts
92     fontbig = ImageFont.truetype( os.path.join( resources_dir, 'Anita semi square.ttf' ), 64)
93     fontsmall = ImageFont.truetype( os.path.join( resources_dir, 'Anita semi square.ttf' ), 20)
94     textColor = "rgb(255, 250, 250)"
95     shadowColor = "rgb(0, 0, 0)"
96
97     # dimensions
98     nbcar = len(uname)
99     width = 600
100     if nbcar > 12:
101         width = min( width*nbcar/12, 1024) #a little more
102     height = 300
103     borderX = 30 #50
104     borderY = 3 #30
105     shadowX = 2
106     shadowY = shadowX
107
108     # load background image 
109     f0 = os.path.join( resources_dir, "background.png" )
110     im = Image.open(f0)
111     im = im.resize( ( width, height ) )
112     draw = ImageDraw.Draw(im)
113
114     # add the name of the application
115     iw, ih = draw.textsize(uname, font=fontbig)
116     x = (width - iw) / 2.0 # horizontal center
117     y = (height - ih) / 2.0 # vertical center
118     draw.text((x+shadowX, y+shadowY), uname, font=fontbig, fill=shadowColor)
119     draw.text((x, y), uname, font=fontbig, fill=textColor)
120
121     # add subtext
122     if len(subtext) > 0:
123         iw, ih = draw.textsize(subtext, font=fontsmall)
124         draw.text((borderX+shadowX, height+shadowY-borderY-ih),
125                   subtext, font=fontsmall, fill=shadowColor)
126         draw.text((borderX, height-borderY-ih),
127                   subtext, font=fontsmall, fill=textColor)
128
129     # add the version if any
130     if len(version) > 0:
131         iw, ih = draw.textsize(uversion, font=fontsmall)
132         draw.text((width+shadowX-borderX-iw, height+shadowY-borderY-ih),
133                   uversion, font=fontsmall, fill=shadowColor)
134         draw.text((width-borderX-iw, height-borderY-ih),
135                   uversion, font=fontsmall, fill=textColor)
136
137     del draw
138     return im
139
140
141 #Create the application logo
142 def profileGenerateLogo( appname, font ):
143     import Image
144     import ImageDraw
145
146     uname = unicode(appname, 'UTF-8')
147
148     # evaluate size before deleting draw
149     im = Image.new( "RGBA", (1, 1), (0, 0, 0, 0) )
150     draw = ImageDraw.Draw( im )
151
152     im = Image.new( "RGBA", draw.textsize( uname, font=font ), (0, 0, 0, 0) )
153     draw = ImageDraw.Draw(im)
154     draw.text( (0+1, 0), uname, font=font, fill="rgb(0, 0, 0)" )
155     draw.text( (0, -1), uname, font=font, fill="rgb(191, 191, 191)" )
156
157     del draw
158     return im
159
160    
161 #Replace strings in the template
162 def profileReplaceStrings( src, dst, options ) :
163     with open( dst, "wt" ) as fout:
164         with open( src, "rt" ) as fin:
165             for line in fin:
166                 l = line.replace( '[LIST_OF_MODULES]', options.modules )
167                 l = l.replace( '[VERSION]', options.version )
168                 l = l.replace( '[SLOGAN]', options.slogan )
169                 l = l.replace( '[NAME_OF_APPLICATION]', options.name.upper() )
170                 l = l.replace( '<Name_of_Application>', options.name )
171                 l = l.replace( '(name_of_application)', options.name.lower() )
172                 fout.write( l )
173
174
175 #Generation of a template profile sources
176 def profileGenerateSources( options, args ) :
177
178     #Set name of several directories
179     app_dir = options.prefix
180     app_resources_dir = os.path.join( app_dir, "resources" )
181     kernel_root_dir = os.environ["KERNEL_ROOT_DIR"]
182     bin_salome_dir = os.path.join( kernel_root_dir, "bin", "salome" )
183     kernel_resources_dir = os.path.join( kernel_root_dir, "share", "salome", "resources", "kernel" )
184     template_dir = os.path.join( kernel_resources_dir, "app-template" )
185
186     #Check if the directory of the sources already exists and delete it
187     if os.path.exists( app_dir ) :
188         if not options.force :
189             print "Directory %s already exists." %app_dir
190             print "Use option --force to overwrite it."
191             return
192         else :
193             shutil.rmtree( app_dir )
194
195     #Copy template directory
196     os.mkdir( app_dir )
197     for root, dirs, files in os.walk( template_dir ) :
198         dst_dir = root.replace( template_dir, app_dir ) 
199         for d in dirs :
200             os.mkdir( os.path.join( dst_dir, d ) )
201         for f in files :
202             profileReplaceStrings( os.path.join( root, f ), os.path.join( dst_dir, f ), options )
203
204     #Complete source directory
205     contextFiles = [ "salomeContext.py", "salomeContextUtils.py", "parseConfigFile.py" ]
206     for f in contextFiles :
207         shutil.copy( os.path.join( bin_salome_dir, f ), os.path.join( app_dir, "src" ) )
208
209     #Search for python modules Image, ImageDraw and ImageFont
210     try:
211         import imp
212         imp.find_module('Image')
213         imp.find_module('ImageDraw')
214         imp.find_module('ImageFont')
215         found = True
216     except ImportError:
217         found = False
218
219     #Generate logo and splash
220     logo_destination = os.path.join( app_resources_dir, 'app_logo.png')
221     splash_destination = os.path.join( app_resources_dir, 'splash.png')
222     about_destination = os.path.join( app_resources_dir, 'about.png')
223     if found :
224         import ImageFont
225         font = ImageFont.truetype( os.path.join( kernel_resources_dir, "Anita semi square.ttf" ) , 18 )
226
227         #Generate and save logo
228         app_logo = profileGenerateLogo( options.name, font )
229         app_logo.save( logo_destination, "PNG" )
230
231         #Generate and splash screen and about image
232         if options.slogan :
233             subtext = options.slogan
234         else :
235             subtext = "Powered by SALOME"
236         im = profileGenerateSplash( kernel_resources_dir, options.name, options.version, subtext )
237         im.save( splash_destination, "PNG" )
238         im.save( about_destination, "PNG" )
239     else :
240         gui_resources_dir = os.path.join( os.environ["GUI_ROOT_DIR"], "share", "salome", "resources", "gui" )
241         logo_name = os.path.join( gui_resources_dir, "icon_applogo.png" )
242         if os.path.exists( logo_name ) :
243             shutil.copy( logo_name, logo_destination )
244         about_name = os.path.join( gui_resources_dir, "icon_about.png" )
245         if os.path.exists( about_name ) :
246             shutil.copy( about_name, about_destination )
247             shutil.copy( about_name, splash_destination )
248
249     #End of script
250     print "Sources of %s were generated in %s." %( options.name, app_dir )
251
252
253 # -----------------------------------------------------------------------------
254
255 if __name__ == '__main__':
256     #Get options and args
257     (options, args) = profileQuickStartParser().parse_args()
258
259     #Check name of the application
260     if not options.name :
261         raise RuntimeError( "A name must be given to the application. Please use option --name." )
262
263     #Check if the prefix's parent is a directory
264     if not os.path.isdir( os.path.dirname( options.prefix ) ) :
265         raise RuntimeError( "%s is not a directory." % os.path.dirname( options.prefix ) )
266
267     #Generate sources of the profile
268     profileGenerateSources( options, args )