Bläddra i källkod

wxGUI/datacatalog: Add new location action to database node in Data tab (#790)

* After clicking on database node, two options for creating new location are available (new empty and download).
* Adds standalone functions download_location_interactively(), create_location_interactively(), and import_file().
* Modernizes and clarifies new location name validation in location wizard.
Linda Kladivova 4 år sedan
förälder
incheckning
bccf537ecc

+ 41 - 4
gui/wxpython/datacatalog/tree.py

@@ -35,10 +35,12 @@ from gui_core.wrap import Menu
 from datacatalog.dialogs import CatalogReprojectionDialog
 from datacatalog.dialogs import CatalogReprojectionDialog
 from icons.icon import MetaIcon
 from icons.icon import MetaIcon
 from startup.guiutils import (create_mapset_interactively,
 from startup.guiutils import (create_mapset_interactively,
+                              create_location_interactively,
                               rename_mapset_interactively,
                               rename_mapset_interactively,
                               rename_location_interactively,
                               rename_location_interactively,
                               delete_mapset_interactively,
                               delete_mapset_interactively,
-                              delete_location_interactively)
+                              delete_location_interactively,
+                              download_location_interactively)
 
 
 from grass.pydispatch.signal import Signal
 from grass.pydispatch.signal import Signal
 
 
@@ -675,8 +677,8 @@ class DataCatalogTree(TreeView):
         location = self.selected_location[0]
         location = self.selected_location[0]
         try:
         try:
             mapset = create_mapset_interactively(self,
             mapset = create_mapset_interactively(self,
-                                        gisdbase.data['name'],
-                                        location.data['name'],)
+                                                 gisdbase.data['name'],
+                                                 location.data['name'])
             if mapset:
             if mapset:
                 self.InsertMapset(name=mapset,
                 self.InsertMapset(name=mapset,
                                   location_node=location)
                                   location_node=location)
@@ -686,6 +688,20 @@ class DataCatalogTree(TreeView):
                    message=_("Unable to create new mapset: %s") % e,
                    message=_("Unable to create new mapset: %s") % e,
                    showTraceback=False)
                    showTraceback=False)
 
 
+    def OnCreateLocation(self, event):
+        """
+        Location wizard started
+        """
+        grassdatabase, location, mapset = (
+            create_location_interactively(self,
+                                          self.selected_grassdb[0].data['name'])
+        )
+        if location is not None:
+            item = self._model.SearchNodes(name=grassdatabase, type='grassdb')
+            if not item:
+                self.InsertGrassDb(name=grassdatabase)
+            self.ReloadTreeItems()
+
     def OnRenameMapset(self, event):
     def OnRenameMapset(self, event):
         """
         """
         Rename selected mapset
         Rename selected mapset
@@ -972,8 +988,20 @@ class DataCatalogTree(TreeView):
                    message=_("Unable to delete location: %s") % e,
                    message=_("Unable to delete location: %s") % e,
                    showTraceback=False)
                    showTraceback=False)
 
 
+    def OnDownloadLocation(self, event):
+        """
+        Download location online
+        """
+        grassdatabase, location, mapset = download_location_interactively(
+                self, self.selected_grassdb[0].data['name']
+        )
+        if location:
+            self.ReloadTreeItems()
+
     def OnDisplayLayer(self, event):
     def OnDisplayLayer(self, event):
-        """Display layer in current graphics view"""
+        """
+        Display layer in current graphics view
+        """
         self.DisplayLayer()
         self.DisplayLayer()
 
 
     def DisplayLayer(self):
     def DisplayLayer(self):
@@ -1299,6 +1327,15 @@ class DataCatalogTree(TreeView):
     def _popupMenuGrassDb(self):
     def _popupMenuGrassDb(self):
         """Create popup menu for grass db"""
         """Create popup menu for grass db"""
         menu = Menu()
         menu = Menu()
+
+        item = wx.MenuItem(menu, wx.ID_ANY, _("&Create new location"))
+        menu.AppendItem(item)
+        self.Bind(wx.EVT_MENU, self.OnCreateLocation, item)
+
+        item = wx.MenuItem(menu, wx.ID_ANY, _("&Download sample location"))
+        menu.AppendItem(item)
+        self.Bind(wx.EVT_MENU, self.OnDownloadLocation, item)
+
         self.PopupMenu(menu)
         self.PopupMenu(menu)
         menu.Destroy()
         menu.Destroy()
 
 

+ 28 - 81
gui/wxpython/gis_set.py

