Package nltk :: Package app :: Module wxwordnet_app
[hide private]
[frames] | no frames]

Source Code for Module nltk.app.wxwordnet_app

  1  # Wordnet Interface: Graphical Wordnet Browser 
  2  #  
  3  # Copyright (C) 2001-2011 NLTK Project 
  4  # Author: Jussi Salmela <jtsalmela@users.sourceforge.net> 
  5  #         Paul Bone <pbone@students.csse.unimelb.edu.au> 
  6  # URL: <http://www.nltk.org/> 
  7  # For license information, see LICENSE.TXT 
  8   
  9  """ 
 10  Wordnet Interface: Graphical Wordnet Browser 
 11   
 12      python wxbrowse.py 
 13       
 14      This has a GUI programmed using wxPython and thus needs wxPython 
 15      to be installed. 
 16   
 17      Features of wxbrowse.py: 
 18   
 19       - A short help display at the start 
 20       - Notebook UI: tabsheets with independent search histories 
 21       - Menu 
 22       - File functions: page save&open, print&preview 
 23       - Tabsheet functions: open&close; start word search in a new tabsheet 
 24       - Page history: previous&next page 
 25       - Font size adjustment: increase&decrease&normalize 
 26       - Show Database Info: 
 27         - counts of words/synsets/relations for every POS 
 28         - example words as hyperlinks, 1 word for every relation&POS pair 
 29       - Help 
 30       - The position and size of the browser window and the font size 
 31         chosen is remembered between sessions. 
 32       - Possibility to give several words/collocations to be searched 
 33         and displayed at the same time by separating them with a comma 
 34         in search word(s) field 
 35       - Tries to deduce the stems of the search word(s) given 
 36       - Showing the parts of speech for a word typed in the search field 
 37       - Showing the parts of speech for a word clicked in one of the 
 38         synsets 
 39       - Showing the relation names for a synset when S: is clicked and 
 40         hiding them again at the second click. 
 41       - Showing the synsets for a relation. This covers most of the 
 42         relations for nouns and some relations for other POS's also. 
 43  """ 
 44   
 45  import os 
 46  import os.path 
 47  import sys 
 48  from time import sleep 
 49  import pickle 
 50  import platform 
 51  from urllib import quote_plus, unquote_plus 
 52  from itertools import groupby 
 53   
 54  import wx 
 55  import wx.html as  html 
 56  import wx.lib.wxpTag 
 57   
 58  from wordnet_app import page_from_word, new_word_and_body, show_page_and_word,\ 
 59       html_header, html_trailer, get_static_page_by_path,\ 
 60       explanation, pg   
 61   
 62   
 63  # 
 64  # Comments within this code indicate future work.  These comments are 
 65  # marked with 'XXX' 
 66  # 
 67   
 68   
 69  # XXX: write these global constants in shouting case. 
 70  # 
 71  # Additionally, through-out this module docstrings should be entered. 
 72  # 
 73   
 74   
 75  frame_title = 'NLTK Wordnet Browser' 
 76  help_about = frame_title + __doc__ 
 77   
 78  # This is used to save options in and to be pickled at exit 
 79  options_dict = {} 
 80   
 81  try: 
 82      nltk_prefs_dir = os.path.join(os.environ['HOME'], ".nltk") 
 83  except KeyError: 
 84      # XXX: This fallback may have problems on windows. 
 85      nltk_prefs_dir = os.path.curdir 
 86  pickle_file_name = os.path.join(nltk_prefs_dir,  
 87                                  (frame_title + os.path.extsep + 'pkl')) 
 88   
 89  ### XXX: MUST find a standard location for the stats HTML page, 
 90  ###      perhapsw in NLTK_DATA. 
 91   
 92  WORDNET_DB_INFO_FILEPATH = 'NLTK Wordnet Browser Database Info.html'  
 93   
 94   
 95   
