catalog.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. """
  2. @package datacatalog::catalog
  3. @brief Data catalog
  4. Classes:
  5. - datacatalog::DataCatalog
  6. (C) 2014-2018 by Tereza Fiedlerova, and the GRASS Development Team
  7. This program is free software under the GNU General Public
  8. License (>=v2). Read the file COPYING that comes with GRASS
  9. for details.
  10. @author Tereza Fiedlerova
  11. @author Linda Kladivova l.kladivova@seznam.cz
  12. """
  13. import wx
  14. import os
  15. from core.debug import Debug
  16. from datacatalog.tree import DataCatalogTree
  17. from datacatalog.toolbars import DataCatalogToolbar
  18. from gui_core.infobar import InfoBar
  19. from datacatalog.infomanager import DataCatalogInfoManager
  20. from gui_core.wrap import Menu
  21. from gui_core.forms import GUI
  22. from grass.script import gisenv
  23. from grass.pydispatch.signal import Signal
  24. from grass.grassdb.manage import split_mapset_path
  25. from grass.grassdb.checks import (get_reason_id_mapset_not_usable,
  26. is_fallback_session,
  27. is_first_time_user)
  28. class DataCatalog(wx.Panel):
  29. """Data catalog panel"""
  30. def __init__(self, parent, giface=None, id=wx.ID_ANY,
  31. title=_("Data catalog"), name='catalog', **kwargs):
  32. """Panel constructor """
  33. self.showNotification = Signal('DataCatalog.showNotification')
  34. self.parent = parent
  35. self.baseTitle = title
  36. self.giface = giface
  37. wx.Panel.__init__(self, parent=parent, id=id, **kwargs)
  38. self.SetName("DataCatalog")
  39. Debug.msg(1, "DataCatalog.__init__()")
  40. # toolbar
  41. self.toolbar = DataCatalogToolbar(parent=self)
  42. # tree with layers
  43. self.tree = DataCatalogTree(self, giface=giface)
  44. self.tree.showNotification.connect(self.showNotification)
  45. # infobar for data catalog
  46. delay = 2000
  47. self.infoBar = InfoBar(self)
  48. self.giface.currentMapsetChanged.connect(self.dismissInfobar)
  49. # infobar manager for data catalog
  50. self.infoManager = DataCatalogInfoManager(infobar=self.infoBar,
  51. giface=self.giface)
  52. self.tree.showImportDataInfo.connect(self.showImportDataInfo)
  53. # some layout
  54. self._layout()
  55. # show infobar for first-time user if applicable
  56. if is_first_time_user():
  57. # show data structure infobar for first-time user
  58. wx.CallLater(delay, self.showDataStructureInfo)
  59. # show infobar if last used mapset is not usable
  60. if is_fallback_session():
  61. # get reason why last used mapset is not usable
  62. last_mapset_path = gisenv()["LAST_MAPSET_PATH"]
  63. self.reason_id = get_reason_id_mapset_not_usable(last_mapset_path)
  64. if self.reason_id in ("non-existent", "invalid", "different-owner"):
  65. # show non-standard situation info
  66. wx.CallLater(delay, self.showFallbackSessionInfo)
  67. elif self.reason_id == "locked":
  68. # show info allowing to switch to locked mapset
  69. wx.CallLater(delay, self.showLockedMapsetInfo)
  70. def _layout(self):
  71. """Do layout"""
  72. sizer = wx.BoxSizer(wx.VERTICAL)
  73. sizer.Add(self.toolbar, proportion=0, flag=wx.EXPAND)
  74. sizer.Add(self.infoBar, proportion=0, flag=wx.EXPAND)
  75. sizer.Add(self.tree.GetControl(), proportion=1, flag=wx.EXPAND)
  76. self.SetAutoLayout(True)
  77. self.SetSizer(sizer)
  78. self.Fit()
  79. self.Layout()
  80. def showDataStructureInfo(self):
  81. self.infoManager.ShowDataStructureInfo(self.OnCreateLocation)
  82. def showLockedMapsetInfo(self):
  83. self.infoManager.ShowLockedMapsetInfo(self.OnSwitchToLastUsedMapset)
  84. def showFallbackSessionInfo(self):
  85. self.infoManager.ShowFallbackSessionInfo(self.reason_id)
  86. def showImportDataInfo(self):
  87. self.infoManager.ShowImportDataInfo(self.OnImportOgrLayers, self.OnImportGdalLayers)
  88. def LoadItems(self):
  89. self.tree.ReloadTreeItems()
  90. def dismissInfobar(self):
  91. if self.infoBar.IsShown():
  92. self.infoBar.Dismiss()
  93. def OnReloadTree(self, event):
  94. """Reload whole tree"""
  95. self.LoadItems()
  96. def OnReloadCurrentMapset(self, event):
  97. """Reload current mapset tree only"""
  98. self.tree.ReloadCurrentMapset()
  99. def OnAddGrassDB(self, event):
  100. """Add grass database"""
  101. dlg = wx.DirDialog(self, _("Choose GRASS data directory:"),
  102. os.getcwd(), wx.DD_DEFAULT_STYLE)
  103. if dlg.ShowModal() == wx.ID_OK:
  104. grassdatabase = dlg.GetPath()
  105. grassdb_node = self.tree.InsertGrassDb(name=grassdatabase)
  106. # Offer to create a new location
  107. if grassdb_node and not os.listdir(grassdatabase):
  108. message = _("Do you want to create a location?")
  109. dlg2 = wx.MessageDialog(self,
  110. message=message,
  111. caption=_("Create location?"),
  112. style=wx.YES_NO | wx.YES_DEFAULT |
  113. wx.ICON_QUESTION)
  114. if dlg2.ShowModal() == wx.ID_YES:
  115. self.tree.CreateLocation(grassdb_node)
  116. dlg2.Destroy()
  117. dlg.Destroy()
  118. def OnCreateMapset(self, event):
  119. """Create new mapset in current location"""
  120. db_node, loc_node, mapset_node = self.tree.GetCurrentDbLocationMapsetNode()
  121. self.tree.CreateMapset(db_node, loc_node)
  122. def OnCreateLocation(self, event):
  123. """Create new location"""
  124. db_node, loc_node, mapset_node = self.tree.GetCurrentDbLocationMapsetNode()
  125. self.tree.CreateLocation(db_node)
  126. def OnDownloadLocation(self, event):
  127. """Download location to current grass database"""
  128. db_node, loc_node, mapset_node = self.tree.GetCurrentDbLocationMapsetNode()
  129. self.tree.DownloadLocation(db_node)
  130. def OnSwitchToLastUsedMapset(self, event):
  131. """Switch to last used mapset"""
  132. last_mapset_path = gisenv()["LAST_MAPSET_PATH"]
  133. grassdb, location, mapset = split_mapset_path(last_mapset_path)
  134. self.tree.SwitchMapset(grassdb, location, mapset)
  135. def OnImportGdalLayers(self, event):
  136. """Convert multiple GDAL layers to GRASS raster map layers"""
  137. from modules.import_export import GdalImportDialog
  138. dlg = GdalImportDialog(parent=self, giface=self.giface)
  139. dlg.CentreOnScreen()
  140. dlg.Show()
  141. def OnImportOgrLayers(self, event):
  142. """Convert multiple OGR layers to GRASS vector map layers"""
  143. from modules.import_export import OgrImportDialog
  144. dlg = OgrImportDialog(parent=self, giface=self.giface)
  145. dlg.CentreOnScreen()
  146. dlg.Show()
  147. def OnLinkGdalLayers(self, event):
  148. """Link multiple GDAL layers to GRASS raster map layers"""
  149. from modules.import_export import GdalImportDialog
  150. dlg = GdalImportDialog(parent=self, giface=self.giface, link=True)
  151. dlg.CentreOnScreen()
  152. dlg.Show()
  153. def OnLinkOgrLayers(self, event):
  154. """Links multiple OGR layers to GRASS vector map layers"""
  155. from modules.import_export import OgrImportDialog
  156. dlg = OgrImportDialog(parent=self, giface=self.giface, link=True)
  157. dlg.CentreOnScreen()
  158. dlg.Show()
  159. def OnRasterOutputFormat(self, event):
  160. """Set raster output format handler"""
  161. from modules.import_export import GdalOutputDialog
  162. dlg = GdalOutputDialog(parent=self, ogr=False)
  163. dlg.CentreOnScreen()
  164. dlg.Show()
  165. def OnVectorOutputFormat(self, event):
  166. """Set vector output format handler"""
  167. from modules.import_export import GdalOutputDialog
  168. dlg = GdalOutputDialog(parent=self, ogr=True)
  169. dlg.CentreOnScreen()
  170. dlg.Show()
  171. def GuiParseCommand(self, cmd):
  172. """Generic handler"""
  173. GUI(parent=self, giface=self.giface).ParseCommand(cmd=[cmd])
  174. def OnMoreOptions(self, event):
  175. self.giface.Help(entry="topic_import")
  176. def SetRestriction(self, restrict):
  177. """Allow editing other mapsets or restrict editing to current mapset"""
  178. self.tree.SetRestriction(restrict)
  179. def Filter(self, text, element=None):
  180. self.tree.Filter(text=text, element=element)
  181. def OnImportMenu(self, event):
  182. """Create popup menu for other import options"""
  183. # create submenu
  184. subMenu = Menu()
  185. subitem = wx.MenuItem(subMenu, wx.ID_ANY, _("Link external raster data [r.external]"))
  186. subMenu.AppendItem(subitem)
  187. self.Bind(wx.EVT_MENU, self.OnLinkGdalLayers, subitem)
  188. subitem = wx.MenuItem(subMenu, wx.ID_ANY, _("Link external vector data [v.external]"))
  189. subMenu.AppendItem(subitem)
  190. self.Bind(wx.EVT_MENU, self.OnLinkOgrLayers, subitem)
  191. subMenu.AppendSeparator()
  192. subitem = wx.MenuItem(subMenu, wx.ID_ANY, _("Set raster output format [r.external.out]"))
  193. subMenu.AppendItem(subitem)
  194. self.Bind(wx.EVT_MENU, self.OnRasterOutputFormat, subitem)
  195. subitem = wx.MenuItem(subMenu, wx.ID_ANY, _("Set vector output format [v.external.out]"))
  196. subMenu.AppendItem(subitem)
  197. self.Bind(wx.EVT_MENU, self.OnVectorOutputFormat, subitem)
  198. # create menu
  199. menu = Menu()
  200. item = wx.MenuItem(menu, wx.ID_ANY, _("Unpack GRASS raster map [r.unpack]"))
  201. menu.AppendItem(item)
  202. self.Bind(wx.EVT_MENU, lambda evt: self.GuiParseCommand('r.unpack'), item)
  203. item = wx.MenuItem(menu, wx.ID_ANY, _("Unpack GRASS vector map [v.unpack]"))
  204. menu.AppendItem(item)
  205. self.Bind(wx.EVT_MENU, lambda evt: self.GuiParseCommand('v.unpack'), item)
  206. menu.AppendSeparator()
  207. item = wx.MenuItem(menu, wx.ID_ANY, _("Create raster map from x,y,z data [r.in.xyz]"))
  208. menu.AppendItem(item)
  209. self.Bind(wx.EVT_MENU, lambda evt: self.GuiParseCommand('r.in.xyz'), item)
  210. item = wx.MenuItem(menu, wx.ID_ANY, _("Create vector map from x,y,z data [v.in.ascii]"))
  211. menu.AppendItem(item)
  212. self.Bind(wx.EVT_MENU, lambda evt: self.GuiParseCommand('v.in.ascii'), item)
  213. menu.AppendSeparator()
  214. menu.AppendMenu(wx.ID_ANY, _("Link external data"), subMenu)
  215. menu.AppendSeparator()
  216. item = wx.MenuItem(menu, wx.ID_ANY, _("More options..."))
  217. menu.AppendItem(item)
  218. self.Bind(wx.EVT_MENU, self.OnMoreOptions, item)
  219. self.PopupMenu(menu)
  220. menu.Destroy()