Package nMOLDYN :: Package GUI :: Module SelectionDialog
[hide private]
[frames] | no frames]

Source Code for Module nMOLDYN.GUI.SelectionDialog

  1  """This modules implements the atom selection dialog used in almost all nMOLDYN analysis. 
  2   
  3  The atom selection can be performed for various purposes such as selection of atoms for the simulation, selection 
  4  of hydrogen atoms to deuterate or selection of several group of atoms on which an analysis will be performed  
  5  collectively. 
  6   
  7  Classes: 
  8      * SelectionDialog: sets up a selection dialog in the scope of an analysis dialog. 
  9  """ 
 10   
 11  # The python distribution modules 
 12  import copy 
 13  import os 
 14  import sys 
 15   
 16  # The Tcl/Tk modules 
 17  import Dialog 
 18  from Tkinter import * 
 19  from tkFileDialog import askopenfilename 
 20   
 21  # The nMOLDYN modules 
 22  from nMOLDYN.Core.Logger import LogMessage 
 23  from nMOLDYN.GUI.Widgets import ComboFileBrowser, ComboFrame, ComboListbox, ComboRadiobutton, ComboText 
 24               
25 -class SelectionDialog(Toplevel):
26 """Sets up a dialog from which the user can perform an atom selection. 27 """ 28
29 - def __init__(self, parent, selectionType, univContents):
30 """The constructor. 31 32 @param parent: the parent widget. 33 34 @param selectionType: a string being one of 'subset', 'deuteration' or 'group' specifying the 35 atom selection type thatwill be performed. 36 @type selectionType: string 37 38 @param univContents: a dictionnary that contains the universe contents. 39 @type univContents: dict 40 """ 41 42 Toplevel.__init__(self, parent) 43 self.transient(parent) 44 45 self.title('%s selection dialog' % selectionType) 46 47 self.parent = parent 48 49 # A local copy of the 'selectionType' argument. One of 'subset', 'deuteration', 'group'. 50 self.selectionType = selectionType 51 52 # A local copy of the 'univContents' argument. 53 self.univContents = copy.deepcopy(univContents) 54 55 # Create a set of all the possible keywords found in the universe contents. It will be used to tag those keywords 56 # in the 'Selection preview' text widget. 57 self.keywords = set() 58 for v in self.univContents.values(): 59 self.keywords.update(v.keys()) 60 61 # The selection dictionnary. 62 self.selection = {} 63 64 # The dictionnary that stores the keywords and values currently selected. 65 self.currentSelection = {} 66 67 # The selection string is set to its default value that is the entry value the ComboButton. 68 # The selection prefix i also set. It is used especially for 'group' selection 69 # types where it introducesand group1, group2 ...For 'subset' and 'deuteration' selection types, 70 # this is respectively 'subset' and 'deuteration' even in these cases the prefix will be omitted in 71 # the final selection string. 72 if self.selectionType == 'group': 73 self.selectionString = self.parent.widgets['group'].getValue() 74 self.selectedPrefixName = None 75 76 elif self.selectionType == 'triplet': 77 self.selectionType = 'group' 78 self.selectionString = self.parent.widgets['triplet'].getValue() 79 self.selectedPrefixName = None 80 81 elif self.selectionType == 'bond': 82 self.selectionType = 'group' 83 self.selectionString = self.parent.widgets['bond'].getValue() 84 self.selectedPrefixName = None 85 86 elif self.selectionType == 'subset': 87 self.selectionString = self.parent.widgets['subset'].getValue() 88 self.selectedPrefixName = self.selectionType 89 90 elif self.selectionType == 'deuteration': 91 self.selectionString = self.parent.widgets['deuteration'].getValue() 92 self.selectedPrefixName = self.selectionType 93 94 # The object name currently selected. 95 self.selectedObjectName = None 96 97 # The selection keyword currently selected. 98 self.selectedKeyword = None 99 100 body = Frame(self) 101 self.initial_focus = self.body(body) 102 body.grid(row = 0, column = 0, sticky = EW) 103 104 self.buttonbox() 105 106 self.grab_set() 107 108 if not self.initial_focus: 109 self.initial_focus = self 110 111 self.protocol("WM_DELETE_WINDOW", self.cancel) 112 113 self.resizable(width = NO, height = NO) 114 115 self.geometry("+%d+%d" % (parent.winfo_rootx()+50, parent.winfo_rooty()+50)) 116 117 self.initial_focus.focus_set() 118 119 self.wait_window(self)
120
121 - def body(self, master):
122 """Create dialog body. Return widget that should have initial focus. 123 """ 124 125 self.settingsFrame = LabelFrame(master, text = 'Settings', bd = 2, relief = GROOVE) 126 self.settingsFrame.grid(row = 0, column = 0, sticky = EW, padx = 3, pady = 3) 127 self.settingsFrame.grid_columnconfigure(0, weight = 1) 128 129 self.selectionMediasRadio = ComboRadiobutton(self.settingsFrame,\ 130 frameLabel = "Selection media",\ 131 contents = ["from a selection file",\ 132 "from the loaded trajectory",\ 133 "from an expression string"],\ 134 layout = (1,3),\ 135 default = 1) 136 [r.config(width = 22, command = self.changeSelectionMedia) for r in self.selectionMediasRadio.radio] 137 self.selectionMediasRadio.grid(row = 0, column = 0, padx = 2, pady = 5, sticky = EW) 138 139 # The frame that will host the selection browsers specific to the selected selection type. 140 self.selectionFrame = Frame(self.settingsFrame, bd = 2, relief = GROOVE, width = 1000, height = 300) 141 self.selectionFrame.grid(row = 1, column = 0, padx = 3, pady = 3, sticky = 'NEW') 142 self.selectionFrame.grid_propagate(0) 143 self.selectionFrame.grid_columnconfigure(0, weight = 1) 144 self.selectionFrame.grid_rowconfigure(10, weight = 1) 145 146 # The selection browser for a selection from a selection file. 147 self.fileBrowser = ComboFileBrowser(self.selectionFrame,\ 148 frameLabel = 'Selection from a selection file',\ 149 command = self.selectFromFile) 150 self.fileBrowser.entry.config(width = 100) 151 self.fileBrowser.entry.bind('<Return>', self.selectFromFile) 152 153 # The selection browser for a selection from the loaded trajectory. This is the one displayed by default. 154 self.objectBrowser = ComboFrame(self.selectionFrame, frameLabel = 'Selection from the loaded trajectory') 155 self.objectBrowser.grid(row = 0, column = 0, padx = 3, pady = 3, sticky = EW) 156 self.objectBrowser.grid_columnconfigure(0, weight = 1) 157 self.objectBrowser.grid_columnconfigure(1, weight = 1) 158 self.objectBrowser.grid_columnconfigure(2, weight = 1) 159 160 if self.selectionType == 'group': 161 self.objectBrowser.grid_columnconfigure(3, weight = 1) 162 self.objectBrowser.grid_columnconfigure(4, weight = 1) 163 164 f = Frame(self.objectBrowser, bd = 0) 165 f.grid(row = 0, column = 0, sticky = EW) 166 # The 'Object type' listbox for the selection of a given object type. 167 self.prefixName = ComboListbox(f, frameLabel = 'Group number', contents = ['group1']) 168 self.prefixName.lb.config(width = 8, height = 8, exportselection = 0, selectmode = SINGLE) 169 170 Button(f, width = 6, text = 'New group', command = self.createNewGroup).grid(row = 1, column = 0, padx = 2, pady = 2, sticky = EW) 171 172 f.grid_rowconfigure(0, weight = 1) 173 174 self.prefixName.grid(row = 0, column = 0, padx = 2, pady = 2, sticky = EW) 175 self.prefixName.grid_columnconfigure(0, weight = 1) 176 self.prefixName.lb.bind('<ButtonRelease-1>', self.selectPrefixName) 177 self.prefixName.lb.bind('<Double-1>', self.deletePrefixName) 178 179 colNum = 1 180 181 else: 182 colNum = 0 183 184 # The 'Object type' listbox for the selection of a given object type. 185 self.objectName = ComboListbox(self.objectBrowser,\ 186 frameLabel = 'Object name',\ 187 contents = sorted(self.univContents.keys())) 188 self.objectName.grid(row = 0, column = colNum, padx = 2, pady = 2, sticky = EW) 189 self.objectName.grid_columnconfigure(0, weight = 1) 190 self.objectName.lb.config(width = 20, exportselection = 0, selectmode = SINGLE) 191 192 self.objectName.lb.bind('<ButtonRelease-1>', self.selectObjectName) 193 self.objectName.lb.bind('<Double-1>', self.deleteObjectName) 194 195 if self.selectionType == 'group': 196 # The 'Selection keyword' listbox for the selection of a given selection keyword. 197 self.groupingLevel = ComboListbox(self.objectBrowser,'Grouping level') 198 self.groupingLevel.grid(row = 0, column = colNum+1, padx = 2, pady = 2, sticky = EW) 199 self.groupingLevel.grid_columnconfigure(0, weight = 1) 200 self.groupingLevel.lb.config(width = 20, exportselection = 0, selectmode = SINGLE) 201 self.groupingLevel.lb.bind('<ButtonRelease-1>', self.selectGroupingLevel) 202 colNum += 1 203 204 # The 'Selection keyword' listbox for the selection of a given selection keyword. 205 self.selectionKeyword = ComboListbox(self.objectBrowser, 'Selection keyword') 206 self.selectionKeyword.grid(row = 0, column = colNum+1, padx = 2, pady = 2, sticky = EW) 207 self.selectionKeyword.grid_columnconfigure(0, weight = 1) 208 self.selectionKeyword.lb.config(width = 20, exportselection = 0, selectmode = SINGLE) 209 self.selectionKeyword.lb.bind('<ButtonRelease-1>', self.selectKeyword) 210 211 # The 'Selection value' listbox for the selection of a given selection value. 212 self.selectionValue = ComboListbox(self.objectBrowser, 'Selection value') 213 self.selectionValue.grid(row = 0, column = colNum+2, padx = 2, pady = 2, sticky = EW) 214 self.selectionValue.grid_columnconfigure(0, weight = 1) 215 self.selectionValue.lb.config(width = 40, exportselection = 0, selectmode = MULTIPLE) 216 self.selectionValue.lb.bind('<ButtonRelease-1>', self.selectValue) 217 self.selectionValue.lb.bind('<Control-a>', self.selectValue) 218 219 # The frame that will host the button used to build the regular selection expression. 220 selectionButtons = ComboFrame(self.objectBrowser, frameLabel = 'Linkers') 221 selectionButtons.grid(row = 1, column = 0, columnspan = 5, padx = 2, pady = 2, sticky = EW) 222 223 # The five buttons that allow to the construction of the selection patterns. 224 Button(selectionButtons, text = 'Clear', width = 4, command = self.clear).grid(row = 0, column = 0) 225 Button(selectionButtons, text = '(' , width = 4, command = lambda : self.appendLinker('(')).grid(row = 0, column = 1) 226 Button(selectionButtons, text = ')' , width = 4, command = lambda : self.appendLinker(')')).grid(row = 0, column = 2) 227 Button(selectionButtons, text = 'AND' , width = 4, command = lambda : self.appendLinker('AND')).grid(row = 0, column = 3) 228 Button(selectionButtons, text = 'OR' , width = 4, command = lambda : self.appendLinker('OR')).grid(row = 0, column = 4) 229 230 # The selection browser for a selection from an expression string. 231 self.expressionBrowser = ComboText(self.selectionFrame, 'Selection from an expression string') 232 self.expressionBrowser.text.config(height = 10, state = NORMAL) 233 self.expressionBrowser.text.bind('<Return>', self.selectFromExpression) 234 235 self.selectionPreview = ComboText(self.settingsFrame, 'Selection preview') 236 self.selectionPreview.grid(row = 2, column = 0, padx = 3, pady = 3, sticky = EW) 237 self.selectionPreview.grid_columnconfigure(0, weight = 1) 238 self.selectionPreview.text.config(height = 10, font = ('Courier', '12')) 239 self.selectionPreview.text.tag_config('prefix' , foreground = 'pink' , font = ('Courier','12','bold')) 240 self.selectionPreview.text.tag_config('italic' , foreground = 'black' , font = ('Courier','12','normal', 'italic')) 241 self.selectionPreview.text.tag_config('bold' , foreground = 'black' , font = ('Courier','12','bold')) 242 self.selectionPreview.text.tag_config('objectname', foreground = 'red' , font = ('Courier','12','bold')) 243 self.selectionPreview.text.tag_config('filename' , foreground = 'blue' , font = ('Courier','12','bold')) 244 self.selectionPreview.text.tag_config('expression', foreground = 'green' , font = ('Courier','12','bold')) 245 self.selectionPreview.text.tag_config('()' , foreground = 'black' , font = ('Courier','12','bold')) 246 self.selectionPreview.text.tag_config('AND' , foreground = 'purple', font = ('Courier','12','bold')) 247 self.selectionPreview.text.tag_config('OR' , foreground = 'purple', font = ('Courier','12','bold')) 248 249 self.displaySelectionString() 250 251 return None
252
253 - def buttonbox(self):
254 """Add standard button box. 255 """ 256 257 # The frame that contains the 'Cancel' and 'OK' buttons. 258 box = LabelFrame(self, text = 'Actions', bd = 2, relief = GROOVE) 259 box.grid(row = 1, column = 0, sticky = EW, padx = 3, pady = 3) 260 box.grid_columnconfigure(0, weight = 1) 261 262 w = Button(box, text = "Cancel", width=10, command = self.cancel) 263 w.grid(row = 0, column = 0, sticky = E) 264 w = Button(box, text = "OK", width=10, command = self.ok, default=ACTIVE) 265 w.grid(row = 0, column = 1, sticky = E) 266 267 self.bind("<Return>", self.ok) 268 self.bind("<Escape>", self.cancel)
269 270 # Standard button semantics.
271 - def ok(self, event = None):
272 """This method is called when the user clicks on the 'OK' button of the selection editor 273 dialog. It closes the selection editor dialog and build the selection string. 274 """ 275 276 if not self.validate(): 277 self.initial_focus.focus_set() 278 return 279 280 self.withdraw() 281 self.update_idletasks() 282 283 self.apply() 284 285 # Put focus back to the parent window 286 self.parent.focus_set() 287 self.destroy()
288
289 - def cancel(self, event = None):
290 """Cancel the selection setting up the selection string to a selection type-dependant value. 291 """ 292 293 if self.selectionType == 'group': 294 self.selectionString = 'all' 295 296 elif self.selectionType == 'subset': 297 self.selectionString = 'all' 298 299 elif self.selectionType == 'deuteration': 300 self.selectionString = 'no' 301 302 # Put focus back to the parent window 303 self.parent.focus_set() 304 self.destroy()
305
306 - def validate(self):
307 return True
308
309 - def apply(self):
310 """Performs a last checking of the selection string before closing the selection dialog. 311 """ 312 313 # The selection string built from tke loaded universe are checked for trailing 'AND' or 'OR' that may 314 # fool the selection string parser. 315 for key in self.selection.keys(): 316 317 # Selection strings coming from file and expression medias do not need to be checked. 318 if key in ['filename','expression']: 319 return 320 321 for subkey in self.selection[key].keys(): 322 if self.selection[key][subkey]: 323 if self.selection[key][subkey][-1] in ['AND', 'OR']: 324 del self.selection[key][subkey][-1] 325 if not self.selection[key][subkey]: 326 del self.selection[key][subkey] 327 else: 328 del self.selection[key][subkey] 329 330 if not self.selection: 331 return 332 333 # Build the selection string out of the self.selection dictionnary. 334 self.buildSelectionString()
335
336 - def getValue(self):
337 """This method returns the self.selectionString class attributes. 338 339 Thanks to this method, the selection dialog can be used like any other ComboWidget for which the getValue 340 allows to fetch their contents. 341 """ 342 return self.selectionString
343
345 """Sets the selection string to its default value. This value depends on the the selection type. 346 """ 347 348 if self.selectionType == 'group': 349 self.selectionString = 'all' 350 351 elif self.selectionType == 'subset': 352 self.selectionString = 'all' 353 354 elif self.selectionType == 'deuteration': 355 self.selectionString = 'no'
356
357 - def changeSelectionMedia(self):
358 """Changes the 'media' from which the selection will be performed. 359 360 It can be either from a selection file, either from the loaded trajectory or from an expression string. 361 When changing selection media, the previous selection is cleared. 362 """ 363 364 self.clear() 365 366 selectionMedia = self.selectionMediasRadio.getValue() 367 368 for w in self.selectionFrame.winfo_children(): 369 w.grid_forget() 370 371 if selectionMedia == 'from a selection file': 372 self.fileBrowser.grid(row = 0, column = 0, padx = 3, pady = 3, sticky = EW) 373 self.fileBrowser.grid_columnconfigure(0, weight = 1) 374 375 elif selectionMedia == 'from the loaded trajectory': 376 self.objectBrowser.grid(row = 0, column = 0, padx = 3, pady = 3, sticky = EW) 377 self.objectBrowser.grid_columnconfigure(0, weight = 1) 378 self.objectBrowser.grid_columnconfigure(1, weight = 1) 379 self.objectBrowser.grid_columnconfigure(2, weight = 1) 380 381 elif selectionMedia == 'from an expression string': 382 self.expressionBrowser.grid(row = 0, column = 0, padx = 3, pady = 3, sticky = EW) 383 self.expressionBrowser.grid_columnconfigure(0, weight = 1)
384
385 - def clear(self):
386 """This methods clears all the listboxes of the 'Selection from the loaded trajectory' browser. 387 It resets the selection listboxes and their associated variables, it resets the selection 388 string, and updates the 'Selection preview' text widget. 389 """ 390 391 self.selectedPrefixName = self.selectionType 392 if self.selectionType == 'group': 393 self.prefixName.lb.selection_clear(0, END) 394 self.groupingLevel.lb.selection_clear(0, END) 395 396 self.selection = {} 397 398 self.selectedObjectName = None 399 400 # The 'Object name' listbox selection is cleared. 401 self.objectName.lb.selection_clear(0, END) 402 403 self.selectedKeyword = None 404 self.selectionKeyword.cleanup() 405 406 self.currentSelection = {} 407 self.selectionValue.cleanup() 408 409 # Build the selection string out of the self.selection dictionnary. 410 self.buildSelectionString() 411 412 # Displays the selection string on the 'Selection preview' text widget. 413 self.displaySelectionString()
414
415 - def buildSelectionString(self):
416 """This method actually build the selection string out of the |self.selection| dictionnary. 417 """ 418 419 # In case of a selection from a file, the selection string just contain the keyword 'filename' 420 # followed by the name of the file. 421 if self.selection.has_key('filename'): 422 self.selectionString = 'filename %s' % self.selection['filename'] 423 424 elif self.selection.has_key('expression'): 425 self.selectionString = 'expression %s' % self.selection['expression'] 426 427 else: 428 self.selectionString = '' 429 for prefix in sorted(self.selection.keys()): 430 # In case of 'subset' and 'deuteration' selection types, the prefix are not included in 431 # the selection string. 432 if prefix not in ['subset', 'deuteration']: 433 self.selectionString += prefix + ' ' 434 435 if self.selectionType == 'group': 436 self.selectionString += 'groupinglevel %s ' % self.groupingLevel.lb.get(int(self.groupingLevel.lb.curselection()[0])) 437 438 sortedObjectNames = sorted(self.selection[prefix].keys()) 439 for index1 in range(len(sortedObjectNames)): 440 objectName = sortedObjectNames[index1] 441 objectSelection = self.selection[prefix][objectName] 442 443 if objectSelection: 444 self.selectionString += 'objectname %s ' % objectName 445 446 for objSel in objectSelection: 447 if isinstance(objSel,dict): 448 sortedKeywords = sorted(objSel.keys()) 449 for index in range(len(sortedKeywords)): 450 keyword = sortedKeywords[index] 451 value = objSel[keyword] 452 self.selectionString += '%s %s ' % (keyword, ','.join(value)) 453 if index < len(sortedKeywords) - 1: 454 self.selectionString += 'OR ' 455 else: 456 self.selectionString += objSel + ' ' 457 if index1 < len(sortedObjectNames) - 1: 458 self.selectionString += 'OR ' 459 460 # The string is stripped. 461 self.selectionString = self.selectionString.strip()
462
463 - def displaySelectionString(self):
464 """Displays in the 'Selection preview' textwidget the selection string under process. 465 """ 466 467 # First the 'Selection preview' text widget is cleaned up. 468 self.selectionPreview.cleanup() 469 470 # If the selection string is empty, do nothing. 471 if not self.selectionString: 472 return 473 474 # The selection string is inserted in the 'Selection preview' text widget. 475 self.selectionPreview.insert(contents = self.selectionString) 476 477 # The prefixes are tagged. 478 for k in self.selection.keys(): 479 self.selectionPreview.tag(k,'prefix') 480 481 # The selection keywords are tagged. 482 for k in self.keywords: 483 self.selectionPreview.tag(k,'italic') 484 485 # The word 'objectname' is tagged. 486 self.selectionPreview.tag('objectname','objectname') 487 # The word 'filename' is tagged. 488 self.selectionPreview.tag('filename','filename') 489 # The word 'filename' is tagged. 490 self.selectionPreview.tag('expression','expression') 491 492 # The linker are tagged. 493 self.selectionPreview.tag('(','()') 494 self.selectionPreview.tag(')','()') 495 self.selectionPreview.tag('AND','AND') 496 self.selectionPreview.tag('OR','OR')
497
498 - def selectFromExpression(self, event):
499 """This callback performs a selection from a expression string by writing the expression in its corresponding text 500 widget. 501 502 The expression must be a set of valid ;-separated python instructions the last one being 'selection = ...' 503 as the selection string parser will search for the selection variables when executing the expression string. 504 505 To refer to the universe just use the variable 'self.universe'. 506 """ 507 508 if not self.expressionBrowser.text.get('0.0', END).strip(): 509 return 510 511 # Update the self.selection dictionnary. 512 self.selection = {'expression' : self.expressionBrowser.text.get('0.0', END).strip()} 513 514 # Build the selection string out of the self.selection dictionnary. 515 self.buildSelectionString() 516 517 # Displays the selection string on the 'Selection preview' text widget. 518 self.displaySelectionString() 519 520 return 'break'
521
522 - def selectFromFile(self, event = None):
523 """This method/callback performs a selection from a file by selection the file from a browser. 524 """ 525 526 # If the method is called as a callback using the Return button on the entry of the file browser. 527 if event: 528 # Is there already a file name in the file browser entry ? There can be one if the methid is used as a 529 # callback when pressing Return on the entry of the filebrowser. 530 filename = self.fileBrowser.getValue() 531 532 # There is no file name so open a browser for the file selection. 533 else: 534 # The name of the NetCDF file to load. 535 filename = askopenfilename(parent = self, filetypes = [('NMS file','.nms'), ('Python file', '.py'), ('All files', '.*')]) 536 537 # Checks that the file name is not an empty string. 538 if not filename: 539 self.fileBrowser.setValue('') 540 return 541 542 # Checks that the file exists. 543 if not os.path.exists(filename): 544 self.fileBrowser.setValue('') 545 return 546 547 # Update the entry of the file browser. 548 self.fileBrowser.setValue(filename) 549 550 # Update the self.selection dictionnary. 551 self.selection = {'filename' : filename} 552 553 # Build the selection string out of the self.selection dictionnary. 554 self.buildSelectionString() 555 556 # Displays the selection string on the 'Selection preview' text widget. 557 self.displaySelectionString() 558 559 return 'break'
560 561 # The following methods all intervene when performing the selection from the loaded trajectory.
562 - def selectPrefixName(self, event):
563 """This callback is called when the user clicks on one item of the 'Group number' listbox of the selection editor. 564 """ 565 566 # The selected object is reset. 567 self.selectedObjectName = None 568 569 # The 'Object name' listbox selection is cleared. 570 self.objectName.lb.selection_clear(0, END) 571 572 # The 'Selection keyword' listbox contents is suppressed. 573 self.selectionKeyword.cleanup() 574 575 # The 'Selection value' listbox contents is suppressed. 576 self.selectionValue.cleanup() 577 578 # The self.currentSelection dictionnary is reset. 579 self.currentSelection = {} 580 581 # If no prefix was selected in the listbox, do nothing. 582 if not self.prefixName.lb.curselection(): 583 self.selectedPrefixName = None 584 else: 585 # The self.selectedPrefixName attribute is updated. 586 self.selectedPrefixName = self.prefixName.lb.get(int(self.prefixName.lb.curselection()[0]))
587
588 - def deletePrefixName(self, event):
589 """This callback will remove the selection string associated to the selected prefix name. 590 """ 591 592 # If no prefix was selected in the listbox, do nothing. 593 if not self.prefixName.lb.curselection(): 594 return 595 596 # The selected prefix. 597 sel = self.prefixName.lb.get(int(self.prefixName.lb.curselection()[0])) 598 599 # The entry of the self.selection dictionnary corresponding to the selected prefix is removed. 600 if self.selection.has_key(sel): 601 del self.selection[sel] 602 603 # Build the selection string out of the self.selection dictionnary. 604 self.buildSelectionString() 605 606 # Displays the selection string on the 'Selection preview' text widget. 607 self.displaySelectionString()
608
609 - def createNewGroup(self):
610 """This callback will create a new group entry in the 'Group number' listbox. 611 """ 612 613 # If the selection type is not 'group', do nothing. 614 if self.selectionType != 'group': 615 return 616 617 # A new entry is inserted at the end of the 'Group number' listbox. 618 self.prefixName.lb.insert(END, 'group' + str(len(self.prefixName.lb.get(0, END))+1))
619
620 - def selectObjectName(self, event):
621 """This callback is called when the user clicks on one item of the 'Object name' listbox of the 622 selection editor. It will display into the 'Selection keyword' listbox all the selection keywords 623 corresponding to the selected object type. 624 """ 625 626 # If there is no prefix selected, do nothing. 627 if not self.selectedPrefixName: 628 return 629 630 # If the self.selection dictionnary does not have the selected prefix name as key, create it. 631 if not self.selection.has_key(self.selectedPrefixName): 632 self.selection[self.selectedPrefixName] = {} 633 634 # If no object was selected in the 'Object name' listbox, do nothing. 635 if not self.objectName.lb.curselection(): 636 return 637 638 # The MMTK object type. 639 self.selectedObjectName = self.objectName.lb.get(int(self.objectName.lb.curselection()[0])) 640 641 # If the self.selection dictionnary does not have the selected object name as subkey, set it with an empty 642 # list that will contain the linker and selection dictionnaries. 643 if not self.selection[self.selectedPrefixName].has_key(self.selectedObjectName): 644 self.selection[self.selectedPrefixName][self.selectedObjectName] = [] 645 646 if self.selectionType == 'group': 647 # Clean and then updates the 'Selection keyword' listbox. 648 self.groupingLevel.cleanup() 649 for gl in sorted(self.univContents[self.selectedObjectName]['groupinglevel'][1]): 650 self.groupingLevel.lb.insert(END, gl) 651 self.groupingLevel.lb.selection_set(self.univContents[self.selectedObjectName]['groupinglevel'][0]) 652 653 # Clean and then updates the 'Selection keyword' listbox. 654 self.selectionKeyword.cleanup() 655 for k in sorted(self.univContents[self.selectedObjectName].keys()): 656 if k in ['number','objectclass', 'groupinglevel']: 657 continue 658 659 self.selectionKeyword.lb.insert(END, k) 660 661 # The 'Selection values' listbox is cleaned up. 662 self.selectionValue.cleanup() 663 664 # The current selection is cleaned up. 665 self.currentSelection = {}
666
667 - def selectGroupingLevel(self, event):
668 """ 669 """ 670 if self.selectionString: 671 # Build the selection string out of the self.selection dictionnary. 672 self.buildSelectionString() 673 674 # Displays the selection string on the 'Selection preview' text widget. 675 self.displaySelectionString()
676
677 - def selectKeyword(self, event):
678 """This callback is called whenever the user clicks on one item of the 'Selection keyword' listbox. 679 It will display in the 'Selection value' listbox the selection values available for the 680 selected keyword. 681 """ 682 683 # If no keyword was selected in the 'Selection keyword' listbox, do nothing. 684 if not self.selectionKeyword.lb.curselection(): 685 return 686 687 # The selected selection keyword. 688 self.selectedKeyword = self.selectionKeyword.lb.get(int(self.selectionKeyword.lb.curselection()[0])) 689 690 # The 'Selection value' listbox is cleaned. 691 self.selectionValue.cleanup() 692 693 # List of the values available for the the selected selection keyword. 694 values = self.univContents[self.selectedObjectName][self.selectedKeyword] 695 696 # The selection values corresponding to the selected selection keyword are displayed in the 'Selection value' listbox. 697 self.selectionValue.insert(values) 698 699 # Activate the 'Selected value' listbox entries that are currently under process. 700 for index in range(len(values)): 701 value = values[index] 702 try: 703 # If the selection keyword is present in the current selection then it is selected in the listbox 704 # by default 705 if value in self.currentSelection[self.selectedKeyword]: 706 self.selectionValue.lb.selection_set(index) 707 except KeyError: 708 continue
709
710 - def deleteObjectName(self, event):
711 """This method will delete the object name from the selection string if it was previously selected. 712 """ 713 714 # If no object name was selected in the 'Object name' listbox, do nothing. 715 if not self.objectName.lb.curselection(): 716 return 717 718 # The selected object name. 719 objectName = self.objectName.lb.get(int(self.objectName.lb.curselection()[0])) 720 721 # Delete the self.selection dictionnary subkeys that matches the selected object name. 722 for k in self.selection.keys(): 723 if self.selection[k].has_key(objectName): 724 del self.selection[k][objectName] 725 726 # Build the selection string out of the self.selection dictionnary. 727 self.buildSelectionString() 728 729 # Displays the selection string on the 'Selection preview' text widget. 730 self.displaySelectionString()
731
732 - def selectValue(self, event):
733 """This callback is called whenever the user clicks on one entry of the 'Selection value' listbox. 734 It will update the current selection. 735 """ 736 737 # If the event is Ctrl-a, select everything. 738 if event.keysym == 'a': 739 self.selectionValue.lb.selection_set(0, END) 740 741 # If some values were selected in the 'Selected value' listbox, updates the self.currentSelection 742 # dictionnary with the selected values. 743 if self.selectionValue.lb.curselection(): 744 selectedValues = [self.selectionValue.lb.get(int(v)) for v in self.selectionValue.lb.curselection()] 745 self.currentSelection[self.selectedKeyword] = selectedValues 746 747 # Else, update the self.currentSelection dictionnary by removing the key corresponding to the 748 # selected keyword for which no values have been selected. 749 else: 750 if self.currentSelection.has_key(self.selectedKeyword): 751 del self.currentSelection[self.selectedKeyword] 752 else: 753 return 754 755 # The selected prefix name. 756 prefixName = self.selectedPrefixName 757 758 # The selected object name. 759 objectName = self.selectedObjectName 760 761 # The selection list is updated. 762 if not self.selection[prefixName][objectName]: 763 if self.currentSelection: 764 # If it is empty, the current expression is automatically appended. 765 self.selection[prefixName][objectName].append(self.currentSelection) 766 else: 767 # It if is not empty and the last element is already a selection expression then replaces it. 768 if isinstance(self.selection[prefixName][objectName][-1],dict): 769 if self.currentSelection: 770 self.selection[prefixName][objectName][-1] = self.currentSelection 771 else: 772 del self.selection[prefixName][objectName][-1] 773 # It if is not empty and the last element is a linker then append the current expression. 774 else: 775 if self.currentSelection: 776 self.selection[prefixName][objectName].append(self.currentSelection) 777 778 reset = True 779 for k in self.selection.keys(): 780 for kk in self.selection[k].keys(): 781 if self.selection[k][kk]: 782 reset = False 783 else: 784 if reset: 785 self.clear() 786 787 # Build the selection string out of the self.selection dictionnary. 788 self.buildSelectionString() 789 790 # Displays the selection string on the 'Selection preview' text widget. 791 self.displaySelectionString()
792
793 - def appendLinker(self, linker):
794 """ 795 This method is called when the user press the '(', ')', 'AND' or 'OR' buttons of the atom selection 796 dialog. It: 797 - checks whether the selected linker can be actually be appended 798 - appends the linker if so. 799 """ 800 801 # If no object name is selected, do nothing. 802 if self.selectedObjectName is None: 803 return 804 805 # Some basic checkings to prevent user from badly formatting a selection pattern string. 806 # May not be sufficient but should throw most of the errors. 807 808 # The linker must be one of '(', ')', 'AND', 'OR'. 809 if linker not in ['(',')','AND','OR']: 810 return 811 812 selList = self.selection[self.selectedPrefixName][self.selectedObjectName] 813 814 # If the selection pattern is empty, then the only possible linker to append is '('. 815 if not selList: 816 if linker != '(': 817 return 818 else: 819 # Case of '('. Must follow '(', 'AND' or 'OR'. 820 if linker == '(': 821 if selList[-1] not in ['AND','OR','(']: 822 return 823 # Case of ')'. 824 # -Should always be less ')' than '('. 825 # -Must not follow '(', 'AND' or 'OR'. 826 elif linker == ')': 827 if selList.count('(') <= selList.count(')'): 828 return 829 if selList[-1] in ['AND', 'OR', '(']: 830 return 831 # Case of 'AND'. Must not follow '(', 'AND' or 'OR'. 832 elif linker == 'AND': 833 if selList[-1] in ['AND','OR','(']: 834 return 835 # Case of 'OR'. Must not follow '(', 'AND' or 'OR'. 836 elif linker == 'OR': 837 if selList[-1] in ['AND','OR','(']: 838 return 839 840 # Everything seems OK, the linker can be appended. 841 selList.append(linker) 842 843 # The 'Selection value' listbox is cleaned up. 844 self.selectionValue.lb.selection_clear(0, END) 845 846 # The current selection is reinitiliazed. 847 self.currentSelection = {} 848 849 # Build the selection string out of the self.selection dictionnary. 850 self.buildSelectionString() 851 852 # Displays the selection string on the 'Selection preview' text widget. 853 self.displaySelectionString()
854