96 -class MyHtmlWindow(html.HtmlWindow):
97 - def __init__(self, parent, id):
98 html.HtmlWindow.__init__(self, parent, id, 99 style=wx.NO_FULL_REPAINT_ON_RESIZE) 100 self.parent = parent 101 self.font_size = self.normal_font_size = \ 102 options_dict['font_size'] 103 self.incr_decr_font_size(0) # Keep it as it is
104
105 - def OnLinkClicked(self, linkinfo):
106 href = linkinfo.GetHref() 107 tab_to_return_to = None 108 word = self.parent.parent.search_word.GetValue() 109 if linkinfo.Event.ControlDown(): 110 if linkinfo.Event.ShiftDown(): 111 self.parent.add_html_page(activate=True) 112 else: 113 tab_to_return_to = self.parent.current_page 114 self.parent.add_html_page(activate=True) 115 self.parent.SetPageText(self.parent.current_page, word) 116 self.parent.parent.search_word.SetValue(word) 117 page,word = page_from_word(word, href) 118 if page: 119 if word: 120 self.parent.SetPageText(self.parent.current_page, word) 121 self.parent.parent.show_page_and_word(page, word) 122 else: 123 self.show_msg('The word was not found!') 124 self.parent.parent.show_page_and_word(page) 125 else: 126 self.show_msg('Relation "%s" is not implemented yet!' % rel_name) 127 128 # XXX: MAY simplfy the if predicate. */ 129 if tab_to_return_to is not None: 130 self.parent.switch_html_page(tab_to_return_to)
131
132 - def OnSetTitle(self, title):
133 "no-op" 134 pass
135
136 - def OnCellMouseHover(self, cell, x, y):
137 "no-op" 138 pass
139
140 - def OnOpeningURL(self, type, url):
141 "no-op" 142 pass
143
144 - def OnCellClicked(self, cell, x, y, evt):
145 linkinfo = cell.GetLink() 146 if linkinfo is not None: 147 pass 148 else: 149 pass 150 super(MyHtmlWindow, self).OnCellClicked(cell, x, y, evt)
151
152 - def incr_decr_font_size(self, change=None):
153 global options_dict 154 page_to_restore = self.GetParser().GetSource() 155 if change: 156 self.font_size += change 157 if self.font_size <= 0: self.font_size = 1 158 else: 159 self.font_size = self.normal_font_size 160 options_dict['font_size'] = self.font_size 161 self.SetStandardFonts(size=self.font_size) 162 self.SetPage(page_to_restore)
163
164 - def show_msg(self, msg):
165 msg1 = '*'*8 + ' ' + msg + ' ' + '*'*8 166 msg2 = '*'*100 167 for i in range(5): 168 for msg in [msg1, msg2]: 169 self.parent.parent.statusbar.SetStatusText(msg) 170 wx.Yield() 171 sleep(0.2) 172 self.parent.parent.statusbar.SetStatusText(' ') 173 wx.Yield()
174
175 - def show_page(self, page):
176 self.SetPage(page)
177 178 179 #----------------------------------------------------------------------------
180 -class NB(wx.Notebook):
181 - def __init__(self, parent):
182 wx.Notebook.__init__(self, parent, -1, size=(21,21), 183 style=wx.BK_DEFAULT) 184 185 self.parent = parent 186 self.add_html_page() 187 self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged) 188 self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGING, self.OnPageChanging)
189
190 - def OnPageChanged(self, event):
191 old = event.GetOldSelection() 192 new = event.GetSelection() 193 sel = self.GetSelection() 194 if old != new: # and self.current_page != new: 195 self.switch_html_page(new) 196 event.Skip()
197 198 # XXX: MAY remove three statments with no effect. */
199 - def OnPageChanging(self, event):
200 old = event.GetOldSelection() 201 new = event.GetSelection() 202 sel = self.GetSelection() 203 event.Skip()
204
205 - def switch_html_page(self, new_page):
206 self.current_page = new_page 207 self.ChangeSelection(new_page) 208 self.h_w = self.GetPage(new_page) 209 self.parent.prev_btn.Enable(self.h_w.prev_wp_list != []) 210 self.parent.next_btn.Enable(self.h_w.next_wp_list != []) 211 self.parent.search_word.SetValue(self.h_w.current_word)
212
213 - def add_html_page(self, tab_text='', activate=True):
214 h_w = MyHtmlWindow(self, -1) 215 if 'gtk2' in wx.PlatformInfo: 216 h_w.SetStandardFonts() 217 h_w.SetRelatedFrame(self.parent.frame, 218 self.parent.titleBase + ' -- %s') 219 h_w.SetRelatedStatusBar(0) 220 h_w.current_word = '' 221 # Init the word-page list for history browsing 222 h_w.prev_wp_list = [] 223 h_w.next_wp_list = [] 224 self.AddPage(h_w, tab_text, activate) 225 if activate: 226 self.current_page = self.GetSelection() 227 self.h_w = h_w 228 if self.h_w.prev_wp_list == []: 229 self.parent.prev_btn.Enable(False) 230 if self.h_w.next_wp_list == []: 231 self.parent.next_btn.Enable(False) 232 return self.current_page
233 234
235 -class HtmlPanel(wx.Panel):
236 - def __init__(self, frame):
237 wx.Panel.__init__(self, frame, -1, style=wx.NO_FULL_REPAINT_ON_RESIZE) 238 self.frame = frame 239 # XXX: MAY simplify setting self.cwdJust use os.getcwd(). */ 240 self.cwd = os.path.split(sys.argv[0])[0] 241 242 if not self.cwd: 243 self.cwd = os.getcwd() 244 if frame: 245 self.titleBase = frame.GetTitle() 246 247 self.statusbar = self.frame.CreateStatusBar() 248 249 self.printer = html.HtmlEasyPrinting(frame_title) 250 251 self.box = wx.BoxSizer(wx.VERTICAL) 252 253 subbox_1 = wx.BoxSizer(wx.HORIZONTAL) 254 255 self.prev_btn = wx.Button(self, -1, 'Previous Page') 256 self.Bind(wx.EVT_BUTTON, self.on_prev_page, self.prev_btn) 257 subbox_1.Add(self.prev_btn, 5, wx.GROW | wx.ALL, 2) 258 259 self.next_btn = wx.Button(self, -1, 'Next Page') 260 self.Bind(wx.EVT_BUTTON, self.on_next_page, self.next_btn) 261 subbox_1.Add(self.next_btn, 5, wx.GROW | wx.ALL, 2) 262 263 btn = wx.Button(self, -1, 'Help') 264 self.Bind(wx.EVT_BUTTON, self.on_help, btn) 265 subbox_1.Add(btn, 5, wx.GROW | wx.ALL, 2) 266 267 btn = wx.Button(self, -1, 'Search the word(s)') 268 self.Bind(wx.EVT_BUTTON, self.on_word_enter, btn) 269 subbox_1.Add(btn, 5, wx.GROW | wx.ALL, 2) 270 271 lbl = wx.StaticText(self, -1, 'Word(s): ', 272 style=wx.ALIGN_RIGHT|wx.ALIGN_BOTTOM) 273 subbox_1.Add(lbl, 5, wx.GROW | wx.ALL, 2) 274 275 self.search_word = wx.TextCtrl(self, -1, '', style=wx.TE_PROCESS_ENTER) 276 self.Bind(wx.EVT_TEXT_ENTER, self.on_word_enter, self.search_word) 277 self.search_word.Bind(wx.EVT_LEFT_UP, self.on_mouse_up) 278 subbox_1.Add(self.search_word, 20, wx.GROW | wx.ALL, 2) 279 280 self.box.Add(subbox_1, 0, wx.GROW) 281 self.nb = NB(self) 282 self.box.Add(self.nb, 1, wx.GROW) 283 284 self.SetSizer(self.box) 285 self.SetAutoLayout(True)
286
287 - def on_key_down(self, event):
288 event.Skip()
289
290 - def on_key_up(self, event):
291 event.Skip()
292
293 - def on_char(self, event):
294 event.Skip()
295
296 - def on_mouse_up(self, event):
297 self.search_word.SetSelection(-1, -1) 298 event.Skip()
299
300 - def on_prev_page(self, event):
301 if self.nb.h_w.prev_wp_list: 302 # Save current word&page&viewStart 303 page = self.nb.h_w.GetParser().GetSource() 304 x,y = self.nb.h_w.GetViewStart() 305 entry = (self.nb.h_w.current_word,page,(x,y)) 306 self.nb.h_w.next_wp_list = [entry] + self.nb.h_w.next_wp_list 307 self.next_btn.Enable(True) 308 # Restore previous word&page 309 word,page,(x,y) = self.nb.h_w.prev_wp_list[-1] 310 self.nb.h_w.prev_wp_list = self.nb.h_w.prev_wp_list[:-1] 311 if self.nb.h_w.prev_wp_list == []: 312 self.prev_btn.Enable(False) 313 self.nb.h_w.current_word = word 314 self.nb.SetPageText(self.nb.current_page, word) 315 self.search_word.SetValue(word) 316 self.nb.h_w.SetPage(page) 317 self.nb.h_w.Scroll(x, y)
318
319 - def on_next_page(self, event):
320 if self.nb.h_w.next_wp_list: 321 # Save current word&page&viewStart 322 page = self.nb.h_w.GetParser().GetSource() 323 x,y = self.nb.h_w.GetViewStart() 324 entry = (self.nb.h_w.current_word,page,(x,y)) 325 self.nb.h_w.prev_wp_list.append(entry) 326 self.prev_btn.Enable(True) 327 # Restore next word&page 328 word,page,(x,y) = self.nb.h_w.next_wp_list[0] 329 self.nb.h_w.next_wp_list = self.nb.h_w.next_wp_list[1:] 330 if self.nb.h_w.next_wp_list == []: 331 self.next_btn.Enable(False) 332 self.nb.h_w.current_word = word 333 self.nb.SetPageText(self.nb.current_page, word) 334 self.search_word.SetValue(word) 335 self.nb.h_w.SetPage(page) 336 self.nb.h_w.Scroll(x, y)
337
338 - def on_help(self, event):
339 self.frame.on_help_help(None)
340
341 - def on_word_change(self, event):
342 word = self.search_word.GetValue() 343 if word.isalnum(): return 344 word_2 = ''.join([x for x in word if 345 x.isalnum() or x == ' ' or x == '-']) 346 self.search_word.SetValue(word_2) 347 event.Skip()
348
349 - def on_word_enter(self, event):
350 if not self.nb.GetPageCount(): 351 self.frame.on_ssw_nt(None) 352 return 353 word = self.search_word.GetValue() 354 word = word.strip() 355 if word == '': return 356 word,body = new_word_and_body(word) 357 if word: 358 self.show_page_and_word(pg(word, body), word) 359 self.nb.h_w.current_word = word 360 self.nb.SetPageText(self.nb.current_page, word) 361 else: 362 self.nb.h_w.show_msg('The word was not found!')
363
364 - def show_page_and_word(self, page, word=None):
365 if self.nb.h_w.current_word: 366 # Save current word&page&viewStart 367 curr_page = self.nb.h_w.GetParser().GetSource() 368 x,y = self.nb.h_w.GetViewStart() 369 entry = (self.nb.h_w.current_word,curr_page,(x,y)) 370 self.nb.h_w.prev_wp_list.append(entry) 371 self.prev_btn.Enable(True) 372 # Clear forward history 373 self.nb.h_w.next_wp_list = [] 374 self.next_btn.Enable(False) 375 if not word: x,y = self.nb.h_w.GetViewStart() 376 self.nb.h_w.SetPage(page) 377 if not word: self.nb.h_w.Scroll(x, y) 378 if word: 379 self.search_word.SetValue(word) 380 self.nb.h_w.current_word = word
381 382
383 -class MyHtmlFrame(wx.Frame):
384 - def __init__(self, parent, title): #, pos, size)
385 wx.Frame.__init__(self, parent, -1, title)#, pos, size) 386 387 menu_bar = wx.MenuBar() 388 389 menu_1 = wx.Menu() 390 o_f = menu_1.Append(-1, 'Open File...\tCtrl+O') 391 s_a = menu_1.Append(-1, 'Save Page As...\tCtrl+S') 392 menu_1.AppendSeparator() 393 print_ = menu_1.Append(-1, 'Print...\tCtrl+P') 394 preview = menu_1.Append(-1, 'Preview') 395 menu_1.AppendSeparator() 396 ex = menu_1.Append(-1, 'Exit') 397 menu_bar.Append(menu_1, '&File') 398 399 menu_1_2 = wx.Menu() 400 nt = menu_1_2.Append(-1, 'New tabsheet\tCtrl+T') 401 ct = menu_1_2.Append(-1, 'Close tabsheet\tCtrl+W') 402 menu_1_2.AppendSeparator() 403 ssw_nt = menu_1_2.Append(-1, 404 'Show search word in new tabsheet\tAlt+Enter') 405 menu_bar.Append(menu_1_2, '&Tabsheets') 406 407 menu_2 = wx.Menu() 408 prev_p = menu_2.Append(-1, 'Previous\tCtrl+Left Arrow') 409 next_p = menu_2.Append(-1, 'Next\tCtrl+Right Arrow') 410 menu_bar.Append(menu_2, '&Page History') 411 412 menu_3 = wx.Menu() 413 i_f = menu_3.Append(-1, 414 'Increase Font Size\tCtrl++ or Ctrl+Numpad+ or Ctrl+UpArrow') 415 d_f = menu_3.Append(-1, 416 'Decrease Font Size\tCtrl+- or Ctrl+Numpad- or Ctrl+DownArrow') 417 n_f = menu_3.Append(-1, 'Normal Font Size\tCtrl+0') 418 menu_3.AppendSeparator() 419 # The Database Info File is not supported in this version. 420 # db_i = menu_3.Append(-1, 'Show Database Info') 421 # menu_3.AppendSeparator() 422 s_s = menu_3.Append(-1, 'Show HTML Source\tCtrl+U') 423 menu_bar.Append(menu_3, '&View') 424 425 menu_4 = wx.Menu() 426 h_h = menu_4.Append(-1, 'Help') 427 h_a = menu_4.Append(-1, 'About...') 428 menu_bar.Append(menu_4, '&Help') 429 430 self.SetMenuBar(menu_bar) 431 432 self.Bind(wx.EVT_MENU, self.on_open_file, o_f) 433 self.Bind(wx.EVT_MENU, self.on_save_as, s_a) 434 self.Bind(wx.EVT_MENU, self.on_print, print_) 435 self.Bind(wx.EVT_MENU, self.on_preview, preview) 436 self.Bind(wx.EVT_MENU, self.on_exit, ex) 437 self.Bind(wx.EVT_MENU, self.on_new_tab, nt) 438 self.Bind(wx.EVT_MENU, self.on_close_tab, ct) 439 self.Bind(wx.EVT_MENU, self.on_ssw_nt, ssw_nt) 440 self.Bind(wx.EVT_MENU, self.on_prev_page, prev_p) 441 self.Bind(wx.EVT_MENU, self.on_next_page, next_p) 442 self.Bind(wx.EVT_MENU, self.on_incr_font, i_f) 443 self.Bind(wx.EVT_MENU, self.on_decr_font, d_f) 444 self.Bind(wx.EVT_MENU, self.on_norm_font, n_f) 445 # The Database Info File is not supported in this version. 446 # self.Bind(wx.EVT_MENU, self.on_db_info, db_i) 447 self.Bind(wx.EVT_MENU, self.on_show_source, s_s) 448 self.Bind(wx.EVT_MENU, self.on_help_help, h_h) 449 self.Bind(wx.EVT_MENU, self.on_help_about, h_a) 450 451 acceltbl = wx.AcceleratorTable([ 452 (wx.ACCEL_CTRL,ord('O'),o_f.GetId()), 453 (wx.ACCEL_CTRL,ord('S'),s_a.GetId()), 454 (wx.ACCEL_CTRL,ord('P'),print_.GetId()), 455 (wx.ACCEL_CTRL,wx.WXK_ADD,i_f.GetId()), 456 (wx.ACCEL_CTRL,wx.WXK_NUMPAD_ADD,i_f.GetId()), 457 (wx.ACCEL_CTRL,wx.WXK_UP,i_f.GetId()), 458 (wx.ACCEL_CTRL,wx.WXK_SUBTRACT,d_f.GetId()), 459 (wx.ACCEL_CTRL,wx.WXK_NUMPAD_SUBTRACT,d_f.GetId()), 460 (wx.ACCEL_CTRL,wx.WXK_DOWN,d_f.GetId()), 461 (wx.ACCEL_CTRL,ord('0'),n_f.GetId()), 462 (wx.ACCEL_CTRL,ord('U'),s_s.GetId()), 463 (wx.ACCEL_ALT,wx.WXK_LEFT,prev_p.GetId()), 464 (wx.ACCEL_CTRL,wx.WXK_LEFT,prev_p.GetId()), 465 (wx.ACCEL_ALT,wx.WXK_RIGHT,next_p.GetId()), 466 (wx.ACCEL_CTRL,wx.WXK_RIGHT,next_p.GetId()), 467 (wx.ACCEL_ALT,wx.WXK_RETURN,ssw_nt.GetId()), 468 ]) 469 470 self.SetAcceleratorTable(acceltbl) 471 472 self.Bind(wx.EVT_SIZE, self.on_frame_resize) 473 self.Bind(wx.EVT_MOVE, self.on_frame_move) 474 self.Bind(wx.EVT_CLOSE, self.on_frame_close) 475 476 self.panel = HtmlPanel(self)
477 478
479 - def on_key_down(self, event):
480 event.Skip()
481
482 - def on_key_up(self, event):
483 event.Skip()
484
485 - def on_frame_close(self, event):
486 pos = self.GetPosition() 487 size = self.GetSize() 488 if pos == (-32000, -32000): # The frame is minimized, ignore pos 489 pos = (0,0) 490 options_dict['frame_pos'] = pos 491 options_dict['frame_size'] = size 492 if not os.access(nltk_prefs_dir, os.F_OK): 493 os.mkdir(nltk_prefs_dir) 494 pkl = open(pickle_file_name, 'wb') 495 pickle.dump(options_dict, pkl, -1) 496 pkl.close() 497 event.Skip()
498
499 - def on_frame_resize(self, event):
500 event.Skip()
501
502 - def on_frame_move(self, event):
503 event.Skip()
504
505 - def on_open_file(self, event):
506 self.load_file()
507
508 - def on_open_URL(self, event):
509 self.load_url()
510
511 - def on_save_as(self, event):
512 self.save_file()
513
514 - def on_print(self, event):
515 self.print_()
516
517 - def on_preview(self, event):
518 self.preview()
519
520 - def on_exit(self, event):
521 self.Close()
522
523 - def on_new_tab(self, event):
524 current_page = self.panel.nb.add_html_page()
525
526 - def on_close_tab(self, event):
527 self.panel.nb.DeletePage(self.panel.nb.current_page)
528
529 - def on_ol_ut(self, event):
530 pass
531
532 - def on_ol_ft(self, event):
533 pass
534
535 - def on_ssw_nt(self, event):
536 word = self.panel.search_word.GetValue() 537 if word == '': return 538 current_page = self.panel.nb.add_html_page() 539 word,body = new_word_and_body(word) 540 if word: 541 self.panel.show_page_and_word(pg(word, body), word) 542 self.panel.nb.h_w.current_word = word 543 self.panel.nb.SetPageText(current_page, word) 544 else: 545 self.panel.nb.h_w.show_msg('The word was not found!')
546
547 - def on_prev_page(self, event):
548 self.panel.on_prev_page(event)
549
550 - def on_next_page(self, event):
551 self.panel.on_next_page(event)
552
553 - def on_incr_font(self, event):
554 self.panel.nb.h_w.incr_decr_font_size(+1)
555
556 - def on_decr_font(self, event):
557 self.panel.nb.h_w.incr_decr_font_size(-1)
558
559 - def on_norm_font(self, event):
560 self.panel.nb.h_w.incr_decr_font_size()
561
562 - def on_db_info(self, event):
563 self.show_db_info()
564
565 - def on_show_source(self, event):
566 self.show_source()
567
568 - def on_help_help(self, event):
569 self.read_file('wx_help.html')
570
571 - def on_help_about(self, event):
572 wx.MessageBox(help_about)
573
574 - def show_db_info(self):
575 word = '* Database Info *' 576 current_page = self.panel.nb.add_html_page() 577 self.panel.nb.SetPageText(current_page,word) 578 try: 579 file = open(WORDNET_DB_INFO_FILEPATH) 580 html = file.read() 581 file.close() 582 except IOError: 583 # TODO: Should give instructions for using dbinfo_html.py 584 html = (html_header % word) + '<p>The database info file:'\ 585 '<p><b>%s</b>' % WORDNET_DB_INFO_FILEPATH + \ 586 '<p>was not found. Run the <b>dbinfo_html.py</b> ' + \ 587 'script to produce it.' + html_trailer 588 self.panel.show_page_and_word(html, word) 589 return
590 591 # These files need to be placed in a known location.
592 - def read_file(self, path):
593 try: 594 if not path.endswith('.htm') and not path.endswith('.html'): 595 path += '.html' 596 page = get_static_page_by_path(path) 597 if path == 'NLTK Wordnet Browser Help.html': 598 word = '* Help *' 599 else: 600 txt = '<title>' + frame_title + ' display of: ' 601 ind_0 = page.find(txt) 602 if ind_0 == -1: 603 err_mess = 'This file is not in NLTK Browser format!' 604 self.panel.nb.h_w.show_msg(err_mess) 605 return 606 ind_1 = page.find('of: ') + len('of: ') 607 ind_2 = page.find('</title>') 608 word = page[ind_1:ind_2] 609 page = page[:ind_0] + page[ind_2+len('</title>'):] 610 current_page = self.panel.nb.add_html_page() 611 self.panel.nb.SetPageText(current_page,word) 612 self.panel.show_page_and_word(page, word) 613 return current_page 614 except: 615 excpt = str(sys.exc_info()) 616 self.panel.nb.h_w.show_msg('Unexpected error; File: ' + \ 617 path + ' ; ' + excpt)
618
619 - def load_file(self):
620 dlg = wx.FileDialog(self, wildcard = '*.htm*', 621 style=wx.OPEN|wx.CHANGE_DIR) 622 if dlg.ShowModal(): 623 path = dlg.GetPath() 624 if path == '': return 625 self.read_file(path) 626 dlg.Destroy()
627
628 - def save_file(self):
629 dlg = wx.FileDialog(self, wildcard='*.html', 630 style=wx.SAVE|wx.CHANGE_DIR|wx.OVERWRITE_PROMPT) 631 if dlg.ShowModal(): 632 path = dlg.GetPath() 633 if path == '': 634 self.panel.nb.h_w.show_msg('Empty Filename!') 635 return 636 source = self.panel.nb.h_w.GetParser().GetSource() 637 try: 638 if not path.endswith('.htm') and not path.endswith('.html'): 639 path += '.html' 640 f = open(path, 'w') 641 f.write(source) 642 f.close() 643 except: 644 excpt = str(sys.exc_info()) 645 self.panel.nb.h_w.show_msg('Unexpected error; File: ' + \ 646 path + ' ; ' + excpt) 647 dlg.Destroy()
648
649 - def load_url(self):
650 dlg = wx.TextEntryDialog(self, 'Enter the URL') 651 if dlg.ShowModal(): 652 url = dlg.GetValue() 653 self.panel.nb.h_w.LoadPage(url) 654 dlg.Destroy()
655
656 - def show_source(self):
657 import wx.lib.dialogs 658 source = self.panel.nb.h_w.GetParser().GetSource() 659 dlg = wx.lib.dialogs.ScrolledMessageDialog(self, source, 660 'HTML Source', size=(1000, 800)) 661 dlg.ShowModal() 662 dlg.Destroy()
663
664 - def print_(self):
665 self.panel.printer.GetPrintData().SetFilename('unnamed') 666 html = self.panel.nb.h_w.GetParser().GetSource() 667 self.panel.printer.PrintText(html)
668
669 - def preview(self):
670 html = self.panel.nb.h_w.GetParser().GetSource() 671 self.panel.printer.PreviewText(html)
672
673 -def _initalize_options():
674 global options_dict 675 if os.path.exists(pickle_file_name): 676 pkl = open(pickle_file_name, 'rb') 677 options_dict = pickle.load(pkl) 678 pkl.close() 679 else: 680 options_dict = {} 681 if 'font_size' not in options_dict: 682 options_dict['font_size'] = 11 683 if 'frame_pos' not in options_dict: 684 options_dict['frame_pos'] = (-1,-1) 685 if 'frame_size' not in options_dict: 686 options_dict['frame_size'] = (-1,-1)
687
688 -def _adjust_pos_and_size(frame):
689 # Try to catch the screen dimensions like this because no better 690 # method is known i.e. start maximized, get the dims, adjust if 691 # pickled info requires 692 max_width,max_height = frame.GetSize() 693 x,y = frame.GetPosition() 694 # The following assumes that, as it seems, when wxPython frame 695 # is created maximized, it is symmetrically oversized the same 696 # amount of pixels. In my case (WinXP, wxPython 2.8) x==y==-4 697 # and the width and height are 8 pixels too large. In the 698 # frame init it is not possible to give negative values except 699 # (-1,-1) which has the special meaning of using the default! 700 if x < 0: 701 max_width += 2 * x 702 x = 0 703 if y < 0: 704 max_height += 2 * y 705 y = 0 706 # If no pos_size_info was found pickled, we're OK 707 if options_dict['frame_pos'] == (-1,-1): 708 return 709 # Now let's try to assure we've got sane values 710 x,y = options_dict['frame_pos'] 711 width,height = options_dict['frame_size'] 712 if x < 0: 713 width += x 714 x = 0 715 if y < 0: 716 height += y 717 y = 0 718 width = min(width, max_width) 719 height = min(height, max_height) 720 if x + width > max_width: 721 x -= x + width - max_width 722 if x < 0: 723 width += x 724 width = min(width, max_width) 725 x = 0 726 if y + height > max_height: 727 y -= y + height - max_height 728 if y < 0: 729 height += y 730 height = min(height, max_height) 731 y = 0 732 frame.Maximize(False) 733 frame.SetSize((width,height)) 734 frame.SetPosition((x,y)) 735 frame.Iconize(False)
736
737 -def get_static_wx_help_page():
738 """ 739 Return static WX help page. 740 """ 741 return \ 742 """ 743 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 744 <html> 745 <!-- Natural Language Toolkit: Wordnet Interface: Graphical Wordnet Browser 746 Copyright (C) 2001-2011 NLTK Project 747 Author: Jussi Salmela <jtsalmela@users.sourceforge.net> 748 URL: <http://www.nltk.org/> 749 For license information, see LICENSE.TXT --> 750 <head> 751 <meta http-equiv='Content-Type' content='text/html; charset=us-ascii'> 752 <title>NLTK Wordnet Browser display of: * Help *</title> 753 </head> 754 <body bgcolor='#F5F5F5' text='#000000'> 755 <h2>NLTK Wordnet Browser Help</h2> 756 <p>The NLTK Wordnet Browser is a tool to use in browsing the Wordnet database. It tries to behave like the Wordnet project's web browser but the difference is that the NLTK Wordnet Browser uses a local Wordnet database. The NLTK Wordnet Browser has only a part of normal browser functionality and it is <b>not</b> an Internet browser.</p> 757 <p>For background information on Wordnet, see the Wordnet project home page: <b>http://wordnet.princeton.edu/</b>. For more information on the NLTK project, see the project home: <b>http://nltk.sourceforge.net/</b>. To get an idea of what the Wordnet version used by this browser includes choose <b>Show Database Info</b> from the <b>View</b> submenu.</p> 758 <h3>The User Interface</h3> 759 <p>The user interface is a so called <b>notebook</b> interface. This 760 is familiar nowadays for almost everyone from Internet browsers, 761 for example. It consists of one or more independent pages often 762 (and here also) called <b>tabsheets</b>.</p> 763 <p>Every tabsheet contains its own search history which can be 764 browsed back and forth at will. The result of a new word search 765 will be shown on the currently active tabsheet if nothing else is 766 wanted. It is also possible to open a new tabsheet for the search 767 word given.</p> 768 <p>The position and size of the browser window as well as font size can be adjusted and the selections are retained between sessions.</p> 769 <h3>Word search</h3> 770 <p>The word to be searched is typed into the <b>Word(s):</b> field and the search started with Enter or by clicking the <b>Search the word(s)</b> button. There is no uppercase/lowercase distinction: the search word is transformed to lowercase before the search.</p> 771 <p>In addition, the word does not have to be in base form. The browser tries to find the possible base form(s) by making certain morphological substitutions. Typing <b>fLIeS</b> as an obscure example gives one <a href="MfLIeS">this</a>. Click the previous link to see what this kind of search looks like and then come back to this page by clicking the <b>Previous Page</b> button.</p> 772 <p>The result of a search is a display of one or more 773 <b>synsets</b> for every part of speech in which a form of the 774 search word was found to occur. A synset is a set of words 775 having the same sense or meaning. Each word in a synset that is 776 underlined is a hyperlink which can be clicked to trigger an 777 automatic search for that word.</p> 778 <p>Every synset has a hyperlink <b>S:</b> at the start of its 779 display line. Clicking that symbol shows you the name of every 780 <b>relation</b> that this synset is part of. Every relation name is a hyperlink that opens up a display for that relation. Clicking it another time closes the display again. Clicking another relation name on a line that has an opened relation closes the open relation and opens the clicked relation.</p> 781 <p>It is also possible to give two or more words or collocations to be searched at the same time separating them with a comma like this <a href="Mcheer up,clear up">cheer up,clear up</a>, for example. Click the previous link to see what this kind of search looks like and then come back to this page by clicking the <b>Previous Page</b> button. As you could see the search result includes the synsets found in the same order than the forms were given in the search field.</p> 782 <p> 783 There are also word level (lexical) relations recorded in the Wordnet database. Opening this kind of relation displays lines with a hyperlink <b>W:</b> at their beginning. Clicking this link shows more info on the word in question.</p> 784 <h3>Menu Structure</h3> 785 The browser has a menubar that you can use to invoke a set of 786 different operations. Most of the menu selections also have a 787 corresponding keyboard shortcut. 788 <h4>The File Menu</h4> 789 <p>Using the file menu you can <b>open</b> a previously saved NLTK 790 Wordnet Browser page. Note that only pages saved with this browser 791 can be read.</p> 792 <p>And as indicated above you can <b>save</b> a search page. The 793 resulting file is a normal HTML mode file which can be viewed, 794 printed etc. as any other HTML file.</p> 795 <p>You can also <b>print</b> a page and <b>preview</b> a page to be 796 printed. The selected printing settings are remembered during the 797 session.</p> 798 <h4>The Tabsheets Menu</h4> 799 <p>You can <b>open an empty tabsheet</b> and <b>close</b> the 800 currently active tabsheet.</p> 801 <p>When you enter a new search word in the search word field you 802 can make the search result be shown in a <b>new tabsheet</b>.</p> 803 <h4>Page History</h4> 804 You can browse the page history of the currently active tabsheet 805 either <b>forwards</b> or <b>backwards</b>. <b>Next Page</b> 806 browses towards the newer pages and <b>Previous Page</b> towards 807 the older pages. 808 <h4>The View Menu</h4> 809 <p>You can <b>increase</b>, <b>decrease</b> and <b>normalize</b> 810 the font size. The font size chosen is retained between 811 sessions.</p> 812 <p>You can choose <b>Show Database Info</b> to see the word, synset and relation counts by POS as well as one example word (as a hyperlink) for every relation&amp;POS pair occuring.</p> 813 <p>You can view the <b>HTML source</b> of a page if you are 814 curious.</p> 815 <h4>The Help Menu</h4> 816 You can view this <b>help text</b> as you already know. The 817 <b>about</b> selection tells you something about the program. 818 <h3>The Keyboard Shortcuts</h3> 819 <p>The following keyboard shortcuts can be used to quickly launch 820 the desired operation.</p> 821 <table border="1" cellpadding="1" cellspacing="1" summary=""> 822 <col align="center"> 823 <col align="center"> 824 <tr> 825 <th>Keyboard Shortcut</th> 826 <th>Operation</th> 827 </tr> 828 <tr> 829 <td>Ctrl+O</td> 830 <td>Open a file</td> 831 </tr> 832 <tr> 833 <td>Ctrl+S</td> 834 <td>Save current page as</td> 835 </tr> 836 <tr> 837 <td>Ctrl+P</td> 838 <td>Print current page</td> 839 </tr> 840 <tr> 841 <td>Ctrl+T</td> 842 <td>Open a new (empty) tabsheet</td> 843 </tr> 844 <tr> 845 <td>Ctrl+W</td> 846 <td>Close the current tabsheet</td> 847 </tr> 848 <tr> 849 <td>Ctrl+LinkClick</td> 850 <td>Open the link in a new unfocused tabsheet</td> 851 </tr> 852 <tr> 853 <td>Ctrl+Shift+LinkClick</td> 854 <td>Opent the link in a new focused tabsheet</td> 855 </tr> 856 <tr> 857 <td>Alt+Enter (1)</td> 858 <td>Show the word in search word field in a new tabsheet</td> 859 </tr> 860 <tr> 861 <td>Alt+LeftArrow</td> 862 <td>Previous page in page history</td> 863 </tr> 864 <tr> 865 <td>Ctrl+LeftArrow (2)</td> 866 <td>Previous page in page history</td> 867 </tr> 868 <tr> 869 <td>Alt+RightArrow</td> 870 <td>Next page in page history</td> 871 </tr> 872 <tr> 873 <td>Ctlr+RightArrow (2)</td> 874 <td>Next page in page history</td> 875 </tr> 876 <tr> 877 <td>Ctrl++/Ctrl+Numpad+/Ctrl+UpArrow (3)</td> 878 <td>Increase font size</td> 879 </tr> 880 <tr> 881 <td>Ctrl+-/Ctrl+Numpad-/Ctrl+DownArrow (3)</td> 882 <td>Decrease font size</td> 883 </tr> 884 <tr> 885 <td>Ctrl+0 (4)</td> 886 <td>Normal font size</td> 887 </tr> 888 <tr> 889 <td>Ctrl+U</td> 890 <td>Show HTML source</td> 891 </tr> 892 </table> 893 <dl> 894 <dt>(1)</dt> 895 <dd>This works only when the search word field is active i.e. the 896 caret is in it.</dd> 897 <dt>(2)</dt> 898 <dd>These are nonstandard combinations, the usual ones being 899 Alt+LeftArrow and Alt+RightArrow. These are still functional because there used to be difficulties with the standard ones earlier in the life of this program. Use these if the standard combinations do not work properly for you.</dd> 900 <dt>(3)</dt> 901 <dd>There are so many of these combinations because the usual i.e. 902 Ctrl++/Ctrl+- combinations did not work on the author's laptop and 903 the Numpad combinations were cumbersome to use. Hopefully the first 904 ones work on the computers of others.</dd> 905 <dt>(4)</dt> 906 <dd>This combination Ctrl+0 is "Ctrl+zero" not "Ctrl+ou".</dd> 907 </dl> 908 </body> 909 </html> 910 """
911
912 -def app():
913 global options_dict 914 915 app = wx.PySimpleApp() 916 _initalize_options() 917 frm = MyHtmlFrame(None, frame_title) #, -1, -1) 918 # Icon handling may not be portable - don't know 919 # This succeeds in Windows, so let's make it conditional 920 if platform.system() == 'Windows': 921 ico = wx.Icon('favicon.ico', wx.BITMAP_TYPE_ICO) 922 frm.SetIcon(ico) 923 word,body = new_word_and_body('green') 924 frm.panel.nb.SetPageText(0,word) 925 frm.panel.nb.h_w.current_word = word 926 frm.panel.search_word.SetValue(word) 927 body = explanation + body 928 frm.panel.nb.h_w.show_page(pg('green', body)) 929 page = frm.panel.nb.h_w.GetParser().GetSource() 930 page = frm.panel.nb.GetPage(0).GetParser().GetSource() 931 frm.Show() 932 frm.Maximize(True) 933 _adjust_pos_and_size(frm) 934 app.MainLoop()
935 936 937 if __name__ == '__main__': 938 app() 939 940 __all__ = ['app'] 941