Package pyplusplus :: Package gui :: Module ui

Source Code for Module pyplusplus.gui.ui

  1  #! /usr/bin/python 
  2  # Copyright 2004-2008 Roman Yakovenko. 
  3  # Distributed under the Boost Software License, Version 1.0. (See 
  4  # accompanying file LICENSE_1_0.txt or copy at 
  5  # http://www.boost.org/LICENSE_1_0.txt) 
  6   
  7  """this module implements GUI. 
  8   
  9  TODO: It could be nice, if GUI will save the user settings beetwen runs. 
 10  """ 
 11   
 12  import os 
 13  import sys 
 14  import time 
 15  import Tkinter 
 16  import tkFileDialog 
 17  import tkSimpleDialog 
 18   
 19  from pygccxml import parser 
 20  from pyplusplus import module_builder 
 21   
 22  import wizard 
23 24 25 -class gui_config_t:
26 27 @staticmethod
28 - def config_file():
29 config_path = os.getenv( 'HOME', os.path.abspath( os.getcwd() ) ) 30 return os.path.join( os.path.abspath( config_path ), ".pyplusplus" )
31 32 @staticmethod
33 - def read_header_name():
34 config_path = gui_config_t.config_file() 35 if os.path.exists(config_path): 36 return open(config_path).read() 37 else: 38 return '' 39 40 @staticmethod
41 - def save_header_name( header_file ):
42 config_path = gui_config_t.config_file() 43 open(config_path, "w").write(header_file)
44
45 #TODO: add configuration file and ability to start\run it. 46 47 -class custom_frame_t(Tkinter.Frame):
48 - def __init__(self, parent, sticky=Tkinter.NSEW ):
49 Tkinter.Frame.__init__( self, parent ) 50 self.grid( sticky=sticky) 51 52 self.rowconfigure( 1, weight=1 ) 53 self.columnconfigure( 0, weight=1 )
54
55 56 -class parser_configuration_ui_t(custom_frame_t):
57 - def __init__(self, parent ):
58 custom_frame_t.__init__( self, parent, sticky=Tkinter.NW ) 59 60 temp = Tkinter.Label( self, text="Parser configuration", justify=Tkinter.LEFT) 61 temp.grid( row=0, sticky=Tkinter.NW + Tkinter.E, columnspan=3) 62 temp.configure( relief=Tkinter.GROOVE, borderwidth=1 ) 63 64 temp = Tkinter.Label( self, text="GCC_XML location:") 65 temp.grid( row=1, sticky=Tkinter.NW) 66 67 self._gccxml_location = Tkinter.Entry( self, width=35 ) 68 self._gccxml_location.grid(row=2, column=0, columnspan=2) 69 70 temp = Tkinter.Button( self, text="...", command=self._select_gccxml_executable ) 71 temp.grid( row=2, column=2) 72 73 temp = Tkinter.Label( self, text="Include paths:", justify=Tkinter.LEFT) 74 temp.grid( row=3, sticky=Tkinter.NW) 75 76 self._include_paths = Tkinter.Listbox( self, height=9, width=35 ) 77 vscrollbar = Tkinter.Scrollbar( self, orient=Tkinter.VERTICAL) 78 hscrollbar = Tkinter.Scrollbar( self, orient=Tkinter.HORIZONTAL) 79 80 self._include_paths.config( yscrollcommand=vscrollbar.set 81 , xscrollcommand=hscrollbar.set ) 82 vscrollbar.config( command=self._include_paths.yview ) 83 hscrollbar.config( command=self._include_paths.xview ) 84 85 self._include_paths.grid( row=4, column=0, columnspan=2, sticky=Tkinter.NW ) 86 vscrollbar.grid( row=4, column=2, sticky=Tkinter.NS + Tkinter.W ) 87 hscrollbar.grid( row=5, column=0, columnspan=2, sticky=Tkinter.EW ) 88 89 temp = Tkinter.Button( self, text="add", command=self._add_include_path ) 90 temp.grid( row=6, column=0, sticky=Tkinter.NW + Tkinter.E) 91 temp = Tkinter.Button( self, text="remove", command=self._remove_include_path ) 92 temp.grid( row=6, column=1, columnspan=2, sticky=Tkinter.NE + Tkinter.W) 93 94 temp = Tkinter.Label( self, text="Defines:", justify=Tkinter.LEFT) 95 temp.grid( row=7, sticky=Tkinter.NW) 96 97 self._defines = Tkinter.Listbox( self, height=9, width=35 ) 98 vscrollbar = Tkinter.Scrollbar( self, orient=Tkinter.VERTICAL) 99 hscrollbar = Tkinter.Scrollbar( self, orient=Tkinter.HORIZONTAL) 100 101 self._defines.config( yscrollcommand=vscrollbar.set 102 , xscrollcommand=hscrollbar.set ) 103 vscrollbar.config( command=self._defines.yview ) 104 hscrollbar.config( command=self._defines.xview ) 105 106 self._defines.grid( row=8, column=0, columnspan=2, sticky=Tkinter.NW ) 107 vscrollbar.grid( row=8, column=2, sticky=Tkinter.NS + Tkinter.W ) 108 hscrollbar.grid( row=9, column=0, columnspan=2, sticky=Tkinter.EW ) 109 110 temp = Tkinter.Button( self, text="add", command=self._add_define ) 111 temp.grid( row=10, column=0, sticky=Tkinter.NW + Tkinter.E) 112 temp = Tkinter.Button( self, text="remove", command=self._remove_define ) 113 temp.grid( row=10, column=1, columnspan=2, sticky=Tkinter.NE + Tkinter.W) 114 115 map( lambda i: self.rowconfigure( i, weight=1 ), range(11) ) 116 117 this_module_dir_path = os.path.abspath ( os.path.dirname( sys.modules[__name__].__file__) ) 118 this_module_dir_path = this_module_dir_path.replace( '\\', '/' ) 119 this_module_dir_path = this_module_dir_path.lower() 120 if this_module_dir_path.endswith( '/sources/pyplusplus_dev/pyplusplus/gui' ): 121 gccxml_09_path = os.path.join( this_module_dir_path, '..', '..', '..', 'gccxml_bin', 'v09', sys.platform, 'bin' ) 122 self._gccxml_location.insert( 0, gccxml_09_path )
123
124 - def _select_gccxml_executable( self ):
125 file_name = tkFileDialog.askopenfilename() 126 if not file_name: 127 return 128 self._gccxml_location.delete( 0, Tkinter.END ) 129 self._gccxml_location.insert( 0, file_name )
130
131 - def _add_include_path( self ):
132 directory = tkFileDialog.askdirectory() 133 if directory: 134 self._include_paths.insert( Tkinter.END, directory )
135
136 - def _remove_include_path(self):
137 selected = list( self._include_paths.curselection() ) 138 selected = map( int, selected ) 139 selected.sort() 140 selected.reverse() 141 map( self._include_paths.delete, selected )
142
143 - def _add_define( self ):
144 symbol = tkSimpleDialog.askstring(title='Py++ - code generator demo' 145 , prompt="Define symbol ( example 'max(a,b)=a<b?b:a' ):") 146 if symbol: 147 self._defines.insert( Tkinter.END, symbol )
148
149 - def _remove_define(self):
150 selected = list( self._defines.curselection() ) 151 selected = map( int, selected ) 152 selected.sort() 153 selected.reverse() 154 map( self._defines.delete, selected )
155
156 - def parser_configuration(self):
157 return parser.config_t( gccxml_path=self._gccxml_location.get() 158 , include_paths=list(self._include_paths.get( 0, Tkinter.END ) ) 159 , define_symbols=list(self._defines.get( 0, Tkinter.END ) ) )
160
161 -class header_file_ui_t(custom_frame_t):
162 - def __init__(self, parent ):
163 custom_frame_t.__init__( self, parent, sticky=Tkinter.NW ) 164 165 temp = Tkinter.Label( self, text="Header file:", justify=Tkinter.LEFT) 166 temp.grid( row=0, sticky=Tkinter.NW + Tkinter.E, columnspan=3) 167 temp.configure( relief=Tkinter.GROOVE, borderwidth=1 ) 168 169 self._header_file = Tkinter.Entry( self, width=35 ) 170 self._header_file.grid(row=1, column=0, sticky=Tkinter.NW + Tkinter.E) 171 172 initial_header = gui_config_t.read_header_name() 173 if initial_header: 174 self._header_file.delete( 0, Tkinter.END ) 175 self._header_file.insert( 0, initial_header ) 176 177 temp = Tkinter.Button( self, text="...", command=self._select_header_file ) 178 temp.grid( row=1, column=2) 179 180 map( lambda i: self.rowconfigure( i, weight=1 ), range(2) )
181 182
183 - def _select_header_file( self ):
184 file_name = tkFileDialog.askopenfilename() 185 if not file_name: 186 return 187 self._header_file.delete( 0, Tkinter.END ) 188 self._header_file.insert( 0, file_name )
189
190 - def header_file(self):
191 hf = self._header_file.get() 192 if not os.path.isabs( hf ): 193 hf = os.path.abspath( hf ) 194 return hf
195
196 -class actions_ui_t(custom_frame_t):
197 - def __init__(self 198 , parent 199 , on_generate_code 200 , on_generate_pyplusplus 201 , on_create_gccxml):
202 custom_frame_t.__init__( self, parent, sticky=Tkinter.NW ) 203 204 temp = Tkinter.Button( self 205 , width=37 206 , text="generate code" 207 , command=on_generate_code ) 208 temp.grid( row=0, columnspan=3, sticky=Tkinter.NW + Tkinter.E ) 209 210 temp = Tkinter.Button( self 211 , text="generate Py++ code" 212 , command=on_generate_pyplusplus ) 213 temp.grid( row=1, sticky=Tkinter.NW + Tkinter.E) 214 215 temp = Tkinter.Button( self 216 , text="create XML" 217 , command=on_create_gccxml ) 218 temp.grid( row=2, sticky=Tkinter.NW + Tkinter.E) 219 220 map( lambda i: self.rowconfigure( i, weight=1 ), range(3) )
221 #self.columnconfigure( 0, weight=1 )
222 223 -class generated_code_ui_t(custom_frame_t):
224 - def __init__(self, parent):
225 custom_frame_t.__init__( self, parent ) 226 227 temp = Tkinter.Label( self, text="Generated code") 228 temp.grid( row=0, sticky=Tkinter.NW + Tkinter.E, columnspan=2) 229 temp.configure( relief=Tkinter.GROOVE, borderwidth=1 ) 230 231 self._generated_code = Tkinter.Text( self, width=80, height=40) 232 vscrollbar = Tkinter.Scrollbar( self, orient=Tkinter.VERTICAL) 233 hscrollbar = Tkinter.Scrollbar( self, orient=Tkinter.HORIZONTAL) 234 235 self._generated_code.config( yscrollcommand=vscrollbar.set 236 , xscrollcommand=hscrollbar.set 237 , wrap=Tkinter.NONE ) 238 vscrollbar.config( command=self._generated_code.yview ) 239 hscrollbar.config( command=self._generated_code.xview ) 240 241 self._generated_code.grid( row=1, column=0, sticky=Tkinter.NSEW) 242 vscrollbar.grid( row=1, column=1, sticky=Tkinter.N + Tkinter.S) 243 hscrollbar.grid( row=2, column=0, sticky=Tkinter.W + Tkinter.E) 244 245 self.rowconfigure( 1, weight=1 ) 246 self.columnconfigure( 0, weight=1 )
247
248 - def set_generated_code(self, code ):
249 self._generated_code.delete( 1.0, Tkinter.END ) 250 self._generated_code.insert( Tkinter.END, code )
251
252 -class statistics_t(custom_frame_t):
253 - def __init__(self, parent):
254 custom_frame_t.__init__( self, parent ) 255 256 temp = Tkinter.Label( self, text="Statistics", justify=Tkinter.LEFT) 257 temp.grid( row=0, sticky=Tkinter.NW + Tkinter.E, columnspan=3) 258 temp.configure( relief=Tkinter.GROOVE, borderwidth=1 ) 259 260 temp = Tkinter.Label( self, text="Parse time:") 261 temp.grid( row=1, column=0, sticky=Tkinter.NW) 262 263 self._parse_time = Tkinter.Label( self, text="0 seconds") 264 self._parse_time.grid( row=1, column=1, sticky=Tkinter.NW) 265 266 temp = Tkinter.Label( self, text="Code generation time:") 267 temp.grid( row=2, column=0, sticky=Tkinter.NW) 268 269 self._code_generation_time = Tkinter.Label( self, text="0 seconds") 270 self._code_generation_time.grid( row=2, column=1, sticky=Tkinter.NW)
271
272 - def set_parse_time(self, time ):
273 self._parse_time.config( text='%0.2f seconds' % time )
274
275 - def set_code_generation_time(self, time ):
276 self._code_generation_time.config( text='%0.2f seconds' % time )
277
278 -class main_widget_ui_t(custom_frame_t):
279 - def __init__(self, parent=None ):
280 custom_frame_t.__init__( self, parent ) 281 282 top = self.winfo_toplevel() 283 top.rowconfigure( 0, weight=1 ) 284 top.columnconfigure( 0, weight=1 ) 285 286 self.master.title('Py++ - code generator demo') 287 288 self._header_file_configurator = header_file_ui_t( self ) 289 self._header_file_configurator.grid( row=0, column=0, sticky=Tkinter.NW, padx=2, pady=2) 290 291 self._parser_configurator = parser_configuration_ui_t( self ) 292 self._parser_configurator.grid( row=1, column=0, sticky=Tkinter.NW, padx=2) 293 294 self._actions_ui = actions_ui_t( self 295 , on_generate_code=lambda:self._generate_code() 296 , on_generate_pyplusplus=lambda: self._generate_pyplusplus() 297 , on_create_gccxml=lambda:self._create_xml()) 298 299 self._actions_ui.grid( row=3, column=0, rowspan=4, sticky=Tkinter.SE +Tkinter.W, padx=2 ) 300 301 self._generated_code = generated_code_ui_t(self) 302 self._generated_code.grid( row=0, column=1, rowspan=5, sticky=Tkinter.NSEW, pady=2) 303 304 self._statistics = statistics_t( self ) 305 self._statistics.grid( row=6, column=1, sticky=Tkinter.EW + Tkinter.S ) 306 307 self.rowconfigure( 0, weight=1 ) 308 self.rowconfigure( 1, weight=1 ) 309 self.rowconfigure( 2, weight=1 ) 310 self.rowconfigure( 3, weight=1 ) 311 self.rowconfigure( 4, weight=1 ) 312 self.rowconfigure( 5, weight=0 ) 313 self.rowconfigure( 6, weight=0 ) 314 315 self.columnconfigure( 0, weight=0 ) 316 self.columnconfigure( 1, weight=1 )
317
318 - def _generate_pyplusplus(self):
319 config = self._parser_configurator.parser_configuration() 320 header_file = self._header_file_configurator.header_file() 321 config.include_paths.append( os.path.split( header_file )[0] ) 322 config.working_directory = os.path.split( header_file )[0] 323 w = wizard.wizard_t( config, header_file ) 324 self._generated_code.set_generated_code( w.create_code() )
325
326 - def _create_xml( self ):
327 try: 328 start_time = time.clock() 329 config = self._parser_configurator.parser_configuration() 330 header_file = self._header_file_configurator.header_file() 331 config.include_paths.append( os.path.split( header_file )[0] ) 332 config.working_directory = os.path.split( header_file )[0] 333 reader = parser.source_reader_t( config=config ) 334 xml_file = reader.create_xml_file( header_file ) 335 parsed_time = time.clock() - start_time 336 xml_file_obj = file( xml_file ) 337 self._generated_code.set_generated_code( xml_file_obj.read() ) 338 xml_file_obj.close() 339 os.remove( xml_file ) 340 self._statistics.set_parse_time( parsed_time ) 341 self._statistics.set_code_generation_time( 0 ) 342 except Exception, error: 343 user_msg = [ 'Error occured during code generation process!' ] 344 user_msg.append( 'Error:' ) 345 user_msg.append( str( error ) ) 346 self._generated_code.set_generated_code( '\n'.join( user_msg ) )
347
348 - def _generate_code(self):
349 global save_header_name 350 351 try: 352 config = self._parser_configurator.parser_configuration() 353 header_file = self._header_file_configurator.header_file() 354 if not header_file or not os.path.isfile( header_file ): 355 raise RuntimeError( 'Header file "%s" does not exist or should be valid file name.' % header_file ) 356 gui_config_t.save_header_name( header_file ) 357 config.include_paths.append( os.path.split( header_file )[0] ) 358 359 start_time = time.clock() 360 mb = module_builder.module_builder_t( 361 [ header_file ] 362 , gccxml_path=config.gccxml_path 363 , working_directory=os.path.split( header_file )[0] 364 , include_paths=config.include_paths 365 , define_symbols=config.define_symbols ) 366 367 parsed_time = time.clock() - start_time 368 369 mb.build_code_creator( "pyplusplus" ) 370 mb.code_creator.user_defined_directories.extend( config.include_paths ) 371 code = mb.code_creator.create() 372 code = code.replace( '\n\r', '\n' ) 373 code = code.replace( '\r\n', '\n' ) 374 code_generated_time = time.clock() - start_time - parsed_time 375 self._generated_code.set_generated_code( code ) 376 self._statistics.set_parse_time( parsed_time ) 377 self._statistics.set_code_generation_time( code_generated_time ) 378 except Exception, error: 379 user_msg = [ 'Error occured during code generation process!' ] 380 user_msg.append( 'Error:' ) 381 user_msg.append( str( error ) ) 382 self._generated_code.set_generated_code( '\n'.join( user_msg ) )
383
384 - def _copy_to_clipboard(self):
385 pass
386
387 -def show_demo():
388 root = Tkinter.Tk() 389 mw = main_widget_ui_t(root) 390 root.geometry("%dx%d%+d%+d" % (1024, 768, 0, 0)) # (width,height, x, y) 391 mw.mainloop()
392 393 if __name__ == "__main__": 394 show_demo() 395