123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904 |
- """
- @package startup.guiutils
- @brief General GUI-dependent utilities for GUI startup of GRASS GIS
- (C) 2018 by Vaclav Petras the GRASS Development Team
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
- @author Vaclav Petras <wenzeslaus gmail com>
- @author Linda Kladivova <l.kladivova@seznam.cz>
- This is for code which depend on something from GUI (wx or wxGUI).
- """
- import os
- import sys
- import wx
- import grass.script as gs
- from grass.script import gisenv
- from grass.grassdb.checks import (
- mapset_exists,
- location_exists,
- is_mapset_locked,
- get_mapset_lock_info,
- is_different_mapset_owner,
- is_mapset_current,
- is_location_current
- )
- from grass.grassdb.create import create_mapset, get_default_mapset_name
- from grass.grassdb.manage import (
- delete_mapset,
- delete_location,
- delete_grassdb,
- rename_mapset,
- rename_location,
- )
- from core.utils import GetListOfLocations
- from core import globalvar
- from core.gcmd import GError, GMessage, DecodeString, RunCommand
- from gui_core.dialogs import TextEntryDialog
- from location_wizard.dialogs import RegionDef
- from gui_core.widgets import GenericMultiValidator
- def SetSessionMapset(database, location, mapset):
- """Sets database, location and mapset for the current session"""
- RunCommand("g.gisenv", set="GISDBASE=%s" % database)
- RunCommand("g.gisenv", set="LOCATION_NAME=%s" % location)
- RunCommand("g.gisenv", set="MAPSET=%s" % mapset)
- class MapsetDialog(TextEntryDialog):
- def __init__(self, parent=None, default=None, message=None, caption=None,
- database=None, location=None):
- self.database = database
- self.location = location
- # list of tuples consisting of conditions and callbacks
- checks = [(gs.legal_name, self._nameValidationFailed),
- (self._checkMapsetNotExists, self._mapsetAlreadyExists),
- (self._checkOGR, self._reservedMapsetName)]
- validator = GenericMultiValidator(checks)
- TextEntryDialog.__init__(
- self, parent=parent,
- message=message,
- caption=caption,
- defaultValue=default,
- validator=validator,
- )
- def _nameValidationFailed(self, ctrl):
- message = _(
- "Name '{}' is not a valid name for location or mapset. "
- "Please use only ASCII characters excluding characters {} "
- "and space.").format(ctrl.GetValue(), '/"\'@,=*~')
- GError(parent=self, message=message, caption=_("Invalid name"))
- def _checkOGR(self, text):
- """Check user's input for reserved mapset name."""
- if text.lower() == 'ogr':
- return False
- return True
- def _reservedMapsetName(self, ctrl):
- message = _(
- "Name '{}' is reserved for direct "
- "read access to OGR layers. Please use "
- "another name for your mapset.").format(ctrl.GetValue())
- GError(parent=self, message=message,
- caption=_("Reserved mapset name"))
- def _checkMapsetNotExists(self, text):
- """Check whether user's input mapset exists or not."""
- if mapset_exists(self.database, self.location, text):
- return False
- return True
- def _mapsetAlreadyExists(self, ctrl):
- message = _(
- "Mapset '{}' already exists. Please consider using "
- "another name for your mapset.").format(ctrl.GetValue())
- GError(parent=self, message=message,
- caption=_("Existing mapset path"))
- class LocationDialog(TextEntryDialog):
- def __init__(self, parent=None, default=None, message=None, caption=None,
- database=None):
- self.database = database
- # list of tuples consisting of conditions and callbacks
- checks = [(gs.legal_name, self._nameValidationFailed),
- (self._checkLocationNotExists, self._locationAlreadyExists)]
- validator = GenericMultiValidator(checks)
- TextEntryDialog.__init__(
- self, parent=parent,
- message=message,
- caption=caption,
- defaultValue=default,
- validator=validator,
- )
- def _nameValidationFailed(self, ctrl):
- message = _(
- "Name '{}' is not a valid name for location or mapset. "
- "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.database, 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 get_reasons_mapsets_not_removable(mapsets, check_permanent):
- """Get reasons why mapsets cannot be removed.
- Parameter *mapsets* is a list of tuples (database, location, mapset).
- Parameter *check_permanent* is True of False. It depends on whether
- we want to check for permanent mapset or not.
- Returns messages as list if there were any failed checks, otherwise empty list.
- """
- messages = []
- for grassdb, location, mapset in mapsets:
- message = get_reason_mapset_not_removable(grassdb, location,
- mapset, check_permanent)
- if message:
- messages.append(message)
- return messages
- def get_reason_mapset_not_removable(grassdb, location, mapset, check_permanent):
- """Get reason why one mapset cannot be removed.
- Parameter *check_permanent* is True of False. It depends on whether
- we want to check for permanent mapset or not.
- Returns message as string if there was failed check, otherwise None.
- """
- message = None
- mapset_path = os.path.join(grassdb, location, mapset)
- # Check if mapset is permanent
- if check_permanent and mapset == "PERMANENT":
- message = _("Mapset <{mapset}> is required for a valid location.").format(
- mapset=mapset_path)
- # Check if mapset is current
- elif is_mapset_current(grassdb, location, mapset):
- message = _("Mapset <{mapset}> is the current mapset.").format(
- mapset=mapset_path)
- # Check whether mapset is in use
- elif is_mapset_locked(mapset_path):
- message = _("Mapset <{mapset}> is in use.").format(
- mapset=mapset_path)
- # Check whether mapset is owned by different user
- elif is_different_mapset_owner(mapset_path):
- message = _("Mapset <{mapset}> is owned by a different user.").format(
- mapset=mapset_path)
- return message
- def get_reasons_locations_not_removable(locations):
- """Get reasons why locations cannot be removed.
- Parameter *locations* is a list of tuples (database, location).
- Returns messages as list if there were any failed checks, otherwise empty list.
- """
- messages = []
- for grassdb, location in locations:
- messages += get_reasons_location_not_removable(grassdb, location)
- return messages
- def get_reasons_location_not_removable(grassdb, location):
- """Get reasons why one location cannot be removed.
- Returns messages as list if there were any failed checks, otherwise empty list.
- """
- messages = []
- location_path = os.path.join(grassdb, location)
- # Check if location is current
- if is_location_current(grassdb, location):
- messages.append(_("Location <{location}> is the current location.").format(
- location=location_path))
- return messages
- # Find mapsets in particular location
- tmp_gisrc_file, env = gs.create_environment(grassdb, location, 'PERMANENT')
- env['GRASS_SKIP_MAPSET_OWNER_CHECK'] = '1'
- g_mapsets = gs.read_command(
- 'g.mapsets',
- flags='l',
- separator='comma',
- quiet=True,
- env=env).strip().split(',')
- # Append to the list of tuples
- mapsets = []
- for g_mapset in g_mapsets:
- mapsets.append((grassdb, location, g_mapset))
- # Concentenate both checks
- messages += get_reasons_mapsets_not_removable(mapsets, check_permanent=False)
- gs.try_remove(tmp_gisrc_file)
- return messages
- def get_reasons_grassdb_not_removable(grassdb):
- """Get reasons why one grassdb cannot be removed.
- Returns messages as list if there were any failed checks, otherwise empty list.
- """
- messages = []
- genv = gisenv()
- # Check if grassdb is current
- if grassdb == genv['GISDBASE']:
- messages.append(_("GRASS database <{grassdb}> is the current database.").format(
- grassdb=grassdb))
- return messages
- g_locations = GetListOfLocations(grassdb)
- # Append to the list of tuples
- locations = []
- for g_location in g_locations:
- locations.append((grassdb, g_location))
- messages = get_reasons_locations_not_removable(locations)
- return messages
- # TODO: similar to (but not the same as) read_gisrc function in grass.py
- def read_gisrc():
- """Read variables from a current GISRC file
- Returns a dictionary representation of the file content.
- """
- grassrc = {}
- gisrc = os.getenv("GISRC")
- if gisrc and os.path.isfile(gisrc):
- try:
- rc = open(gisrc, "r")
- for line in rc.readlines():
- try:
- key, val = line.split(":", 1)
- except ValueError as e:
- sys.stderr.write(
- _('Invalid line in GISRC file (%s):%s\n' % (e, line)))
- grassrc[key.strip()] = DecodeString(val.strip())
- finally:
- rc.close()
- return grassrc
- def GetVersion():
- """Gets version and revision
- Returns tuple `(version, revision)`. For standard releases revision
- is an empty string.
- Revision string is currently wrapped in parentheses with added
- leading space. This is an implementation detail and legacy and may
- change anytime.
- """
- versionFile = open(os.path.join(globalvar.ETCDIR, "VERSIONNUMBER"))
- versionLine = versionFile.readline().rstrip('\n')
- versionFile.close()
- try:
- grassVersion, grassRevision = versionLine.split(' ', 1)
- if grassVersion.endswith('dev'):
- grassRevisionStr = ' (%s)' % grassRevision
- else:
- grassRevisionStr = ''
- except ValueError:
- grassVersion = versionLine
- grassRevisionStr = ''
- return (grassVersion, grassRevisionStr)
- def create_mapset_interactively(guiparent, grassdb, location):
- """
- Create new mapset
- """
- dlg = MapsetDialog(
- parent=guiparent,
- default=get_default_mapset_name(),
- message=_("Name for the new mapset:"),
- caption=_("Create new mapset"),
- database=grassdb,
- location=location,
- )
- mapset = None
- if dlg.ShowModal() == wx.ID_OK:
- mapset = dlg.GetValue()
- try:
- create_mapset(grassdb, location, mapset)
- except OSError as err:
- mapset = None
- GError(
- parent=guiparent,
- message=_("Unable to create new mapset: {}").format(err),
- showTraceback=False,
- )
- dlg.Destroy()
- 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):
- """Rename mapset with user interaction.
- Exceptions during renaming are handled in get_reason_mapset_not_removable
- function.
- Returns newmapset if there was a change or None if the mapset cannot be
- renamed (see reasons given by get_reason_mapset_not_removable
- function) or if another error was encountered.
- """
- newmapset = None
- # Check selected mapset
- message = get_reason_mapset_not_removable(grassdb, location, mapset,
- check_permanent=True)
- if message:
- dlg = wx.MessageDialog(
- parent=guiparent,
- message=_(
- "Cannot rename mapset <{mapset}> for the following reason:\n\n"
- "{reason}\n\n"
- "No mapset will be renamed."
- ).format(mapset=mapset, reason=message),
- caption=_("Unable to rename selected mapset"),
- style=wx.OK | wx.ICON_WARNING
- )
- dlg.ShowModal()
- dlg.Destroy()
- return newmapset
- # Display question dialog
- dlg = MapsetDialog(
- parent=guiparent,
- default=mapset,
- message=_("Current name: {}\n\nEnter new name:").format(mapset),
- caption=_("Rename selected mapset"),
- database=grassdb,
- location=location,
- )
- if dlg.ShowModal() == wx.ID_OK:
- newmapset = dlg.GetValue()
- try:
- rename_mapset(grassdb, location, mapset, newmapset)
- except OSError as err:
- newmapset = None
- wx.MessageBox(
- parent=guiparent,
- caption=_("Error"),
- message=_("Unable to rename mapset.\n\n{}").format(err),
- style=wx.OK | wx.ICON_ERROR | wx.CENTRE,
- )
- dlg.Destroy()
- return newmapset
- def rename_location_interactively(guiparent, grassdb, location):
- """Rename location with user interaction.
- Exceptions during renaming are handled in get_reasons_location_not_removable
- function.
- Returns newlocation if there was a change or None if the location cannot be
- renamed (see reasons given by get_reasons_location_not_removable
- function) or if another error was encountered.
- """
- newlocation = None
- # Check selected location
- messages = get_reasons_location_not_removable(grassdb, location)
- if messages:
- dlg = wx.MessageDialog(
- parent=guiparent,
- message=_(
- "Cannot rename location <{location}> for the following reasons:\n\n"
- "{reasons}\n\n"
- "No location will be renamed."
- ).format(location=location, reasons="\n".join(messages)),
- caption=_("Unable to rename selected location"),
- style=wx.OK | wx.ICON_WARNING
- )
- dlg.ShowModal()
- dlg.Destroy()
- return newlocation
- # Display question dialog
- dlg = LocationDialog(
- parent=guiparent,
- default=location,
- message=_("Current name: {}\n\nEnter new name:").format(location),
- caption=_("Rename selected location"),
- database=grassdb,
- )
- if dlg.ShowModal() == wx.ID_OK:
- newlocation = dlg.GetValue()
- try:
- rename_location(grassdb, location, newlocation)
- except OSError as err:
- newlocation = None
- wx.MessageBox(
- parent=guiparent,
- caption=_("Error"),
- message=_("Unable to rename location.\n\n{}").format(err),
- style=wx.OK | wx.ICON_ERROR | wx.CENTRE,
- )
- dlg.Destroy()
- 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.Centre()
- 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):
- """Delete one mapset with user interaction.
- This is currently just a convenience wrapper for delete_mapsets_interactively().
- """
- mapsets = [(grassdb, location, mapset)]
- return delete_mapsets_interactively(guiparent, mapsets)
- def delete_mapsets_interactively(guiparent, mapsets):
- """Delete multiple mapsets with user interaction.
- Parameter *mapsets* is a list of tuples (database, location, mapset).
- Exceptions during deletation are handled in get_reasons_mapsets_not_removable
- function.
- Returns True if there was a change, i.e., all mapsets were successfuly
- deleted or at least one mapset was deleted.
- Returns False if one or more mapsets cannot be deleted (see reasons given
- by get_reasons_mapsets_not_removable function) or if an error was
- encountered when deleting the first mapset in the list.
- """
- deletes = []
- modified = False
- # Check selected mapsets
- messages = get_reasons_mapsets_not_removable(mapsets, check_permanent=True)
- if messages:
- dlg = wx.MessageDialog(
- parent=guiparent,
- message=_(
- "Cannot delete one or more mapsets for the following reasons:\n\n"
- "{reasons}\n\n"
- "No mapsets will be deleted."
- ).format(reasons="\n".join(messages)),
- caption=_("Unable to delete selected mapsets"),
- style=wx.OK | wx.ICON_WARNING
- )
- dlg.ShowModal()
- dlg.Destroy()
- return modified
- # No error occurs, create list of mapsets for deleting
- for grassdb, location, mapset in mapsets:
- mapset_path = os.path.join(grassdb, location, mapset)
- deletes.append(mapset_path)
- # Display question dialog
- dlg = wx.MessageDialog(
- parent=guiparent,
- message=_(
- "Do you want to continue with deleting"
- " one or more of the following mapsets?\n\n"
- "{deletes}\n\n"
- "All maps included in these mapsets will be permanently deleted!"
- ).format(deletes="\n".join(deletes)),
- caption=_("Delete selected mapsets"),
- style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION,
- )
- if dlg.ShowModal() == wx.ID_YES:
- try:
- for grassdb, location, mapset in mapsets:
- delete_mapset(grassdb, location, mapset)
- modified = True
- dlg.Destroy()
- return modified
- except OSError as error:
- wx.MessageBox(
- parent=guiparent,
- caption=_("Error when deleting mapsets"),
- message=_(
- "The following error occured when deleting mapset <{path}>:"
- "\n\n{error}\n\n"
- "Deleting of mapsets was interrupted."
- ).format(
- path=os.path.join(grassdb, location, mapset),
- error=error,
- ),
- style=wx.OK | wx.ICON_ERROR | wx.CENTRE,
- )
- dlg.Destroy()
- return modified
- def delete_location_interactively(guiparent, grassdb, location):
- """Delete one location with user interaction.
- This is currently just a convenience wrapper for delete_locations_interactively().
- """
- locations = [(grassdb, location)]
- return delete_locations_interactively(guiparent, locations)
- def delete_locations_interactively(guiparent, locations):
- """Delete multiple locations with user interaction.
- Parameter *locations* is a list of tuples (database, location).
- Exceptions during deletation are handled in get_reasons_locations_not_removable
- function.
- Returns True if there was a change, i.e., all locations were successfuly
- deleted or at least one location was deleted.
- Returns False if one or more locations cannot be deleted (see reasons given
- by get_reasons_locations_not_removable function) or if an error was
- encountered when deleting the first location in the list.
- """
- deletes = []
- modified = False
- # Check selected locations
- messages = get_reasons_locations_not_removable(locations)
- if messages:
- dlg = wx.MessageDialog(
- parent=guiparent,
- message=_(
- "Cannot delete one or more locations for the following reasons:\n\n"
- "{reasons}\n\n"
- "No locations will be deleted."
- ).format(reasons="\n".join(messages)),
- caption=_("Unable to delete selected locations"),
- style=wx.OK | wx.ICON_WARNING
- )
- dlg.ShowModal()
- dlg.Destroy()
- return modified
- # No error occurs, create list of locations for deleting
- for grassdb, location in locations:
- location_path = os.path.join(grassdb, location)
- deletes.append(location_path)
- # Display question dialog
- dlg = wx.MessageDialog(
- parent=guiparent,
- message=_(
- "Do you want to continue with deleting"
- " one or more of the following locations?\n\n"
- "{deletes}\n\n"
- "All mapsets included in these locations will be permanently deleted!"
- ).format(deletes="\n".join(deletes)),
- caption=_("Delete selected locations"),
- style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION,
- )
- if dlg.ShowModal() == wx.ID_YES:
- try:
- for grassdb, location in locations:
- delete_location(grassdb, location)
- modified = True
- dlg.Destroy()
- return modified
- except OSError as error:
- wx.MessageBox(
- parent=guiparent,
- caption=_("Error when deleting locations"),
- message=_(
- "The following error occured when deleting location <{path}>:"
- "\n\n{error}\n\n"
- "Deleting of locations was interrupted."
- ).format(
- path=os.path.join(grassdb, location),
- error=error,
- ),
- style=wx.OK | wx.ICON_ERROR | wx.CENTRE,
- )
- dlg.Destroy()
- return modified
- def delete_grassdb_interactively(guiparent, grassdb):
- """
- Delete grass database if could be deleted.
- If current grass database found, desired operation cannot be performed.
- Exceptions during deleting are handled in this function.
- Returns True if grass database is deleted from the disk. Returns None if
- cannot be deleted (see above the possible reasons).
- """
- deleted = False
- # Check selected grassdb
- messages = get_reasons_grassdb_not_removable(grassdb)
- if messages:
- dlg = wx.MessageDialog(
- parent=guiparent,
- message=_(
- "Cannot delete GRASS database from disk for the following reason:\n\n"
- "{reasons}\n\n"
- "GRASS database will not be deleted."
- ).format(reasons="\n".join(messages)),
- caption=_("Unable to delete selected GRASS database"),
- style=wx.OK | wx.ICON_WARNING
- )
- dlg.ShowModal()
- else:
- dlg = wx.MessageDialog(
- parent=guiparent,
- message=_(
- "Do you want to delete"
- " the following GRASS database from disk?\n\n"
- "{grassdb}\n\n"
- "The directory will be permanently deleted!"
- ).format(grassdb=grassdb),
- caption=_("Delete selected GRASS database"),
- style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION,
- )
- if dlg.ShowModal() == wx.ID_YES:
- try:
- delete_grassdb(grassdb)
- deleted = True
- dlg.Destroy()
- return deleted
- except OSError as error:
- wx.MessageBox(
- parent=guiparent,
- caption=_("Error when deleting GRASS database"),
- message=_(
- "The following error occured when deleting database <{path}>:"
- "\n\n{error}\n\n"
- "Deleting of GRASS database was interrupted."
- ).format(
- path=grassdb,
- error=error,
- ),
- style=wx.OK | wx.ICON_ERROR | wx.CENTRE,
- )
- dlg.Destroy()
- return deleted
- def can_switch_mapset_interactive(guiparent, grassdb, location, mapset):
- """
- Checks if mapset is locked and offers to remove the lock file.
- Returns True if user wants to switch to the selected mapset in spite of
- removing lock. Returns False if a user wants to stay in the current
- mapset or if an error was encountered.
- """
- can_switch = True
- mapset_path = os.path.join(grassdb, location, mapset)
- if is_mapset_locked(mapset_path):
- info = get_mapset_lock_info(mapset_path)
- user = info['owner'] if info['owner'] else _('unknown')
- lockpath = info['lockpath']
- timestamp = info['timestamp']
- dlg = wx.MessageDialog(
- parent=guiparent,
- message=_("User {user} is already running GRASS in selected mapset "
- "<{mapset}>\n (file {lockpath} created {timestamp} "
- "found).\n\n"
- "Concurrent use not allowed.\n\n"
- "Do you want to stay in the current mapset or remove "
- ".gislock and switch to selected mapset?"
- ).format(user=user,
- mapset=mapset,
- lockpath=lockpath,
- timestamp=timestamp),
- caption=_("Mapset is in use"),
- style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION,
- )
- dlg.SetYesNoLabels("S&witch to selected mapset",
- "S&tay in current mapset")
- if dlg.ShowModal() == wx.ID_YES:
- # Remove lockfile
- try:
- os.remove(lockpath)
- except IOError as e:
- wx.MessageBox(
- parent=guiparent,
- caption=_("Error when removing lock file"),
- message=_("Unable to remove {lockpath}.\n\n Details: {error}."
- ).format(lockpath=lockpath,
- error=e),
- style=wx.OK | wx.ICON_ERROR | wx.CENTRE
- )
- can_switch = False
- else:
- can_switch = False
- dlg.Destroy()
- return can_switch
- 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)
- def switch_mapset_interactively(guiparent, giface, dbase, location, mapset):
- """Switch current mapset. Emits giface.currentMapsetChanged signal."""
- if dbase:
- if RunCommand('g.mapset', parent=guiparent,
- location=location,
- mapset=mapset,
- dbase=dbase) == 0:
- GMessage(parent=guiparent,
- message=_("Current GRASS database is <%(dbase)s>.\n"
- "Current location is <%(loc)s>.\n"
- "Current mapset is <%(mapset)s>."
- ) %
- {'dbase': dbase, 'loc': location, 'mapset': mapset})
- giface.currentMapsetChanged.emit(dbase=dbase,
- location=location,
- mapset=mapset)
- elif location:
- if RunCommand('g.mapset', parent=guiparent,
- location=location,
- mapset=mapset) == 0:
- GMessage(parent=guiparent,
- message=_("Current location is <%(loc)s>.\n"
- "Current mapset is <%(mapset)s>.") %
- {'loc': location, 'mapset': mapset})
- giface.currentMapsetChanged.emit(dbase=None,
- location=location,
- mapset=mapset)
- else:
- if RunCommand('g.mapset',
- parent=guiparent,
- mapset=mapset) == 0:
- GMessage(parent=guiparent,
- message=_("Current mapset is <%s>.") % mapset)
- giface.currentMapsetChanged.emit(dbase=None, location=None, mapset=mapset)
|