help.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. """!
  2. @package help.py
  3. @brief Help window
  4. @todo Needs improvements...
  5. Classes:
  6. - HelpWindow
  7. - MenuTreeWindow
  8. - AboutWindow
  9. (C) 2008-2009 by the GRASS Development Team
  10. This program is free software under the GNU General Public
  11. License (>=v2). Read the file COPYING that comes with GRASS
  12. for details.
  13. @author Martin Landa <landa.martin gmail.com>
  14. """
  15. import os
  16. import wx
  17. try:
  18. import wx.lib.agw.customtreectrl as CT
  19. except ImportError:
  20. import wx.lib.customtreectrl as CT
  21. import wx.lib.flatnotebook as FN
  22. import wx.lib.scrolledpanel as scrolled
  23. from wx.lib.wordwrap import wordwrap
  24. import menudata
  25. import gcmd
  26. import globalvar
  27. class HelpWindow(wx.Frame):
  28. """!GRASS Quickstart help window"""
  29. def __init__(self, parent, id, title, size, file):
  30. wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
  31. sizer = wx.BoxSizer(wx.VERTICAL)
  32. # text
  33. helpFrame = wx.html.HtmlWindow(parent=self, id=wx.ID_ANY)
  34. helpFrame.SetStandardFonts (size = 10)
  35. helpFrame.SetBorders(10)
  36. wx.InitAllImageHandlers()
  37. helpFrame.LoadFile(file)
  38. self.Ok = True
  39. sizer.Add(item=helpFrame, proportion=1, flag=wx.EXPAND)
  40. self.SetAutoLayout(True)
  41. self.SetSizer(sizer)
  42. # sizer.Fit(self)
  43. # sizer.SetSizeHints(self)
  44. self.Layout()
  45. class MenuTreeWindow(wx.Frame):
  46. """!Show menu tree"""
  47. def __init__(self, parent, id = wx.ID_ANY, title = _("Menu tree window"), **kwargs):
  48. self.parent = parent # LayerManager
  49. wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
  50. self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
  51. self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
  52. self.dataBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
  53. label=" %s " % _("Menu tree (double-click to run command)"))
  54. # tree
  55. self.tree = MenuTree(parent = self.panel, data = menudata.Data())
  56. self.tree.Load()
  57. self.searchDict = { _('label') : 'label', # i18n workaround
  58. _('help') : 'help',
  59. _('command') : 'command',
  60. _('keywords') : 'keywords' }
  61. # search
  62. self.searchBy = wx.Choice(parent = self.panel, id = wx.ID_ANY,
  63. choices = [_('label'),
  64. _('help'),
  65. _('command'),
  66. _('keywords')])
  67. self.search = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY,
  68. value = "", size = (-1, 25),
  69. style = wx.TE_PROCESS_ENTER)
  70. # statusbar
  71. self.statusbar = self.CreateStatusBar(number=1)
  72. # close on run
  73. self.closeOnRun = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
  74. label = _("Close dialog on run"))
  75. self.closeOnRun.SetValue(True)
  76. # buttons
  77. self.btnRun = wx.Button(self.panel, id = wx.ID_OK, label = _("Run"))
  78. self.btnRun.SetToolTipString(_("Run selected command"))
  79. self.btnRun.Enable(False)
  80. self.btnClose = wx.Button(self.panel, id = wx.ID_CLOSE)
  81. self.btnClose.SetToolTipString(_("Close dialog"))
  82. # bindings
  83. self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
  84. self.btnRun.Bind(wx.EVT_BUTTON, self.OnRun)
  85. self.search.Bind(wx.EVT_TEXT_ENTER, self.OnShowItem)
  86. self.search.Bind(wx.EVT_TEXT, self.OnUpdateStatusBar)
  87. self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnItemActivated)
  88. self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnItemSelected)
  89. self.__Layout()
  90. self.search.SetFocus()
  91. def __Layout(self):
  92. """!Do dialog layout"""
  93. sizer = wx.BoxSizer(wx.VERTICAL)
  94. # body
  95. dataSizer = wx.StaticBoxSizer(self.dataBox, wx.HORIZONTAL)
  96. dataSizer.Add(item = self.tree, proportion =1,
  97. flag = wx.EXPAND)
  98. # search
  99. searchSizer = wx.BoxSizer(wx.HORIZONTAL)
  100. searchSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
  101. label = _("Search:")),
  102. proportion = 0,
  103. flag = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
  104. border = 3)
  105. searchSizer.Add(item = self.searchBy, proportion = 0,
  106. flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT | wx.RIGHT,
  107. border = 5)
  108. searchSizer.Add(item = self.search, proportion = 1,
  109. flag = wx.EXPAND | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL,
  110. border = 5)
  111. # buttons
  112. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  113. btnSizer.Add(item = self.btnRun, proportion = 0,
  114. flag = wx.LEFT | wx.RIGHT, border = 5)
  115. btnSizer.Add(item = self.btnClose, proportion = 0,
  116. flag = wx.LEFT | wx.RIGHT, border = 5)
  117. sizer.Add(item = dataSizer, proportion = 1,
  118. flag = wx.EXPAND | wx.ALL, border = 5)
  119. sizer.Add(item = searchSizer, proportion=0,
  120. flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
  121. sizer.Add(item = btnSizer, proportion=0,
  122. flag = wx.ALIGN_RIGHT | wx.ALL, border = 5)
  123. sizer.Add(item = self.closeOnRun, proportion=0,
  124. flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
  125. self.panel.SetAutoLayout(True)
  126. self.panel.SetSizer(sizer)
  127. sizer.Fit(self.panel)
  128. self.Layout()
  129. self.SetSize((530, 370))
  130. def OnCloseWindow(self, event):
  131. """!Close window"""
  132. self.Destroy()
  133. def OnRun(self, event):
  134. """!Run selected command"""
  135. if not self.tree.GetSelected():
  136. return # should not happen
  137. data = self.tree.GetPyData(self.tree.GetSelected())
  138. if not data:
  139. return
  140. handler = 'self.parent.' + data['handler'].lstrip('self.')
  141. if data['handler'] == 'self.OnXTerm':
  142. wx.MessageBox(parent = self,
  143. message = _('You must run this command from the menu or command line',
  144. 'This command require an XTerm'),
  145. caption = _('Message'), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
  146. elif data['command']:
  147. eval(handler)(event = None, cmd = data['command'].split())
  148. else:
  149. eval(handler)(None)
  150. if self.closeOnRun.IsChecked():
  151. self.OnCloseWindow(None)
  152. def OnItemActivated(self, event):
  153. """!Item activated (double-click)"""
  154. item = event.GetItem()
  155. if not item or not item.IsOk():
  156. return
  157. data = self.tree.GetPyData(item)
  158. if not data or not data.has_key('command'):
  159. return
  160. self.tree.itemSelected = item
  161. self.OnRun(None)
  162. def OnItemSelected(self, event):
  163. """!Item selected"""
  164. item = event.GetItem()
  165. if not item or not item.IsOk():
  166. return
  167. data = self.tree.GetPyData(item)
  168. if not data or not data.has_key('command'):
  169. return
  170. if data['command']:
  171. label = data['command'] + ' -- ' + data['help']
  172. else:
  173. label = data['help']
  174. self.statusbar.SetStatusText(label, 0)
  175. def OnShowItem(self, event):
  176. """!Highlight first found item in menu tree"""
  177. if len(self.tree.itemsMarked) > 0:
  178. if self.tree.GetSelected():
  179. self.tree.ToggleItemSelection(self.tree.GetSelected())
  180. idx = self.tree.itemsMarked.index(self.tree.GetSelected()) + 1
  181. else:
  182. idx = 0
  183. try:
  184. self.tree.ToggleItemSelection(self.tree.itemsMarked[idx])
  185. self.tree.itemSelected = self.tree.itemsMarked[idx]
  186. self.tree.EnsureVisible(self.tree.itemsMarked[idx])
  187. except IndexError:
  188. self.tree.ToggleItemSelection(self.tree.itemsMarked[0]) # reselect first item
  189. self.tree.EnsureVisible(self.tree.itemsMarked[0])
  190. self.tree.itemSelected = self.tree.itemsMarked[0]
  191. else:
  192. for item in self.tree.root.GetChildren():
  193. self.tree.Collapse(item)
  194. itemSelected = self.tree.GetSelection()
  195. if itemSelected:
  196. self.tree.ToggleItemSelection(itemSelected)
  197. self.tree.itemSelected = None
  198. if self.tree.itemSelected:
  199. self.btnRun.Enable()
  200. else:
  201. self.btnRun.Enable(False)
  202. def OnUpdateStatusBar(self, event):
  203. """!Update statusbar text"""
  204. element = self.searchDict[self.searchBy.GetStringSelection()]
  205. self.tree.itemsMarked = self.SearchItems(element = element,
  206. value = event.GetString())
  207. self.tree.itemSelected = None
  208. nItems = len(self.tree.itemsMarked)
  209. if event.GetString():
  210. self.statusbar.SetStatusText(_("%d items match") % nItems, 0)
  211. else:
  212. self.statusbar.SetStatusText("", 0)
  213. event.Skip()
  214. def SearchItems(self, element, value):
  215. """!Search item
  216. @param element element index (see self.searchBy)
  217. @param value
  218. @return list of found tree items
  219. """
  220. items = list()
  221. if not value:
  222. return items
  223. item = self.tree.GetFirstChild(self.tree.root)[0]
  224. self.__ProcessItem(item, element, value, items)
  225. return items
  226. def __ProcessItem(self, item, element, value, listOfItems):
  227. """!Search items (used by SearchItems)
  228. @param item reference item
  229. @param listOfItems list of found items
  230. """
  231. while item and item.IsOk():
  232. subItem = self.tree.GetFirstChild(item)[0]
  233. if subItem:
  234. self.__ProcessItem(subItem, element, value, listOfItems)
  235. data = self.tree.GetPyData(item)
  236. if data and data.has_key(element) and \
  237. value.lower() in data[element].lower():
  238. listOfItems.append(item)
  239. item = self.tree.GetNextSibling(item)
  240. class MenuTree(CT.CustomTreeCtrl):
  241. """!Menu tree class"""
  242. def __init__(self, parent, data, id = wx.ID_ANY,
  243. ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS | \
  244. CT.TR_LINES_AT_ROOT | CT.TR_SINGLE,
  245. **kwargs):
  246. self.parent = parent
  247. self.menudata = data
  248. super(MenuTree, self).__init__(parent, id, ctstyle = ctstyle, **kwargs)
  249. self.root = self.AddRoot(_("Menu tree"))
  250. self.itemsMarked = [] # list of marked items
  251. self.itemSelected = None
  252. def Load(self, data = None):
  253. """!Load menu data tree
  254. @param data menu data (None to use self.menudata)
  255. """
  256. if not data:
  257. data = self.menudata
  258. self.itemsMarked = [] # list of marked items
  259. for eachMenuData in data.GetMenu():
  260. for label, items in eachMenuData:
  261. item = self.AppendItem(parentId = self.root,
  262. text = label.replace('&', ''))
  263. self.__AppendItems(item, items)
  264. def __AppendItems(self, item, data):
  265. """!Append items into tree (used by Load()
  266. @param item tree item (parent)
  267. @parent data menu data"""
  268. for eachItem in data:
  269. if len(eachItem) == 2:
  270. if eachItem[0]:
  271. itemSub = self.AppendItem(parentId = item,
  272. text = eachItem[0])
  273. self.__AppendItems(itemSub, eachItem[1])
  274. else:
  275. if eachItem[0]:
  276. itemNew = self.AppendItem(parentId = item,
  277. text = eachItem[0])
  278. data = { 'label' : eachItem[0],
  279. 'help' : eachItem[1],
  280. 'handler' : eachItem[2],
  281. 'command' : eachItem[3],
  282. 'keywords' : eachItem[4] }
  283. self.SetPyData(itemNew, data)
  284. def GetSelected(self):
  285. """!Get selected item"""
  286. return self.itemSelected
  287. class AboutWindow(wx.Frame):
  288. def __init__(self, parent):
  289. """!Create custom About Window
  290. @todo improve styling
  291. """
  292. wx.Frame.__init__(self, parent=parent, id=wx.ID_ANY, size=(550,400),
  293. title=_('About GRASS GIS'))
  294. panel = wx.Panel(parent = self, id = wx.ID_ANY)
  295. # icon
  296. self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
  297. # get version and web site
  298. version, svn_gis_h_rev, svn_gis_h_date = gcmd.RunCommand('g.version',
  299. flags = 'r',
  300. read = True).splitlines()
  301. infoTxt = wx.Panel(parent = panel, id = wx.ID_ANY)
  302. infoSizer = wx.BoxSizer(wx.VERTICAL)
  303. logo = os.path.join(globalvar.ETCDIR, "gui", "icons", "grass.ico")
  304. logoBitmap = wx.StaticBitmap(parent = infoTxt, id = wx.ID_ANY,
  305. bitmap = wx.Bitmap(name = logo,
  306. type = wx.BITMAP_TYPE_ICO))
  307. infoSizer.Add(item = logoBitmap, proportion = 0,
  308. flag = wx.ALL | wx.ALIGN_CENTER, border = 10)
  309. i = 0
  310. for label in [version.replace('GRASS', 'GRASS GIS').strip() + '\n\n',
  311. _('Official GRASS site: http://grass.osgeo.org') + '\n\n',
  312. _('GIS Library') + ' ' + svn_gis_h_rev + '(' + svn_gis_h_date.split(' ')[1] + ')']:
  313. info = wx.StaticText(parent = infoTxt,
  314. id = wx.ID_ANY,
  315. label = label)
  316. if i == 0:
  317. info.SetFont(wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
  318. infoSizer.Add(item = info, proportion = 0,
  319. flag = wx.TOP | wx.ALIGN_CENTER, border = 5)
  320. i += 1
  321. #
  322. # create pages
  323. #
  324. copyrightwin = self.PageCopyright()
  325. licensewin = self.PageLicense()
  326. authorwin = self.PageCredit()
  327. contribwin = self.PageContributors()
  328. transwin = self.PageTranslators()
  329. # create a flat notebook for displaying information about GRASS
  330. nbstyle = FN.FNB_VC8 | \
  331. FN.FNB_BACKGROUND_GRADIENT | \
  332. FN.FNB_TABS_BORDER_SIMPLE | \
  333. FN.FNB_NO_X_BUTTON
  334. aboutNotebook = FN.FlatNotebook(panel, id=wx.ID_ANY, style=nbstyle)
  335. aboutNotebook.SetTabAreaColour(globalvar.FNPageColor)
  336. # make pages for About GRASS notebook
  337. pg1 = aboutNotebook.AddPage(infoTxt, text=_("Info"))
  338. pg2 = aboutNotebook.AddPage(copyrightwin, text=_("Copyright"))
  339. pg3 = aboutNotebook.AddPage(licensewin, text=_("License"))
  340. pg4 = aboutNotebook.AddPage(authorwin, text=_("Authors"))
  341. pg5 = aboutNotebook.AddPage(contribwin, text=_("Contributors"))
  342. pg5 = aboutNotebook.AddPage(transwin, text=_("Translators"))
  343. wx.CallAfter(aboutNotebook.SetSelection, 0)
  344. # buttons
  345. btnClose = wx.Button(parent = panel, id = wx.ID_CLOSE)
  346. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  347. btnSizer.Add(item = btnClose, proportion = 0,
  348. flag = wx.ALL | wx.ALIGN_RIGHT,
  349. border = 5)
  350. # bindings
  351. # self.aboutNotebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnAGPageChanged)
  352. btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
  353. infoTxt.SetSizer(infoSizer)
  354. infoSizer.Fit(infoTxt)
  355. sizer = wx.BoxSizer(wx.VERTICAL)
  356. sizer.Add(item=aboutNotebook, proportion=1,
  357. flag=wx.EXPAND | wx.ALL, border=1)
  358. sizer.Add(item=btnSizer, proportion=0,
  359. flag=wx.ALL | wx.ALIGN_RIGHT, border=1)
  360. panel.SetSizer(sizer)
  361. self.Layout()
  362. def PageCopyright(self):
  363. """Copyright information"""
  364. copyfile = os.path.join(os.getenv("GISBASE"), "COPYING")
  365. if os.path.exists(copyfile):
  366. copyrightFile = open(copyfile, 'r')
  367. copytext = copyrightFile.read()
  368. copyrightFile.close()
  369. else:
  370. copytext = _('%s file missing') % 'COPYING'
  371. # put text into a scrolling panel
  372. copyrightwin = scrolled.ScrolledPanel(self, id=wx.ID_ANY,
  373. size=wx.DefaultSize,
  374. style = wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER)
  375. copyrighttxt = wx.StaticText(copyrightwin, id=wx.ID_ANY, label=copytext)
  376. copyrightwin.SetAutoLayout(True)
  377. copyrightwin.sizer = wx.BoxSizer(wx.VERTICAL)
  378. copyrightwin.sizer.Add(item=copyrighttxt, proportion=1,
  379. flag=wx.EXPAND | wx.ALL, border=3)
  380. copyrightwin.SetSizer(copyrightwin.sizer)
  381. copyrightwin.Layout()
  382. copyrightwin.SetupScrolling()
  383. return copyrightwin
  384. def PageLicense(self):
  385. """Licence about"""
  386. licfile = os.path.join(os.getenv("GISBASE"), "GPL.TXT")
  387. if os.path.exists(licfile):
  388. licenceFile = open(licfile, 'r')
  389. license = ''.join(licenceFile.readlines())
  390. licenceFile.close()
  391. else:
  392. license = _('%s file missing') % 'GPL.TXT'
  393. # put text into a scrolling panel
  394. licensewin = scrolled.ScrolledPanel(self, id=wx.ID_ANY,
  395. style = wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER)
  396. licensetxt = wx.StaticText(licensewin, id=wx.ID_ANY, label=license)
  397. licensewin.SetAutoLayout(True)
  398. licensewin.sizer = wx.BoxSizer(wx.VERTICAL)
  399. licensewin.sizer.Add(item=licensetxt, proportion=1,
  400. flag=wx.EXPAND | wx.ALL, border=3)
  401. licensewin.SetSizer(licensewin.sizer)
  402. licensewin.Layout()
  403. licensewin.SetupScrolling()
  404. return licensewin
  405. def PageCredit(self):
  406. """Credit about"""
  407. # credits
  408. authfile = os.path.join(os.getenv("GISBASE"), "AUTHORS")
  409. if os.path.exists(authfile):
  410. authorsFile = open(authfile, 'r')
  411. authors = unicode(''.join(authorsFile.readlines()), "utf-8")
  412. authorsFile.close()
  413. else:
  414. authors = _('%s file missing') % 'AUTHORS'
  415. authorwin = scrolled.ScrolledPanel(self, id=wx.ID_ANY,
  416. style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
  417. authortxt = wx.StaticText(authorwin, id=wx.ID_ANY, label=authors)
  418. authorwin.SetAutoLayout(1)
  419. authorwin.SetupScrolling()
  420. authorwin.sizer = wx.BoxSizer(wx.VERTICAL)
  421. authorwin.sizer.Add(item=authortxt, proportion=1,
  422. flag=wx.EXPAND | wx.ALL, border=3)
  423. authorwin.SetSizer(authorwin.sizer)
  424. authorwin.Layout()
  425. return authorwin
  426. def PageContributors(self):
  427. """Contributors info"""
  428. contribfile = os.path.join(os.getenv("GISBASE"), "contributors.csv")
  429. if os.path.exists(contribfile):
  430. contribFile = open(contribfile, 'r')
  431. contribs = list()
  432. for line in contribFile.readlines():
  433. cvs_id, name, email, country, osgeo_id, rfc2_agreed = line.split(',')
  434. contribs.append((name, email, country, osgeo_id))
  435. contribs[0] = (_('Name'), _('E-mail'), _('Country'), _('OSGeo_ID'))
  436. contribFile.close()
  437. else:
  438. contribs = None
  439. contribwin = scrolled.ScrolledPanel(self, id=wx.ID_ANY,
  440. style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
  441. contribwin.SetAutoLayout(1)
  442. contribwin.SetupScrolling()
  443. contribwin.sizer = wx.BoxSizer(wx.VERTICAL)
  444. if not contribs:
  445. contribtxt = wx.StaticText(contribwin, id=wx.ID_ANY,
  446. label=_('%s file missing') % 'contibutors.csv')
  447. contribwin.sizer.Add(item=contribtxt, proportion=1,
  448. flag=wx.EXPAND | wx.ALL, border=3)
  449. else:
  450. contribBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
  451. for developer in contribs:
  452. for item in developer:
  453. contribBox.Add(item = wx.StaticText(parent = contribwin, id = wx.ID_ANY,
  454. label = item))
  455. contribwin.sizer.Add(item=contribBox, proportion=1,
  456. flag=wx.EXPAND | wx.ALL, border=3)
  457. contribwin.SetSizer(contribwin.sizer)
  458. contribwin.Layout()
  459. return contribwin
  460. def PageTranslators(self):
  461. """Translators info"""
  462. translatorsfile = os.path.join(os.getenv("GISBASE"), "translators.csv")
  463. if os.path.exists(translatorsfile):
  464. translatorsFile = open(translatorsfile, 'r')
  465. translators = dict()
  466. for line in translatorsFile.readlines()[1:]:
  467. name, email, languages = line.rstrip('\n').split(',')
  468. for language in languages.split(' '):
  469. if not translators.has_key(language):
  470. translators[language] = list()
  471. translators[language].append((name, email))
  472. translatorsFile.close()
  473. else:
  474. translators = None
  475. translatorswin = scrolled.ScrolledPanel(self, id=wx.ID_ANY,
  476. style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
  477. translatorswin.SetAutoLayout(1)
  478. translatorswin.SetupScrolling()
  479. translatorswin.sizer = wx.BoxSizer(wx.VERTICAL)
  480. if not translators:
  481. translatorstxt = wx.StaticText(translatorswin, id=wx.ID_ANY,
  482. label=_('%s file missing') % 'translators.csv')
  483. translatorswin.sizer.Add(item=translatorstxt, proportion=1,
  484. flag=wx.EXPAND | wx.ALL, border=3)
  485. else:
  486. translatorsBox = wx.FlexGridSizer(cols=3, vgap=5, hgap=5)
  487. languages = translators.keys()
  488. languages.sort()
  489. translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
  490. label = _('Name')))
  491. translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
  492. label = _('E-mail')))
  493. translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
  494. label = _('Language')))
  495. for lang in languages:
  496. for translator in translators[lang]:
  497. name, email = translator
  498. translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
  499. label = unicode(name, "utf-8")))
  500. translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
  501. label = email))
  502. translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
  503. label = lang))
  504. translatorswin.sizer.Add(item=translatorsBox, proportion=1,
  505. flag=wx.EXPAND | wx.ALL, border=3)
  506. translatorswin.SetSizer(translatorswin.sizer)
  507. translatorswin.Layout()
  508. return translatorswin
  509. def OnCloseWindow(self, event):
  510. """!Close window"""
  511. self.Close()