help.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. """!
  2. @package help.py
  3. @brief Help window
  4. Classes:
  5. - HelpWindow
  6. - MenuTreeWindow
  7. - AboutWindow
  8. (C) 2008-2010 by the GRASS Development Team
  9. This program is free software under the GNU General Public License
  10. (>=v2). Read the file COPYING that comes with GRASS for details.
  11. @author Martin Landa <landa.martin gmail.com>
  12. """
  13. import os
  14. import wx
  15. try:
  16. import wx.lib.agw.customtreectrl as CT
  17. # import wx.lib.agw.hyperlink as hl
  18. except ImportError:
  19. import wx.lib.customtreectrl as CT
  20. # import wx.lib.hyperlink as hl
  21. import wx.lib.flatnotebook as FN
  22. import wx.lib.scrolledpanel as scrolled
  23. import menudata
  24. import gcmd
  25. import globalvar
  26. class HelpWindow(wx.Frame):
  27. """!GRASS Quickstart help window"""
  28. def __init__(self, parent, id, title, size, file):
  29. wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
  30. sizer = wx.BoxSizer(wx.VERTICAL)
  31. # text
  32. helpFrame = wx.html.HtmlWindow(parent=self, id=wx.ID_ANY)
  33. helpFrame.SetStandardFonts (size = 10)
  34. helpFrame.SetBorders(10)
  35. wx.InitAllImageHandlers()
  36. helpFrame.LoadFile(file)
  37. self.Ok = True
  38. sizer.Add(item=helpFrame, proportion=1, flag=wx.EXPAND)
  39. self.SetAutoLayout(True)
  40. self.SetSizer(sizer)
  41. # sizer.Fit(self)
  42. # sizer.SetSizeHints(self)
  43. self.Layout()
  44. class MenuTreeWindow(wx.Frame):
  45. """!Show menu tree"""
  46. def __init__(self, parent, id = wx.ID_ANY, title = _("Menu tree window"), **kwargs):
  47. self.parent = parent # LayerManager
  48. wx.Frame.__init__(self, parent = parent, id = id, title = title, **kwargs)
  49. self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
  50. self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
  51. self.dataBox = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
  52. label=" %s " % _("Menu tree (double-click to run command)"))
  53. # tree
  54. self.tree = MenuTree(parent = self.panel, data = menudata.ManagerData())
  55. self.tree.Load()
  56. self.searchDict = { _('label') : 'label', # i18n workaround
  57. _('help') : 'help',
  58. _('command') : 'command',
  59. _('keywords') : 'keywords' }
  60. # search
  61. self.searchBy = wx.Choice(parent = self.panel, id = wx.ID_ANY,
  62. choices = [_('label'),
  63. _('help'),
  64. _('command'),
  65. _('keywords')])
  66. self.searchBy.SetSelection(3)
  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. infoGridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  304. infoGridSizer.AddGrowableCol(0)
  305. infoGridSizer.AddGrowableCol(1)
  306. logo = os.path.join(globalvar.ETCDIR, "gui", "icons", "grass.ico")
  307. logoBitmap = wx.StaticBitmap(parent = infoTxt, id = wx.ID_ANY,
  308. bitmap = wx.Bitmap(name = logo,
  309. type = wx.BITMAP_TYPE_ICO))
  310. infoSizer.Add(item = logoBitmap, proportion = 0,
  311. flag = wx.ALL | wx.ALIGN_CENTER, border = 25)
  312. info = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
  313. label = version.replace('GRASS', 'GRASS GIS').strip() + '\n\n')
  314. info.SetFont(wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
  315. infoSizer.Add(item = info, proportion = 0,
  316. flag = wx.BOTTOM | wx.ALIGN_CENTER, border = 15)
  317. infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
  318. label = _('Official GRASS site:')),
  319. pos = (0, 0),
  320. flag = wx.ALIGN_RIGHT)
  321. infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
  322. label = 'http://grass.osgeo.org'),
  323. pos = (0, 1),
  324. flag = wx.ALIGN_LEFT)
  325. # infoGridSizer.Add(item = hl.HyperLinkCtrl(parent = self, id = wx.ID_ANY,
  326. # label = 'http://grass.osgeo.org',
  327. # URL = 'http://grass.osgeo.org'),
  328. # pos = (0, 1),
  329. # flag = wx.LEFT)
  330. infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
  331. label = _('GIS Library Revision:')),
  332. pos = (2, 0),
  333. flag = wx.ALIGN_RIGHT)
  334. infoGridSizer.Add(item = wx.StaticText(parent = infoTxt, id = wx.ID_ANY,
  335. label = svn_gis_h_rev.split(' ')[1] + ' (' +
  336. svn_gis_h_date.split(' ')[1] + ')'),
  337. pos = (2, 1),
  338. flag = wx.ALIGN_LEFT)
  339. infoSizer.Add(item = infoGridSizer,
  340. proportion = 1,
  341. flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER | wx.ALIGN_CENTER_VERTICAL,
  342. border = 25)
  343. #
  344. # create pages
  345. #
  346. copyrightwin = self.PageCopyright()
  347. licensewin = self.PageLicense()
  348. authorwin = self.PageCredit()
  349. contribwin = self.PageContributors()
  350. transwin = self.PageTranslators()
  351. # create a flat notebook for displaying information about GRASS
  352. nbstyle = FN.FNB_VC8 | \
  353. FN.FNB_BACKGROUND_GRADIENT | \
  354. FN.FNB_TABS_BORDER_SIMPLE | \
  355. FN.FNB_NO_X_BUTTON
  356. aboutNotebook = FN.FlatNotebook(panel, id=wx.ID_ANY, style=nbstyle)
  357. aboutNotebook.SetTabAreaColour(globalvar.FNPageColor)
  358. # make pages for About GRASS notebook
  359. pg1 = aboutNotebook.AddPage(infoTxt, text=_("Info"))
  360. pg2 = aboutNotebook.AddPage(copyrightwin, text=_("Copyright"))
  361. pg3 = aboutNotebook.AddPage(licensewin, text=_("License"))
  362. pg4 = aboutNotebook.AddPage(authorwin, text=_("Authors"))
  363. pg5 = aboutNotebook.AddPage(contribwin, text=_("Contributors"))
  364. pg5 = aboutNotebook.AddPage(transwin, text=_("Translators"))
  365. wx.CallAfter(aboutNotebook.SetSelection, 0)
  366. # buttons
  367. btnClose = wx.Button(parent = panel, id = wx.ID_CLOSE)
  368. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  369. btnSizer.Add(item = btnClose, proportion = 0,
  370. flag = wx.ALL | wx.ALIGN_RIGHT,
  371. border = 5)
  372. # bindings
  373. # self.aboutNotebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnAGPageChanged)
  374. btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
  375. infoTxt.SetSizer(infoSizer)
  376. infoSizer.Fit(infoTxt)
  377. sizer = wx.BoxSizer(wx.VERTICAL)
  378. sizer.Add(item=aboutNotebook, proportion=1,
  379. flag=wx.EXPAND | wx.ALL, border=1)
  380. sizer.Add(item=btnSizer, proportion=0,
  381. flag=wx.ALL | wx.ALIGN_RIGHT, border=1)
  382. panel.SetSizer(sizer)
  383. self.Layout()
  384. def PageCopyright(self):
  385. """Copyright information"""
  386. copyfile = os.path.join(os.getenv("GISBASE"), "COPYING")
  387. if os.path.exists(copyfile):
  388. copyrightFile = open(copyfile, 'r')
  389. copytext = copyrightFile.read()
  390. copyrightFile.close()
  391. else:
  392. copytext = _('%s file missing') % 'COPYING'
  393. # put text into a scrolling panel
  394. copyrightwin = scrolled.ScrolledPanel(self, id=wx.ID_ANY,
  395. size=wx.DefaultSize,
  396. style = wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER)
  397. copyrighttxt = wx.StaticText(copyrightwin, id=wx.ID_ANY, label=copytext)
  398. copyrightwin.SetAutoLayout(True)
  399. copyrightwin.sizer = wx.BoxSizer(wx.VERTICAL)
  400. copyrightwin.sizer.Add(item=copyrighttxt, proportion=1,
  401. flag=wx.EXPAND | wx.ALL, border=3)
  402. copyrightwin.SetSizer(copyrightwin.sizer)
  403. copyrightwin.Layout()
  404. copyrightwin.SetupScrolling()
  405. return copyrightwin
  406. def PageLicense(self):
  407. """Licence about"""
  408. licfile = os.path.join(os.getenv("GISBASE"), "GPL.TXT")
  409. if os.path.exists(licfile):
  410. licenceFile = open(licfile, 'r')
  411. license = ''.join(licenceFile.readlines())
  412. licenceFile.close()
  413. else:
  414. license = _('%s file missing') % 'GPL.TXT'
  415. # put text into a scrolling panel
  416. licensewin = scrolled.ScrolledPanel(self, id=wx.ID_ANY,
  417. style = wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER)
  418. licensetxt = wx.StaticText(licensewin, id=wx.ID_ANY, label=license)
  419. licensewin.SetAutoLayout(True)
  420. licensewin.sizer = wx.BoxSizer(wx.VERTICAL)
  421. licensewin.sizer.Add(item=licensetxt, proportion=1,
  422. flag=wx.EXPAND | wx.ALL, border=3)
  423. licensewin.SetSizer(licensewin.sizer)
  424. licensewin.Layout()
  425. licensewin.SetupScrolling()
  426. return licensewin
  427. def PageCredit(self):
  428. """Credit about"""
  429. # credits
  430. authfile = os.path.join(os.getenv("GISBASE"), "AUTHORS")
  431. if os.path.exists(authfile):
  432. authorsFile = open(authfile, 'r')
  433. authors = unicode(''.join(authorsFile.readlines()), "utf-8")
  434. authorsFile.close()
  435. else:
  436. authors = _('%s file missing') % 'AUTHORS'
  437. authorwin = scrolled.ScrolledPanel(self, id=wx.ID_ANY,
  438. style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
  439. authortxt = wx.StaticText(authorwin, id=wx.ID_ANY, label=authors)
  440. authorwin.SetAutoLayout(1)
  441. authorwin.SetupScrolling()
  442. authorwin.sizer = wx.BoxSizer(wx.VERTICAL)
  443. authorwin.sizer.Add(item=authortxt, proportion=1,
  444. flag=wx.EXPAND | wx.ALL, border=3)
  445. authorwin.SetSizer(authorwin.sizer)
  446. authorwin.Layout()
  447. return authorwin
  448. def PageContributors(self):
  449. """Contributors info"""
  450. contribfile = os.path.join(os.getenv("GISBASE"), "contributors.csv")
  451. if os.path.exists(contribfile):
  452. contribFile = open(contribfile, 'r')
  453. contribs = list()
  454. for line in contribFile.readlines():
  455. cvs_id, name, email, country, osgeo_id, rfc2_agreed = line.split(',')
  456. contribs.append((name, email, country, osgeo_id))
  457. contribs[0] = (_('Name'), _('E-mail'), _('Country'), _('OSGeo_ID'))
  458. contribFile.close()
  459. else:
  460. contribs = None
  461. contribwin = scrolled.ScrolledPanel(self, id=wx.ID_ANY,
  462. style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
  463. contribwin.SetAutoLayout(1)
  464. contribwin.SetupScrolling()
  465. contribwin.sizer = wx.BoxSizer(wx.VERTICAL)
  466. if not contribs:
  467. contribtxt = wx.StaticText(contribwin, id=wx.ID_ANY,
  468. label=_('%s file missing') % 'contibutors.csv')
  469. contribwin.sizer.Add(item=contribtxt, proportion=1,
  470. flag=wx.EXPAND | wx.ALL, border=3)
  471. else:
  472. contribBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
  473. for developer in contribs:
  474. for item in developer:
  475. contribBox.Add(item = wx.StaticText(parent = contribwin, id = wx.ID_ANY,
  476. label = item))
  477. contribwin.sizer.Add(item=contribBox, proportion=1,
  478. flag=wx.EXPAND | wx.ALL, border=3)
  479. contribwin.SetSizer(contribwin.sizer)
  480. contribwin.Layout()
  481. return contribwin
  482. def PageTranslators(self):
  483. """Translators info"""
  484. translatorsfile = os.path.join(os.getenv("GISBASE"), "translators.csv")
  485. if os.path.exists(translatorsfile):
  486. translatorsFile = open(translatorsfile, 'r')
  487. translators = dict()
  488. for line in translatorsFile.readlines()[1:]:
  489. name, email, languages = line.rstrip('\n').split(',')
  490. for language in languages.split(' '):
  491. if not translators.has_key(language):
  492. translators[language] = list()
  493. translators[language].append((name, email))
  494. translatorsFile.close()
  495. else:
  496. translators = None
  497. translatorswin = scrolled.ScrolledPanel(self, id=wx.ID_ANY,
  498. style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)
  499. translatorswin.SetAutoLayout(1)
  500. translatorswin.SetupScrolling()
  501. translatorswin.sizer = wx.BoxSizer(wx.VERTICAL)
  502. if not translators:
  503. translatorstxt = wx.StaticText(translatorswin, id=wx.ID_ANY,
  504. label=_('%s file missing') % 'translators.csv')
  505. translatorswin.sizer.Add(item=translatorstxt, proportion=1,
  506. flag=wx.EXPAND | wx.ALL, border=3)
  507. else:
  508. translatorsBox = wx.FlexGridSizer(cols=3, vgap=5, hgap=5)
  509. languages = translators.keys()
  510. languages.sort()
  511. translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
  512. label = _('Name')))
  513. translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
  514. label = _('E-mail')))
  515. translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
  516. label = _('Language')))
  517. for lang in languages:
  518. for translator in translators[lang]:
  519. name, email = translator
  520. translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
  521. label = unicode(name, "utf-8")))
  522. translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
  523. label = email))
  524. translatorsBox.Add(item = wx.StaticText(parent = translatorswin, id = wx.ID_ANY,
  525. label = lang))
  526. translatorswin.sizer.Add(item=translatorsBox, proportion=1,
  527. flag=wx.EXPAND | wx.ALL, border=3)
  528. translatorswin.SetSizer(translatorswin.sizer)
  529. translatorswin.Layout()
  530. return translatorswin
  531. def OnCloseWindow(self, event):
  532. """!Close window"""
  533. self.Close()