@@ -32,19 +32,20 @@ from core import globalvar
 import wx
 import wx
 import wx.lib.mixins.listctrl as listmix
 import wx.lib.mixins.listctrl as listmix
 
 
-from core.gcmd import GMessage, GError, RunCommand
+from core.gcmd import GError, RunCommand
 from core.utils import GetListOfLocations, GetListOfMapsets
 from core.utils import GetListOfLocations, GetListOfMapsets
 from startup.utils import (
 from startup.utils import (
     get_lockfile_if_present, get_possible_database_path,
     get_lockfile_if_present, get_possible_database_path,
     create_database_directory)
     create_database_directory)
 from startup.guiutils import (SetSessionMapset,
 from startup.guiutils import (SetSessionMapset,
                               create_mapset_interactively,
                               create_mapset_interactively,
+                              create_location_interactively,
                               rename_mapset_interactively,
                               rename_mapset_interactively,
                               rename_location_interactively,
                               rename_location_interactively,
                               delete_mapset_interactively,
                               delete_mapset_interactively,
-                              delete_location_interactively)
+                              delete_location_interactively,
+                              download_location_interactively)
 import startup.guiutils as sgui
 import startup.guiutils as sgui
-from location_wizard.dialogs import RegionDef
 from gui_core.widgets import StaticWrapText
 from gui_core.widgets import StaticWrapText
 from gui_core.wrap import Button, ListCtrl, StaticText, StaticBox, \
 from gui_core.wrap import Button, ListCtrl, StaticText, StaticBox, \
     TextCtrl, BitmapFromImage
     TextCtrl, BitmapFromImage
@@ -231,7 +232,7 @@ class GRASSStartup(wx.Frame):
         self.bexit.Bind(wx.EVT_BUTTON, self.OnExit)
         self.bexit.Bind(wx.EVT_BUTTON, self.OnExit)
         self.bhelp.Bind(wx.EVT_BUTTON, self.OnHelp)
         self.bhelp.Bind(wx.EVT_BUTTON, self.OnHelp)
         self.bmapset.Bind(wx.EVT_BUTTON, self.OnCreateMapset)
         self.bmapset.Bind(wx.EVT_BUTTON, self.OnCreateMapset)
-        self.bwizard.Bind(wx.EVT_BUTTON, self.OnWizard)
+        self.bwizard.Bind(wx.EVT_BUTTON, self.OnCreateLocation)
 
 
         self.rename_location_button.Bind(wx.EVT_BUTTON, self.OnRenameLocation)
         self.rename_location_button.Bind(wx.EVT_BUTTON, self.OnRenameLocation)
         self.delete_location_button.Bind(wx.EVT_BUTTON, self.OnDeleteLocation)
         self.delete_location_button.Bind(wx.EVT_BUTTON, self.OnDeleteLocation)
@@ -535,76 +536,23 @@ class GRASSStartup(wx.Frame):
                 'your home directory. '
                 'your home directory. '
                 'Press Browse button to select the directory.'))
                 'Press Browse button to select the directory.'))
 
 
-    def OnWizard(self, event):
+    def OnCreateLocation(self, event):
         """Location wizard started"""
         """Location wizard started"""
-        from location_wizard.wizard import LocationWizard
-        gWizard = LocationWizard(parent=self,
-                                 grassdatabase=self.tgisdbase.GetValue())
-        if gWizard.location is not None:
-            self.tgisdbase.SetValue(gWizard.grassdatabase)
+        grassdatabase, location, mapset = (
+            create_location_interactively(self, self.gisdbase)
+        )
+        if location is not None:
+            self.OnSelectLocation(None)
+            self.lbmapsets.SetSelection(self.listOfMapsets.index(mapset))
+            self.bstart.SetFocus()
+            self.tgisdbase.SetValue(grassdatabase)
             self.OnSetDatabase(None)
             self.OnSetDatabase(None)
-            self.UpdateMapsets(os.path.join(self.gisdbase, gWizard.location))
+            self.UpdateMapsets(os.path.join(grassdatabase, location))
             self.lblocations.SetSelection(
             self.lblocations.SetSelection(
-                self.listOfLocations.index(
-                    gWizard.location))
+                self.listOfLocations.index(location))
             self.lbmapsets.SetSelection(0)
             self.lbmapsets.SetSelection(0)
