test_mapdisp.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. #!/usr/bin/env python
  2. ############################################################################
  3. #
  4. # MODULE: Map window and mapdisplay test module
  5. # AUTHOR(S): Vaclav Petras
  6. # PURPOSE: Test functionality using small GUI applications.
  7. # COPYRIGHT: (C) 2013 by Vaclav Petras, and the GRASS Development Team
  8. #
  9. # This program is free software; you can redistribute it and/or modify
  10. # it under the terms of the GNU General Public License as published by
  11. # the Free Software Foundation; either version 2 of the License, or
  12. # (at your option) any later version.
  13. #
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. # GNU General Public License for more details.
  18. #
  19. ############################################################################
  20. #%module
  21. #% description: Georectifies a map and allows to manage Ground Control Points.
  22. #% keywords: general
  23. #% keywords: GUI
  24. #% keywords: georectification
  25. #%end
  26. #%option
  27. #% key: test
  28. #% description: Test to run
  29. #% options: mapwindow,mapdisplay,apitest,distance,profile
  30. #% descriptions: mapwindow;Opens map window ;mapdisplay;Opens map display; apitest;Open an application to test API of map window; distance;Starts map window with distance measurement activated; profile;Starts map window with profile tool activated
  31. #% required: yes
  32. #%end
  33. #%option G_OPT_R_INPUT
  34. #% key: raster
  35. #% multiple: yes
  36. #% required: no
  37. #%end
  38. #%option G_OPT_V_INPUT
  39. #% key: vector
  40. #% multiple: yes
  41. #% required: no
  42. #%end
  43. """
  44. Module to run test map window (BufferedWidnow) and map display (MapFrame).
  45. @author Vaclav Petras <wenzeslaus gmail.com>
  46. """
  47. import os
  48. import sys
  49. import wx
  50. import grass.script as grass
  51. # adding a path to wxGUI modules
  52. if __name__ == '__main__':
  53. WXGUIBASE = os.path.join(os.getenv('GISBASE'), 'etc', 'gui', 'wxpython')
  54. if WXGUIBASE not in sys.path:
  55. sys.path.append(WXGUIBASE)
  56. import core.utils as utils
  57. from core.utils import _
  58. from core.settings import UserSettings
  59. from core.globalvar import CheckWxVersion
  60. from core.giface import StandaloneGrassInterface
  61. from mapwin.base import MapWindowProperties
  62. from mapwin.buffered import BufferedMapWindow
  63. from core.render import Map
  64. from rlisetup.sampling_frame import RLiSetupMapPanel
  65. # TODO: same classes as in dmon
  66. class Layer(object):
  67. def __init__(self, maplayer):
  68. self._maplayer = maplayer
  69. def __getattr__(self, name):
  70. if name == 'cmd':
  71. return utils.CmdTupleToList(self._maplayer.GetCmd())
  72. elif hasattr(self._maplayer, name):
  73. return getattr(self._maplayer, name)
  74. elif name == 'maplayer':
  75. return self._maplayer
  76. elif name == 'type':
  77. return self._maplayer.GetType()
  78. #elif name == 'ctrl':
  79. elif name == 'label':
  80. return self._maplayer.GetName()
  81. #elif name == 'maplayer' : None,
  82. #elif name == 'propwin':
  83. class LayerList(object):
  84. def __init__(self, map_):
  85. self._map = map_
  86. def GetSelectedLayers(self, checkedOnly=True):
  87. # hidden and selected vs checked and selected
  88. items = self._map.GetListOfLayers()
  89. layers = []
  90. for item in items:
  91. layer = Layer(item)
  92. layers.append(layer)
  93. return layers
  94. class MapdispGrassInterface(StandaloneGrassInterface):
  95. """!@implements GrassInterface"""
  96. def __init__(self, map_):
  97. StandaloneGrassInterface.__init__(self)
  98. self._map = map_
  99. self.mapWindow = None
  100. def GetLayerList(self):
  101. return LayerList(self._map)
  102. def GetMapWindow(self):
  103. return self.mapWindow
  104. # this is a copy of method from some frame class
  105. def copyOfInitMap(map_, width, height):
  106. """!Initialize map display, set dimensions and map region
  107. """
  108. if not grass.find_program('g.region', '--help'):
  109. sys.exit(_("GRASS module '%s' not found. Unable to start map "
  110. "display window.") % 'g.region')
  111. map_.ChangeMapSize((width, height))
  112. map_.region = map_.GetRegion() # g.region -upgc
  113. # self.Map.SetRegion() # adjust region to match display window
  114. class TextShower(object):
  115. def __init__(self, parent, title):
  116. self._cf = wx.Frame(parent=parent, title=title)
  117. self._cp = wx.Panel(parent=self._cf, id=wx.ID_ANY)
  118. self._cs = wx.BoxSizer(wx.VERTICAL)
  119. self._cl = wx.StaticText(parent=self._cp, id=wx.ID_ANY, label="No text set yet")
  120. self._cs.Add(item=self._cl, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
  121. self._cp.SetSizer(self._cs)
  122. self._cp.Layout()
  123. self._cf.Show()
  124. def SetLabel(self, text):
  125. self._cl.SetLabel(text)
  126. class Tester(object):
  127. def _listenToAllMapWindowSignals(self, window):
  128. output = sys.stderr
  129. # will make bad thigs after it is closed but who cares
  130. coordinatesShower = TextShower(window, "Coordinates")
  131. window.zoomChanged.connect(lambda: output.write("zoomChanged\n"))
  132. window.zoomHistoryUnavailable.connect(lambda: output.write("zoomHistoryUnavailable\n"))
  133. window.zoomHistoryAvailable.connect(lambda: output.write("zoomHistoryAvailable\n"))
  134. window.mapQueried.connect(lambda: output.write("mapQueried\n"))
  135. window.mouseEntered.connect(lambda: output.write("mouseEntered\n"))
  136. window.mouseLeftUpPointer.connect(lambda: output.write("mouseLeftUpPointer\n"))
  137. window.mouseLeftUp.connect(lambda: output.write("mouseLeftUp\n"))
  138. window.mouseMoving.connect(lambda x, y: coordinatesShower.SetLabel("%s , %s" % (x, y)))
  139. window.mouseHandlerRegistered.connect(lambda: output.write("mouseHandlerRegistered\n"))
  140. window.mouseHandlerUnregistered.connect(lambda: output.write("mouseHandlerUnregistered\n"))
  141. def testMapWindow(self, giface, map_):
  142. self.frame = wx.Frame(parent=None, title=_("Map window test frame"))
  143. panel = wx.Panel(parent=self.frame, id=wx.ID_ANY)
  144. sizer = wx.BoxSizer(wx.VERTICAL)
  145. mapWindowProperties = MapWindowProperties()
  146. mapWindowProperties.setValuesFromUserSettings()
  147. width, height = self.frame.GetClientSize()
  148. copyOfInitMap(map_, width, height)
  149. window = BufferedMapWindow(parent=panel, giface=giface, Map=map_,
  150. properties=mapWindowProperties)
  151. sizer.Add(item=window, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
  152. panel.SetSizer(sizer)
  153. panel.Layout()
  154. self.frame.Show()
  155. def testMapDisplay(self, giface, map_):
  156. from mapdisp.frame import MapFrame
  157. # known issues (should be similar with d.mon):
  158. # * opening map in digitizer ends with: vdigit/toolbars.py:723: 'selection' referenced before assignment
  159. # * nviz start fails (closes window? segfaults?) after mapdisp/frame.py:306: 'NoneType' object has no attribute 'GetLayerNotebook'
  160. frame = MapFrame(parent=None, title=_("Map display test"),
  161. giface=giface, Map=map_)
  162. # this is questionable: how complete the giface when creating objects
  163. # which are in giface
  164. giface.mapWindow = frame.GetMapWindow()
  165. frame.GetMapWindow().ZoomToMap()
  166. frame.Show()
  167. def testMapWindowApi(self, giface, map_):
  168. self.frame = wx.Frame(parent=None, title=_("Map window API test frame"))
  169. panel = wx.Panel(parent=self.frame, id=wx.ID_ANY)
  170. sizer = wx.BoxSizer(wx.VERTICAL)
  171. mapWindowProperties = MapWindowProperties()
  172. mapWindowProperties.setValuesFromUserSettings()
  173. mapWindowProperties.showRegion = True
  174. width, height = self.frame.GetClientSize()
  175. copyOfInitMap(map_, width, height)
  176. window = BufferedMapWindow(parent=panel, giface=giface, Map=map_,
  177. properties=mapWindowProperties)
  178. giface.mapWindow = window
  179. sizer.Add(item=window, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
  180. panel.SetSizer(sizer)
  181. panel.Layout()
  182. window.ZoomToWind()
  183. from mapdisp.frame import MeasureController
  184. self.measureController = MeasureController(giface)
  185. self.measureController.StartMeasurement()
  186. self._listenToAllMapWindowSignals(window)
  187. self.frame.Show()
  188. def testMapWindowDistance(self, giface, map_):
  189. self.frame = wx.Frame(parent=None,
  190. title=_("Map window distance measurement test frame"))
  191. panel = wx.Panel(parent=self.frame, id=wx.ID_ANY)
  192. sizer = wx.BoxSizer(wx.VERTICAL)
  193. mapWindowProperties = MapWindowProperties()
  194. mapWindowProperties.setValuesFromUserSettings()
  195. mapWindowProperties.showRegion = True
  196. width, height = self.frame.GetClientSize()
  197. copyOfInitMap(map_, width, height)
  198. window = BufferedMapWindow(parent=panel, giface=giface, Map=map_,
  199. properties=mapWindowProperties)
  200. giface.mapWindow = window
  201. sizer.Add(item=window, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
  202. panel.SetSizer(sizer)
  203. panel.Layout()
  204. window.ZoomToWind()
  205. self._listenToAllMapWindowSignals(window)
  206. self.frame.Show()
  207. from mapwin.analysis import MeasureDistanceController
  208. self.controller = MeasureDistanceController(giface, window)
  209. self.controller.Start()
  210. def testMapWindowProfile(self, giface, map_):
  211. self.frame = wx.Frame(parent=None,
  212. title=_("Map window profile tool test frame"))
  213. panel = wx.Panel(parent=self.frame, id=wx.ID_ANY)
  214. sizer = wx.BoxSizer(wx.VERTICAL)
  215. mapWindowProperties = MapWindowProperties()
  216. mapWindowProperties.setValuesFromUserSettings()
  217. mapWindowProperties.showRegion = True
  218. width, height = self.frame.GetClientSize()
  219. copyOfInitMap(map_, width, height)
  220. window = BufferedMapWindow(parent=panel, giface=giface, Map=map_,
  221. properties=mapWindowProperties)
  222. giface.mapWindow = window
  223. sizer.Add(item=window, proportion=1, flag=wx.EXPAND | wx.ALL, border=5)
  224. panel.SetSizer(sizer)
  225. panel.Layout()
  226. window.ZoomToWind()
  227. self._listenToAllMapWindowSignals(window)
  228. self.frame.Show()
  229. from mapwin.analysis import ProfileController
  230. self.controller = ProfileController(giface, window)
  231. self.controller.Start()
  232. rasters = []
  233. for layer in giface.GetLayerList().GetSelectedLayers():
  234. if layer.maplayer.GetType() == 'raster':
  235. rasters.append(layer.maplayer.GetName())
  236. from wxplot.profile import ProfileFrame
  237. profileWindow = ProfileFrame(parent=self.frame,
  238. controller=self.controller,
  239. units=map_.projinfo['units'],
  240. rasterList=rasters)
  241. profileWindow.CentreOnParent()
  242. profileWindow.Show()
  243. # Open raster select dialog to make sure that a raster (and
  244. # the desired raster) is selected to be profiled
  245. profileWindow.OnSelectRaster(None)
  246. def testMapWindowRlisetup(self, map_):
  247. self.frame = wx.Frame(parent=None,
  248. title=_("Map window rlisetup test frame"))
  249. RLiSetupMapPanel(parent=self.frame, map_=map_)
  250. self.frame.Show()
  251. def main():
  252. """!Sets the GRASS display driver
  253. """
  254. driver = UserSettings.Get(group='display', key='driver', subkey='type')
  255. if driver == 'png':
  256. os.environ['GRASS_RENDER_IMMEDIATE'] = 'png'
  257. else:
  258. os.environ['GRASS_RENDER_IMMEDIATE'] = 'cairo'
  259. # TODO: message format should not be GUI
  260. # TODO: should messages here be translatable?
  261. # (for test its great, for translator not)
  262. options, flags = grass.parser()
  263. test = options['test']
  264. app = wx.PySimpleApp()
  265. if not CheckWxVersion([2, 9]):
  266. wx.InitAllImageHandlers()
  267. map_ = Map()
  268. if options['raster']:
  269. names = options['raster']
  270. for name in names.split(','):
  271. cmdlist = ['d.rast', 'map=%s' % name]
  272. map_.AddLayer(ltype='raster', command=cmdlist, active=True,
  273. name=name, hidden=False, opacity=1.0,
  274. render=True)
  275. if options['vector']:
  276. names = options['vector']
  277. for name in names.split(','):
  278. cmdlist = ['d.vect', 'map=%s' % name]
  279. map_.AddLayer(ltype='vector', command=cmdlist, active=True,
  280. name=name, hidden=False, opacity=1.0,
  281. render=True)
  282. giface = MapdispGrassInterface(map_=map_)
  283. tester = Tester()
  284. if test == 'mapwindow':
  285. tester.testMapWindow(giface, map_)
  286. elif test == 'mapdisplay':
  287. tester.testMapDisplay(giface, map_)
  288. elif test == 'apitest':
  289. tester.testMapWindowApi(giface, map_)
  290. elif test == 'distance':
  291. tester.testMapWindowDistance(giface, map_)
  292. elif test == 'profile':
  293. tester.testMapWindowProfile(giface, map_)
  294. elif test == 'rlisetup':
  295. tester.testMapWindowRlisetup(map_)
  296. else:
  297. # TODO: this should not happen but happens
  298. import grass.script as sgrass
  299. sgrass.fatal(_("Unknown value %s of test parameter." % test))
  300. app.MainLoop()
  301. if __name__ == '__main__':
  302. main()