-            self.SetLocation(self.gisdbase, gWizard.location, 'PERMANENT')
-            if gWizard.georeffile:
-                message = _("Do you want to import <%(name)s> to the newly created location?") % {
-                    'name': gWizard.georeffile}
-                dlg = wx.MessageDialog(parent=self, message=message, caption=_(
-                    "Import data?"), style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
-                dlg.CenterOnParent()
-                if dlg.ShowModal() == wx.ID_YES:
-                    self.ImportFile(gWizard.georeffile)
-                dlg.Destroy()
-            if gWizard.default_region:
-                defineRegion = RegionDef(self, location=gWizard.location)
-                defineRegion.CenterOnParent()
-                defineRegion.ShowModal()
-                defineRegion.Destroy()
-
-            if gWizard.user_mapset:
-                self.OnCreateMapset(event)
-
-    def ImportFile(self, filePath):
-        """Tries to import file as vector or raster.
-
-        If successfull sets default region from imported map.
-        """
-        RunCommand('db.connect', flags='c')
-        mapName = os.path.splitext(os.path.basename(filePath))[0]
-        vectors = RunCommand('v.in.ogr', input=filePath, flags='l',
-                             read=True)
-
-        wx.BeginBusyCursor()
-        wx.GetApp().Yield()
-        if vectors:
-            # vector detected
-            returncode, error = RunCommand(
-                'v.in.ogr', input=filePath, output=mapName, flags='e',
-                getErrorMsg=True)
-        else:
-            returncode, error = RunCommand(
-                'r.in.gdal', input=filePath, output=mapName, flags='e',
-                getErrorMsg=True)
-        wx.EndBusyCursor()
+            self.SetLocation(grassdatabase, location, mapset)
 
 
-        if returncode != 0:
-            GError(
-                parent=self,
-                message=_(
-                    "Import of <%(name)s> failed.\n"
-                    "Reason: %(msg)s") % ({
-                        'name': filePath,
-                        'msg': error}))
-        else:
-            GMessage(
-                message=_(
-                    "Data file <%(name)s> imported successfully. "
-                    "The location's default region was set from this imported map.") % {
-                    'name': filePath},
-                parent=self)
 
 
     # the event can be refactored out by using lambda in bind
     # the event can be refactored out by using lambda in bind
     def OnRenameMapset(self, event):
     def OnRenameMapset(self, event):
@@ -618,7 +566,7 @@ class GRASSStartup(wx.Frame):
             if newmapset:
             if newmapset:
                 self.OnSelectLocation(None)
                 self.OnSelectLocation(None)
                 self.lbmapsets.SetSelection(
                 self.lbmapsets.SetSelection(
-                        self.listOfMapsets.index(newmapset))
+                    self.listOfMapsets.index(newmapset))
         except Exception as e:
         except Exception as e:
             GError(parent=self,
             GError(parent=self,
                    message=_("Unable to rename mapset: %s") % e,
                    message=_("Unable to rename mapset: %s") % e,
@@ -634,7 +582,7 @@ class GRASSStartup(wx.Frame):
             if newlocation:
             if newlocation:
                 self.UpdateLocations(self.gisdbase)
                 self.UpdateLocations(self.gisdbase)
                 self.lblocations.SetSelection(
                 self.lblocations.SetSelection(
-                        self.listOfLocations.index(newlocation))
+                    self.listOfLocations.index(newlocation))
                 self.UpdateMapsets(newlocation)
                 self.UpdateMapsets(newlocation)
         except Exception as e:
         except Exception as e:
             GError(parent=self,
             GError(parent=self,
@@ -674,24 +622,23 @@ class GRASSStartup(wx.Frame):
                    showTraceback=False)
                    showTraceback=False)
 
 
     def OnDownloadLocation(self, event):
     def OnDownloadLocation(self, event):
-        """Download location online"""
-        from startup.locdownload import LocationDownloadDialog
-
-        loc_download = LocationDownloadDialog(parent=self, database=self.gisdbase)
-        loc_download.ShowModal()
-        location = loc_download.GetLocation()
+        """
+        Download location online
+        """
+        grassdatabase, location, mapset = download_location_interactively(
+            self, self.gisdbase
+        )
         if location:
         if location:
             # get the new location to the list
             # get the new location to the list
-            self.UpdateLocations(self.gisdbase)
+            self.UpdateLocations(grassdatabase)
             # seems to be used in similar context
             # seems to be used in similar context
-            self.UpdateMapsets(os.path.join(self.gisdbase, location))
+            self.UpdateMapsets(os.path.join(grassdatabase, location))
             self.lblocations.SetSelection(
             self.lblocations.SetSelection(
                 self.listOfLocations.index(location))
                 self.listOfLocations.index(location))
             # wizard does this as well, not sure if needed
             # wizard does this as well, not sure if needed
-            self.SetLocation(self.gisdbase, location, 'PERMANENT')
+            self.SetLocation(grassdatabase, location, mapset)
             # seems to be used in similar context
             # seems to be used in similar context
             self.OnSelectLocation(None)
             self.OnSelectLocation(None)
-        loc_download.Destroy()
 
 
     def UpdateLocations(self, dbase):
     def UpdateLocations(self, dbase):
         """Update list of locations"""
         """Update list of locations"""

+ 27 - 36
gui/wxpython/location_wizard/wizard.py

@@ -53,10 +53,11 @@ import wx.lib.scrolledpanel as scrolled
 from core import utils
 from core import utils
 from core.utils import cmp
 from core.utils import cmp
 from core.gcmd import RunCommand, GError, GMessage, GWarning
 from core.gcmd import RunCommand, GError, GMessage, GWarning
-from gui_core.widgets import GenericValidator
+from gui_core.widgets import GenericMultiValidator
 from gui_core.wrap import SpinCtrl, SearchCtrl, StaticText, \
 from gui_core.wrap import SpinCtrl, SearchCtrl, StaticText, \
     TextCtrl, Button, CheckBox, StaticBox, NewId, ListCtrl, HyperlinkCtrl
     TextCtrl, Button, CheckBox, StaticBox, NewId, ListCtrl, HyperlinkCtrl
 from location_wizard.dialogs import SelectTransformDialog
 from location_wizard.dialogs import SelectTransformDialog
+from startup.utils import location_exists
 
 
 from grass.script import decode
 from grass.script import decode
 from grass.script import core as grass
 from grass.script import core as grass
@@ -171,10 +172,11 @@ class DatabasePage(TitledPage):
         self.tgisdbase = self.MakeLabel(grassdatabase)
         self.tgisdbase = self.MakeLabel(grassdatabase)
         self.tlocation = self.MakeTextCtrl("newLocation", size=(400, -1))
         self.tlocation = self.MakeTextCtrl("newLocation", size=(400, -1))
         self.tlocation.SetFocus()
         self.tlocation.SetFocus()
+
+        checks = [(grass.legal_name, self._nameValidationFailed),
+                  (self._checkLocationNotExists, self._locationAlreadyExists)]
         self.tlocation.SetValidator(
         self.tlocation.SetValidator(
-            GenericValidator(
-                grass.legal_name,
-                self._nameValidationFailed))
+            GenericMultiValidator(checks))
         self.tlocTitle = self.MakeTextCtrl(size=(400, -1))
         self.tlocTitle = self.MakeTextCtrl(size=(400, -1))
 
 
         # text for required options
         # text for required options
@@ -255,15 +257,23 @@ class DatabasePage(TitledPage):
 
 
     def _nameValidationFailed(self, ctrl):
     def _nameValidationFailed(self, ctrl):
         message = _(
         message = _(
-            "Name <%(name)s> is not a valid name for location. "
-            "Please use only ASCII characters excluding %(chars)s "
-            "and space.") % {
-            'name': ctrl.GetValue(),
-            'chars': '/"\'@,=*~'}
-        GError(
-            parent=self,
-            message=message,
-            caption=_("Invalid location name"))
+            "Name '{}' is not a valid name for location. "
+            "Please use only ASCII characters excluding characters {} "
+            "and space.").format(ctrl.GetValue(), '/"\'@,=*~')
+        GError(parent=self, message=message, caption=_("Invalid name"))
+
+    def _checkLocationNotExists(self, text):
+        """Check whether user's input location exists or not."""
+        if location_exists(self.tgisdbase.GetLabel(), text):
+            return False
+        return True
+
+    def _locationAlreadyExists(self, ctrl):
+        message = _(
+            "Location '{}' already exists. Please consider using "
+            "another name for your location.").format(ctrl.GetValue())
+        GError(parent=self, message=message,
+               caption=_("Existing location path"))
 
 
     def OnChangeName(self, event):
     def OnChangeName(self, event):
         """Name for new location was changed"""
         """Name for new location was changed"""
@@ -287,21 +297,6 @@ class DatabasePage(TitledPage):
         dlg.Destroy()
         dlg.Destroy()
 
 
     def OnPageChanging(self, event=None):
     def OnPageChanging(self, event=None):
-        error = None
-        if os.path.isdir(
-            os.path.join(
-                self.tgisdbase.GetLabel(),
-                self.tlocation.GetValue())):
-            error = _("Location already exists in GRASS Database.")
-
-        if error:
-            GError(parent=self,
-                   message="%s <%s>.%s%s" % (_("Unable to create location"),
-                                             str(self.tlocation.GetValue()),
-                                             os.linesep,
-                                             error))
-            event.Veto()
-            return
 
 
         self.location = self.tlocation.GetValue()
         self.location = self.tlocation.GetValue()
         self.grassdatabase = self.tgisdbase.GetLabel()
         self.grassdatabase = self.tgisdbase.GetLabel()
@@ -600,7 +595,7 @@ class ItemList(ListCtrl,
         for column in columns:
         for column in columns:
             self.InsertColumn(i, column)
             self.InsertColumn(i, column)
             i += 1
             i += 1
-        
+
         self.EnableAlternateRowColours()
         self.EnableAlternateRowColours()
 
 
         if self.sourceData:
         if self.sourceData:
@@ -1482,6 +1477,7 @@ class WKTPage(TitledPage):
             if not nextButton.IsEnabled():
             if not nextButton.IsEnabled():
                 nextButton.Enable()
                 nextButton.Enable()
 
 
+
 class EPSGPage(TitledPage):
 class EPSGPage(TitledPage):
     """Wizard page for selecting EPSG code for
     """Wizard page for selecting EPSG code for
     setting coordinate system parameters"""
     setting coordinate system parameters"""
@@ -1489,7 +1485,7 @@ class EPSGPage(TitledPage):
     def __init__(self, wizard, parent):
     def __init__(self, wizard, parent):
         TitledPage.__init__(self, wizard, _("Select CRS from a list"))
         TitledPage.__init__(self, wizard, _("Select CRS from a list"))
 
 
-        self.sizer = wx.BoxSizer(wx.VERTICAL)  
+        self.sizer = wx.BoxSizer(wx.VERTICAL)
         searchBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
         searchBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
         epsglistBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
         epsglistBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
         informationBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
         informationBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
@@ -1982,7 +1978,7 @@ class CustomPage(TitledPage):
                 return
                 return
 
 
             # check for datum tranforms
             # check for datum tranforms
-            # FIXME: -t flag is a hack-around for trac bug #1849          
+            # FIXME: -t flag is a hack-around for trac bug #1849
             ret, out, err = RunCommand('g.proj',
             ret, out, err = RunCommand('g.proj',
                                        read=True, getErrorMsg=True,
                                        read=True, getErrorMsg=True,
                                        proj4=self.customstring,
                                        proj4=self.customstring,
@@ -2550,11 +2546,6 @@ class LocationWizard(wx.Object):
                             database))
                             database))
                     return None
                     return None
 
 
-            # change to new GISDbase directory
-            RunCommand('g.gisenv',
-                       parent=self.wizard,
-                       set='GISDBASE=%s' % database)
-
             wx.MessageBox(
             wx.MessageBox(
                 parent=self.wizard,
                 parent=self.wizard,
                 message=_(
                 message=_(

+ 118 - 0
gui/wxpython/startup/guiutils.py

@@ -24,6 +24,7 @@ import grass.script as gs
 from core import globalvar
 from core import globalvar
 from core.gcmd import GError, GMessage, DecodeString, RunCommand
 from core.gcmd import GError, GMessage, DecodeString, RunCommand
 from gui_core.dialogs import TextEntryDialog
 from gui_core.dialogs import TextEntryDialog
+from location_wizard.dialogs import RegionDef
 from gui_core.widgets import GenericMultiValidator
 from gui_core.widgets import GenericMultiValidator
 from startup.utils import (create_mapset, delete_mapset, delete_location,
 from startup.utils import (create_mapset, delete_mapset, delete_location,
                            rename_mapset, rename_location, mapset_exists,
                            rename_mapset, rename_location, mapset_exists,
@@ -211,6 +212,59 @@ def create_mapset_interactively(guiparent, grassdb, location):
     return mapset
     return mapset
 
 
 
 
+def create_location_interactively(guiparent, grassdb):
+    """
+    Create new location using Location Wizard.
+
+    Returns tuple (database, location, mapset) where mapset is "PERMANENT"
+    by default or another mapset a user created and may want to switch to.
+    """
+    from location_wizard.wizard import LocationWizard
+
+    gWizard = LocationWizard(parent=guiparent,
+                             grassdatabase=grassdb)
+
+    if gWizard.location is None:
+        gWizard_output = (None, None, None)
+        # Returns Nones after Cancel
+        return gWizard_output
+
+    if gWizard.georeffile:
+        message = _(
+            "Do you want to import {}"
+            "to the newly created location?"
+        ).format(gWizard.georeffile)
+        dlg = wx.MessageDialog(parent=guiparent,
+                               message=message,
+                               caption=_("Import data?"),
+                               style=wx.YES_NO | wx.YES_DEFAULT |
+                               wx.ICON_QUESTION)
+        dlg.CenterOnParent()
+        if dlg.ShowModal() == wx.ID_YES:
+            import_file(guiparent, gWizard.georeffile)
+        dlg.Destroy()
+
+    if gWizard.default_region:
+        defineRegion = RegionDef(guiparent, location=gWizard.location)
+        defineRegion.CenterOnParent()
+        defineRegion.ShowModal()
+        defineRegion.Destroy()
+
+    if gWizard.user_mapset:
+        mapset = create_mapset_interactively(guiparent,
+                                                  gWizard.grassdatabase,
+                                                  gWizard.location)
+        # Returns database and location created by user
+        # and a mapset user may want to switch to
+        gWizard_output = (gWizard.grassdatabase, gWizard.location,
+                          mapset)
+    else:
+        # Returns PERMANENT mapset when user mapset not defined
+        gWizard_output = (gWizard.grassdatabase, gWizard.location,
+                          "PERMANENT")
+    return gWizard_output
+
+
 def rename_mapset_interactively(guiparent, grassdb, location, mapset):
 def rename_mapset_interactively(guiparent, grassdb, location, mapset):
     """
     """
     Rename selected mapset
     Rename selected mapset
@@ -281,6 +335,29 @@ def rename_location_interactively(guiparent, grassdb, location):
     return newlocation
     return newlocation
 
 
 
 
+def download_location_interactively(guiparent, grassdb):
+    """
+    Download new location using Location Wizard.
+
+    Returns tuple (database, location, mapset) where mapset is "PERMANENT"
+    by default or in future it could be the mapset the user may want to
+    switch to.
+    """
+    from startup.locdownload import LocationDownloadDialog
+
+    result = (None, None, None)
+    loc_download = LocationDownloadDialog(parent=guiparent,
+                                          database=grassdb)
+    loc_download.ShowModal()
+
+    if loc_download.GetLocation() is not None:
+        # Returns database and location created by user
+        # and a mapset user may want to switch to
+        result = (grassdb, loc_download.GetLocation(), "PERMANENT")
+    loc_download.Destroy()
+    return result
+
+
 def delete_mapset_interactively(guiparent, grassdb, location, mapset):
 def delete_mapset_interactively(guiparent, grassdb, location, mapset):
     """
     """
     Delete selected mapset
     Delete selected mapset
@@ -355,3 +432,44 @@ def delete_location_interactively(guiparent, grassdb, location):
             )
             )
     dlg.Destroy()
     dlg.Destroy()
     return False
     return False
+
+
+def import_file(guiparent, filePath):
+    """Tries to import file as vector or raster.
+
+    If successfull sets default region from imported map.
+    """
+    RunCommand('db.connect', flags='c')
+    mapName = os.path.splitext(os.path.basename(filePath))[0]
+    vectors = RunCommand('v.in.ogr', input=filePath, flags='l',
+                         read=True)
+
+    wx.BeginBusyCursor()
+    wx.GetApp().Yield()
+    if vectors:
+        # vector detected
+        returncode, error = RunCommand(
+            'v.in.ogr', input=filePath, output=mapName, flags='e',
+            getErrorMsg=True)
+    else:
+        returncode, error = RunCommand(
+            'r.in.gdal', input=filePath, output=mapName, flags='e',
+            getErrorMsg=True)
+    wx.EndBusyCursor()
+
+    if returncode != 0:
+        GError(
+            parent=guiparent,
+            message=_(
+                "Import of <%(name)s> failed.\n"
+                "Reason: %(msg)s") % ({
+                    'name': filePath,
+                    'msg': error}))
+    else:
+        GMessage(
+            message=_(
+                "Data file <%(name)s> imported successfully. "
+                "The location's default region was set from "
+                "this imported map.") % {
+                'name': filePath},
+            parent=guiparent)