def GetSelectedMap(self): """Return name of selected map in layer tree""" layerList = self._giface.GetLayerList() layerSelected = layerList.GetSelectedLayer() if layerSelected is None: return None if not layerSelected.maplayer.IsActive(): GWarning(_("Selected map <%s> has been disabled for rendering. " "Operation canceled.") % str(layerSelected), parent=self.mapWin) return None if layerSelected: mapName = str(layerSelected) if self.mapName is not None: if self.mapName != mapName: self.Reset() else: mapName = None self.UnregisterMapEvtHandler() GError(_("No map layer selected. Operation canceled.")) return mapName
def UnregisterAllHandlers(self): """Unregisters all registered handlers @deprecated This method is deprecated. Use Signals or drawing API instead. Before each handler is unregistered it is called with string value "unregistered" of event parameter. """ for containerEv, handlers in six.iteritems(self.handlersContainer): for handler in handlers: try: handler("unregistered") handlers.remove(handler) except: GError( parent=self, message= _("Error occurred during unregistration of handler: %s \n \ Handler was unregistered.") % handler.__name__, ) handlers.remove(handler)
def _readJinjaInfo(self): '''Parser of 'comments'({# #}) in jinja template which are represented by jinjainfo::MdDescription parsed values initializing list of jinjainfo::MdDesctiption obect ''' try: with open(self.template, "r") as f: for line in f: # if found start of comments if str(line).find("{#") != -1: values = findBetween(line, "{#", "#}") values1 = findBetween(line, "{%", "#}") values2 = findBetween(line, "{{", "#}") if values1 != '': values += ",selfInfoString='''{%" + values1 + "#}'''" else: values += ",selfInfoString='''{{" + values2 + "#}'''" exe_str = "self.mdDescription.append(MdDescription(%s))" % values exe_str = exe_str.encode("utf-8", 'ignore') eval(exe_str) except: GError('Cannot open jinja template')
def OnCopy(self, event): """Copy selected features from (background) vector map""" if not self.digit: GError(_("No vector map open for editing."), self.parent) return # select background map dlg = VectorDialog(self.parent, title = _("Select background vector map"), layerTree = self._giface.GetLayerTree()) if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() return mapName = dlg.GetName(full=True) dlg.Destroy() # close open background map if any bgMap = UserSettings.Get(group = 'vdigit', key = 'bgmap', subkey = 'value', internal = True) if bgMap: self.digit.CloseBackgroundMap() self.editingBgMap.emit(mapName = bgMap, unset=True) # open background map for reading UserSettings.Set(group = 'vdigit', key = 'bgmap', subkey = 'value', value = str(mapName), internal = True) self.digit.OpenBackgroundMap(mapName) self.editingBgMap.emit(mapName = mapName) if self.action['desc'] == 'copyLine': # select previous action self.ToggleTool(self.addPoint, True) self.ToggleTool(self.additionalTools, False) self.OnAddPoint(event) return Debug.msg(2, "Digittoolbar.OnCopy():") self.action = { 'desc' : "copyLine", 'id' : self.additionalTools } self.MapWindow.mouse['box'] = 'box'
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.Yield() if mapName in 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=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)
def QuerySelectedMap(self): """Return w.what info from last clicked coords on display""" self.mapName = self.GetSelectedMap() if not self.mapName: return {} mapInfo = self.mapWin.GetMap() threshold = 10.0 * ( (mapInfo.region["e"] - mapInfo.region["w"]) / mapInfo.width) try: query = grass.vector_what( map=[self.mapName], coord=self.mapWin.GetLastEN(), distance=threshold, skip_attributes=True, ) except grass.ScriptError: GError(parent=self, message=_("Failed to query vector map(s) <%s>.") % self.map) return None return query[0]
def OnOutputSave(self, event): """Save (selected) text from output window to the file""" text = self.cmdOutput.GetSelectedText() if not text: text = self.cmdOutput.GetText() # add newline if needed if len(text) > 0 and text[-1] != "\n": text += "\n" dlg = wx.FileDialog( self, message=_("Save file as..."), defaultFile="grass_cmd_output.txt", wildcard=_("%(txt)s (*.txt)|*.txt|%(files)s (*)|*") % {"txt": _("Text files"), "files": _("Files")}, style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT, ) # Show the dialog and retrieve the user response. If it is the OK response, # process the data. if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() try: output = open(path, "w") output.write(text) except IOError as e: GError( _("Unable to write file '%(path)s'.\n\nDetails: %(error)s") % {"path": path, "error": e} ) finally: output.close() message = _("Command output saved into '%s'") % path self.showNotification.emit(message=message) dlg.Destroy()
def OnExportMap(self, event): """Export selected features to a new map Add new map layer to layer tree and checked it @todo: set color of map to higlight color """ if len(self.selectedFeatures) == 0: GMessage(_('No features selected')) return lst = '' for cat in self.selectedFeatures: # build text string of categories for v.extract input lst += str(cat['Category']) + ',' lst = lst[:-1] outMap = str(self.selectedFeatures[0]['Map']) + '_selection' + str( self._id_generator(3)) ret, err = RunCommand('v.extract', input=self.selectedFeatures[0]['Map'], layer=self.selectedFeatures[0]['Layer'], output=outMap, cats=lst, getErrorMsg=True) if ret == 0: tree = self._giface.GetLayerTree() if tree: tree.AddLayer(ltype='vector', lname=outMap, lcmd=['d.vect', 'map=%s' % outMap], lchecked=True) # TODO colorize new map self.Reset() else: GMessage(_('Vector map <%s> was created') % outMap) self.Reset() else: GError(_("Unable to create a new vector map.\n\nReason: %s") % err)
def UpdateLocations(self, dbase): """Update list of locations""" try: self.listOfLocations = GetListOfLocations(dbase) except UnicodeEncodeError: GError(parent=self, message=_("Unable to set GRASS database. " "Check your locale settings.")) self.lblocations.Clear() self.lblocations.InsertItems(self.listOfLocations, 0) if len(self.listOfLocations) > 0: self._hideMessage() self.lblocations.SetSelection(0) else: self.lblocations.SetSelection(wx.NOT_FOUND) self._showWarning( _("No GRASS Location found in '%s'." " Create a new Location or choose different" " GRASS database directory.") % self.gisdbase) return self.listOfLocations
def GetOptData(self, dcmd, layer, params, propwin): """Handler for module dialogs.""" if dcmd: layer.cmd = dcmd layer.selected = True mapName, found = GetLayerNameFromCmd(dcmd) if found: try: if layer.hidden: layer.hidden = False signal = self.layerAdded else: signal = self.cmdChanged layer.name = mapName signal.emit(index=self._layerList.GetLayerIndex(layer), layer=layer) except ValueError as e: self._layerList.RemoveLayer(layer) GError(parent=self, message=str(e), showTraceback=False) self._update() self.anyChange.emit()
def OnApplyInputChanges(self): first, second = self._inputDialog.GetValues() if self._inputDialog.IsSimpleMode(): self.rasters["first"], self.rasters["second"] = first, second res1 = self.SetFirstRaster(name=self.rasters["first"]) res2 = self.SetSecondRaster(name=self.rasters["second"]) if not (res1 and res2) and (first or second): message = "" if first and not res1: message += _("Map <%s> not found. ") % self.rasters["first"] if second and not res2: message += _("Map <%s> not found.") % self.rasters["second"] if message: GError(parent=self, message=message) return self.ZoomToMap() else: LayerListToRendererConverter(self.GetFirstMap()).ConvertAll(first) LayerListToRendererConverter(self.GetSecondMap()).ConvertAll(second) self.SetRasterNames() if self.IsAutoRendered(): self.OnRender(event=None)
def CreateNewMapset(self, mapset): if mapset in self.listOfMapsets: GMessage(parent=self, message=_("Mapset <%s> already exists.") % mapset) return False if mapset.lower() == 'ogr': dlg1 = wx.MessageDialog( parent=self, message=_( "Mapset <%s> is reserved for direct " "read access to OGR layers. Please consider to use " "another name for your mapset.\n\n" "Are you really sure that you want to create this mapset?") % mapset, caption=_("Reserved mapset name"), style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) ret = dlg1.ShowModal() dlg1.Destroy() if ret == wx.ID_NO: dlg1.Destroy() return False try: self.gisdbase = self.tgisdbase.GetValue() location = self.listOfLocations[self.lblocations.GetSelection()] create_mapset(self.gisdbase, location, mapset) self.OnSelectLocation(None) self.lbmapsets.SetSelection(self.listOfMapsets.index(mapset)) self.bstart.SetFocus() return True except Exception as e: GError(parent=self, message=_("Unable to create new mapset: %s") % e, showTraceback=False) return False
def UpdateLocations(self, dbase): """Update list of locations""" try: self.listOfLocations = GetListOfLocations(dbase) except (UnicodeEncodeError, UnicodeDecodeError) as e: GError(parent=self, message=_("Unicode error detected. " "Check your locale settings. Details: {0}").format(e), showTraceback=False) self.lblocations.Clear() self.lblocations.InsertItems(self.listOfLocations, 0) if len(self.listOfLocations) > 0: self._hideMessage() self.lblocations.SetSelection(0) else: self.lblocations.SetSelection(wx.NOT_FOUND) self._showWarning(_("No GRASS Location found in '%s'." " Create a new Location or choose different" " GRASS database directory.") % self.gisdbase) return self.listOfLocations
def CmdProtocolSave(self): """Save list of manually entered commands into a text log file""" if not hasattr(self, 'cmdFileProtocol'): return # it should not happen try: output = open(self.cmdFileProtocol, "a") cmds = self.cmdPrompt.GetCommands() output.write('\n'.join(cmds)) if len(cmds) > 0: output.write('\n') except IOError as e: GError( _("Unable to write file '%(filePath)s'.\n\nDetails: %(error)s") % { 'filePath': self.cmdFileProtocol, 'error': e }) finally: output.close() message = _("Command log saved to '%s'") % self.cmdFileProtocol self.showNotification.emit(message=message) del self.cmdFileProtocol
def OnRun(self, event): """Run Python script""" if not self.filename: self.filename = gscript.tempfile() + '.py' self.tempfile = True try: fd = open(self.filename, "w") fd.write(self.body.GetText()) except IOError as e: GError(_("Unable to launch Python script. %s") % e, parent=self.guiparent) return finally: fd.close() mode = stat.S_IMODE(os.lstat(self.filename)[stat.ST_MODE]) os.chmod(self.filename, mode | stat.S_IXUSR) else: # always save automatically before running fd = open(self.filename, "w") try: fd.write(self.body.GetText()) finally: fd.close() # set executable file # (not sure if needed every time but useful for opened files) os.chmod(self.filename, stat.S_IRWXU | stat.S_IWUSR) # run in console as other modules, avoid Python shell which # carries variables over to the next execution env = os.environ.copy() if self.overwrite: env['GRASS_OVERWRITE'] = '1' cmd = [fd.name] if self.parameters: cmd.extend(self.parameters) self.giface.RunCmd(cmd, env=env)
def OpenRecentFile(self, path, file_exists, file_history): """Try open recent file and read content :param str path: file path :param bool file_exists: file path exists :param bool file_history: file history obj instance :return: None """ if not file_exists: GError( _("File <{}> doesn't exist." "It was probably moved or deleted.".format(path)), parent=self.guiparent, ) else: if self.CanReplaceContent(by_message="file"): self.filename = path content = self._openFile(file_path=path) if content: self.body.SetText(content) file_history.AddFileToHistory( filename=path) # move up the list self.tempfile = False
def OnAddCat(self, event): """Button 'Add' new category pressed """ try: layer = int(self.layerNew.GetStringSelection()) cat = int(self.catNew.GetValue()) if layer <= 0: raise ValueError except ValueError: GError( parent=self, message=_( "Unable to add new layer/category <%(layer)s/%(category)s>.\n" "Layer and category number must be integer.\n" "Layer number must be greater than zero.") % { 'layer': str( self.layerNew.GetValue()), 'category': str( self.catNew.GetValue())}) return False if layer not in self.cats[self.fid].keys(): self.cats[self.fid][layer] = [] self.cats[self.fid][layer].append(cat) # reload list self.itemDataMap = self.list.Populate(self.cats[self.fid], update=True) # update category number for add self.catNew.SetValue(cat + 1) event.Skip() return True
def UpdateCategoryRaster(self, cat_id, attrs, render=True): cat_rast = self.scatt_mgr.core.GetCatRast(cat_id) if not grass.find_file(cat_rast, element='cell', mapset='.')['file']: return cats_attrs = self.cats_mgr.GetCategoryAttrs(cat_id) if "color" in attrs: ret, err_msg = RunCommand('r.colors', map=cat_rast, rules="-", stdin="1 %s" % cats_attrs["color"], getErrorMsg=True) if ret != 0: GError("r.colors failed\n%s" % err_msg) if render: self.giface.updateMap.emit() if "name" in attrs: # TODO hack self.giface.GetLayerList()._tree.SetItemText( self.added_cats_rasts[cat_id], cats_attrs['name']) cats_attrs["name"]
def AddScattPlot(self): if not self.data_set and self.iclass_conn: self.show_add_scatt_plot = True self.iclass_conn.SetData() self.show_add_scatt_plot = False return if not self.data_set: GError(_('No data set.')) return self.computingStarted.emit() bands = self.core.GetBands() #added_bands_ids = [] # for scatt_id in self.plots): # added_bands_ids.append[idBandsToidScatt(scatt_id)] self.digit_conn.Update() ncells = self.region["rows"] * self.region["cols"] if ncells > MAX_NCELLS: GError( _( parent=self.guiparent, mmessage=_( "Interactive Scatter Plot Tool can not be used.\n" "Number of cells (rows*cols) <%d> in current region" "is higher than maximum limit <%d>.\n\n" "You can reduce number of cells in current region using <g.region> command." % (ncells, MAX_NCELLS)))) return elif ncells > WARN_NCELLS: dlg = wx.MessageDialog( parent=self.guiparent, message=_("Number of cells (rows*cols) <%d> in current region is " "higher than recommended threshold <%d>.\n" "It is strongly advised to reduce number of cells " "in current region below recommend threshold.\n " "It can be done by <g.region> command.\n\n" "Do you want to continue using " "Interactive Scatter Plot Tool with this region?" % (ncells, WARN_NCELLS)), style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_WARNING) ret = dlg.ShowModal() if ret != wx.ID_YES: return dlg = AddScattPlotDialog(parent=self.guiparent, bands=self.all_bands, check_bands_callback=self.CheckBands) if dlg.ShowModal() == wx.ID_OK: scatt_ids = [] sel_bands = dlg.GetBands() for b_1, b_2 in sel_bands: transpose = False if b_1 > b_2: transpose = True tmp_band = b_2 b_2 = b_1 b_1 = tmp_band b_1_id = self.all_bands_to_bands[self.all_bands[b_1]] b_2_id = self.all_bands_to_bands[self.all_bands[b_2]] scatt_id = idBandsToidScatt(b_1_id, b_2_id, len(bands)) if scatt_id in self.plots: continue self.plots[scatt_id] = {'transpose': transpose, 'scatt': None} scatt_ids.append(scatt_id) self._addScattPlot(scatt_ids) dlg.Destroy()
def OnPasteMap(self, event): # copying between mapsets of one location if not self.copy_layer: if self.copy_mode: GMessage(_("No map selected for copying."), parent=self) else: GMessage(_("No map selected for moving."), parent=self) return gisrc, env = gscript.create_environment( gisenv()['GISDBASE'], self.selected_location.label, mapset=self.selected_mapset.label) gisrc2, env2 = gscript.create_environment( gisenv()['GISDBASE'], self.copy_location.label, mapset=self.copy_mapset.label) new_name = self.copy_layer.label if self.selected_location == self.copy_location: # within one mapset if self.selected_mapset == self.copy_mapset: # ignore when just moves map if self.copy_mode is False: return new_name = self._getNewMapName( _('New name'), _('Select new name'), self.copy_layer.label, env=env, mapset=self.selected_mapset.label, element=self.copy_type.label) if not new_name: return # within one location, different mapsets else: if map_exists(new_name, element=self.copy_type.label, env=env, mapset=self.selected_mapset.label): new_name = self._getNewMapName( _('New name'), _('Select new name'), self.copy_layer.label, env=env, mapset=self.selected_mapset.label, element=self.copy_type.label) if not new_name: return string = self.copy_layer.label + '@' + self.copy_mapset.label + ',' + new_name pasted = 0 if self.copy_mode: label = _("Copying <{name}>...").format(name=string) else: label = _("Moving <{name}>...").format(name=string) self.showNotification.emit(message=label) if self.copy_type.label == 'vector': pasted, cmd = self._runCommand('g.copy', vector=string, env=env) node = 'vector' elif self.copy_type.label == 'raster': pasted, cmd = self._runCommand('g.copy', raster=string, env=env) node = 'raster' else: pasted, cmd = self._runCommand('g.copy', raster_3d=string, env=env) node = 'raster_3d' if pasted == 0: self.InsertLayer(name=new_name, mapset_node=self.selected_mapset, element_name=node) Debug.msg(1, "COPIED TO: " + new_name) if self.copy_mode: self.showNotification.emit( message=_("g.copy completed").format(cmd=cmd)) else: self.showNotification.emit( message=_("g.copy completed").format(cmd=cmd)) # remove old if not self.copy_mode: self._removeMapAfterCopy(env2) gscript.try_remove(gisrc) gscript.try_remove(gisrc2) # expand selected mapset self.ExpandNode(self.selected_mapset, recursive=True) self._initVariablesCatalog() else: if self.copy_type.label == 'raster_3d': GError(_("Reprojection is not implemented for 3D rasters"), parent=self) return if map_exists(new_name, element=self.copy_type.label, env=env, mapset=self.selected_mapset.label): new_name = self._getNewMapName( _('New name'), _('Select new name'), self.copy_layer.label, env=env, mapset=self.selected_mapset.label, element=self.copy_type.label) if not new_name: return gisdbase = gisenv()['GISDBASE'] callback = lambda: self._onDoneReprojection( iEnv=env2, iGisrc=gisrc2, oGisrc=gisrc) dlg = CatalogReprojectionDialog( self, self._giface, gisdbase, self.copy_location.label, self.copy_mapset.label, self.copy_layer.label, env2, gisdbase, self.selected_location.label, self.selected_mapset.label, new_name, self.copy_type.label, env, callback) dlg.ShowModal()
def GetRegion(self, rast=[], zoom=False, vect=[], regionName=None, n=None, s=None, e=None, w=None, default=False, update=False): """!Get region settings (g.region -upgc) Optionally extent, raster or vector map layer can be given. @param rast list of raster maps @param zoom zoom to raster map (ignore NULLs) @param vect list of vector maps @param regionName named region or None @param n,s,e,w force extent @param default force default region settings @param update if True update current display region settings @return region settings as directory, e.g. { 'n':'4928010', 's':'4913700', 'w':'589980',...} @see GetCurrentRegion() """ region = {} tmpreg = os.getenv("GRASS_REGION") if tmpreg: del os.environ["GRASS_REGION"] # use external gisrc if defined gisrc_orig = os.getenv("GISRC") if self.gisrc: os.environ["GISRC"] = self.gisrc # do not update & shell style output cmd = {} cmd['flags'] = 'ugpc' if default: cmd['flags'] += 'd' if regionName: cmd['region'] = regionName if n: cmd['n'] = n if s: cmd['s'] = s if e: cmd['e'] = e if w: cmd['w'] = w if rast: if zoom: cmd['zoom'] = rast[0] else: cmd['rast'] = ','.join(rast) if vect: cmd['vect'] = ','.join(vect) ret, reg, msg = RunCommand('g.region', read=True, getErrorMsg=True, **cmd) if ret != 0: if rast: message = _("Unable to zoom to raster map <%s>.") % rast[0] + \ "\n\n" + _("Details:") + " %s" % msg elif vect: message = _("Unable to zoom to vector map <%s>.") % vect[0] + \ "\n\n" + _("Details:") + " %s" % msg else: message = _( "Unable to get current geographic extent. " "Force quiting wxGUI. Please manually run g.region to " "fix the problem.") GError(message) return self.region for r in reg.splitlines(): key, val = r.split("=", 1) try: region[key] = float(val) except ValueError: region[key] = val # back to original gisrc if self.gisrc: os.environ["GISRC"] = gisrc_orig # restore region if tmpreg: os.environ["GRASS_REGION"] = tmpreg Debug.msg(3, "Map.GetRegion(): %s" % region) if update: self.region = region return region
def _export(self, exportInfo, decorations): size = self.frame.animationPanel.GetSize() if self.temporalMode == TemporalMode.TEMPORAL: timeLabels, mapNamesDict = self.temporalManager.GetLabelsAndMaps() frameCount = len(timeLabels) else: frameCount = self.animationData[ 0].mapCount # should be the same for all animWinSize = [] animWinPos = [] animWinIndex = [] legends = [anim.legendCmd for anim in self.animationData] # determine position and sizes of bitmaps for i, (win, anim) in enumerate(zip(self.mapwindows, self.animations)): if anim.IsActive(): pos = win.GetPosition() animWinPos.append(pos) animWinSize.append(win.GetSize()) animWinIndex.append(i) images = [] busy = wx.BusyInfo( _("Preparing export, please wait..."), parent=self.frame) wx.Yield() lastBitmaps = {} fgcolor = UserSettings.Get( group='animation', key='font', subkey='fgcolor') bgcolor = UserSettings.Get( group='animation', key='font', subkey='bgcolor') for frameIndex in range(frameCount): image = wx.EmptyImage(*size) image.Replace(0, 0, 0, 255, 255, 255) # collect bitmaps of all windows and paste them into the one for i in animWinIndex: frameId = self.animations[i].GetFrame(frameIndex) if not UserSettings.Get(group='animation', key='temporal', subkey=['nodata', 'enable']): if frameId is not None: bitmap = self.bitmapProvider.GetBitmap(frameId) lastBitmaps[i] = bitmap else: if i not in lastBitmaps: lastBitmaps[i] = wx.NullBitmap() else: bitmap = self.bitmapProvider.GetBitmap(frameId) lastBitmaps[i] = bitmap im = wx.ImageFromBitmap(lastBitmaps[i]) # add legend if used legend = legends[i] if legend: legendBitmap = self.bitmapProvider.LoadOverlay(legend) x, y = self.mapwindows[i].GetOverlayPos() legImage = wx.ImageFromBitmap(legendBitmap) # not so nice result, can we handle the transparency # otherwise? legImage.ConvertAlphaToMask() im.Paste(legImage, x, y) if im.GetSize() != animWinSize[i]: im.Rescale(*animWinSize[i]) image.Paste(im, *animWinPos[i]) # paste decorations for decoration in decorations: # add image x = decoration['pos'][0] / 100. * size[0] y = decoration['pos'][1] / 100. * size[1] if decoration['name'] == 'image': decImage = wx.Image(decoration['file']) elif decoration['name'] == 'time': timeLabel = timeLabels[frameIndex] if timeLabel[1]: # interval text = _("%(from)s %(dash)s %(to)s") % { 'from': timeLabel[0], 'dash': u"\u2013", 'to': timeLabel[1]} else: if self.temporalManager.GetTemporalType() == TemporalType.ABSOLUTE: text = timeLabel[0] else: text = _("%(start)s %(unit)s") % \ {'start': timeLabel[0], 'unit': timeLabel[2]} decImage = RenderText( text, decoration['font'], bgcolor, fgcolor).ConvertToImage() elif decoration['name'] == 'text': text = decoration['text'] decImage = RenderText( text, decoration['font'], bgcolor, fgcolor).ConvertToImage() image.Paste(decImage, x, y) images.append(image) del busy # export pilImages = [WxImageToPil(image) for image in images] busy = wx.BusyInfo(_("Exporting animation, please wait..."), parent=self.frame) wx.Yield() try: if exportInfo['method'] == 'sequence': filename = os.path.join( exportInfo['directory'], exportInfo['prefix'] + '.' + exportInfo['format'].lower()) writeIms(filename=filename, images=pilImages) elif exportInfo['method'] == 'gif': writeGif(filename=exportInfo['file'], images=pilImages, duration=self.timeTick / float(1000), repeat=True) elif exportInfo['method'] == 'swf': writeSwf(filename=exportInfo['file'], images=pilImages, duration=self.timeTick / float(1000), repeat=True) elif exportInfo['method'] == 'avi': writeAvi(filename=exportInfo['file'], images=pilImages, duration=self.timeTick / float(1000), encoding=exportInfo['encoding'], inputOptions=exportInfo['options']) except Exception as e: del busy GError(parent=self.frame, message=str(e)) return del busy
def _export(self, exportInfo, decorations): size = self.frame.animationPanel.GetSize() if self.temporalMode == TemporalMode.TEMPORAL: timeLabels, mapNamesDict = self.temporalManager.GetLabelsAndMaps() frameCount = len(timeLabels) else: frameCount = self.animationData[ 0].mapCount # should be the same for all animWinSize = [] animWinPos = [] animWinIndex = [] legends = [anim.legendCmd for anim in self.animationData] # determine position and sizes of bitmaps for i, (win, anim) in enumerate(zip(self.mapwindows, self.animations)): if anim.IsActive(): pos = win.GetPosition() animWinPos.append(pos) animWinSize.append(win.GetSize()) animWinIndex.append(i) images = [] busy = wx.BusyInfo(_("Preparing export, please wait..."), parent=self.frame) wx.GetApp().Yield() lastBitmaps = {} fgcolor = UserSettings.Get(group="animation", key="font", subkey="fgcolor") bgcolor = UserSettings.Get(group="animation", key="font", subkey="bgcolor") for frameIndex in range(frameCount): image = EmptyImage(*size) image.Replace(0, 0, 0, 255, 255, 255) # collect bitmaps of all windows and paste them into the one for i in animWinIndex: frameId = self.animations[i].GetFrame(frameIndex) if not UserSettings.Get(group="animation", key="temporal", subkey=["nodata", "enable"]): if frameId is not None: bitmap = self.bitmapProvider.GetBitmap(frameId) lastBitmaps[i] = bitmap else: if i not in lastBitmaps: lastBitmaps[i] = wx.NullBitmap() else: bitmap = self.bitmapProvider.GetBitmap(frameId) lastBitmaps[i] = bitmap im = ImageFromBitmap(lastBitmaps[i]) # add legend if used legend = legends[i] if legend: legendBitmap = self.bitmapProvider.LoadOverlay(legend) x, y = self.mapwindows[i].GetOverlayPos() legImage = ImageFromBitmap(legendBitmap) # not so nice result, can we handle the transparency # otherwise? legImage.ConvertAlphaToMask() im.Paste(legImage, x, y) if im.GetSize() != animWinSize[i]: im.Rescale(*animWinSize[i]) image.Paste(im, *animWinPos[i]) # paste decorations for decoration in decorations: # add image x = decoration["pos"][0] / 100.0 * size[0] y = decoration["pos"][1] / 100.0 * size[1] if decoration["name"] == "image": decImage = wx.Image(decoration["file"]) elif decoration["name"] == "time": timeLabel = timeLabels[frameIndex] if timeLabel[1]: # interval text = _("%(from)s %(dash)s %(to)s") % { "from": timeLabel[0], "dash": "\u2013", "to": timeLabel[1], } else: if (self.temporalManager.GetTemporalType() == TemporalType.ABSOLUTE): text = timeLabel[0] else: text = _("%(start)s %(unit)s") % { "start": timeLabel[0], "unit": timeLabel[2], } decImage = RenderText(text, decoration["font"], bgcolor, fgcolor).ConvertToImage() elif decoration["name"] == "text": text = decoration["text"] decImage = RenderText(text, decoration["font"], bgcolor, fgcolor).ConvertToImage() image.Paste(decImage, x, y) images.append(image) del busy # export pilImages = [WxImageToPil(image) for image in images] self.busy = wx.BusyInfo(_("Exporting animation, please wait..."), parent=self.frame) wx.GetApp().Yield() try: def export_avi_callback(event): error = event.ret del self.busy if error: GError(parent=self.frame, message=error) return if exportInfo["method"] == "sequence": filename = os.path.join( exportInfo["directory"], exportInfo["prefix"] + "." + exportInfo["format"].lower(), ) writeIms(filename=filename, images=pilImages) elif exportInfo["method"] == "gif": writeGif( filename=exportInfo["file"], images=pilImages, duration=self.timeTick / float(1000), repeat=True, ) elif exportInfo["method"] == "swf": writeSwf( filename=exportInfo["file"], images=pilImages, duration=self.timeTick / float(1000), repeat=True, ) elif exportInfo["method"] == "avi": thread = gThread() thread.Run( callable=writeAvi, filename=exportInfo["file"], images=pilImages, duration=self.timeTick / float(1000), encoding=exportInfo["encoding"], inputOptions=exportInfo["options"], bg_task=True, ondone=export_avi_callback, ) except Exception as e: del self.busy GError(parent=self.frame, message=str(e)) return if exportInfo["method"] in ("sequence", "gif", "swf"): del self.busy
def errMsg(self, label): print(label) GError(label)
def export_avi_callback(event): error = event.ret del self.busy if error: GError(parent=self.frame, message=error) return
def StartEditing(self, mapLayer): """Start editing selected vector map layer. :param mapLayer: MapLayer to be edited """ # check if topology is available (skip for hidden - temporary # maps, see iclass for details) if ( not mapLayer.IsHidden() and grass.vector_info(mapLayer.GetName())["level"] != 2 ): dlg = wx.MessageDialog( parent=self.MapWindow, message=_( "Topology for vector map <%s> is not available. " "Topology is required by digitizer.\nDo you want to " "rebuild topology (takes some time) and open the vector map " "for editing?" ) % mapLayer.GetName(), caption=_("Digitizer error"), style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION | wx.CENTRE, ) if dlg.ShowModal() == wx.ID_YES: RunCommand("v.build", map=mapLayer.GetName()) else: return # deactive layer self.Map.ChangeLayerActive(mapLayer, False) # clean map canvas self.MapWindow.EraseMap() # unset background map if needed if mapLayer: if ( UserSettings.Get( group="vdigit", key="bgmap", subkey="value", settings_type="internal", ) == mapLayer.GetName() ): UserSettings.Set( group="vdigit", key="bgmap", subkey="value", value="", settings_type="internal", ) self.parent.SetStatusText( _("Please wait, " "opening vector map <%s> for editing...") % mapLayer.GetName(), 0, ) self.MapWindow.pdcVector = PseudoDC() self.digit = self.MapWindow.digit = self.digitClass(mapwindow=self.MapWindow) self.mapLayer = mapLayer # open vector map (assume that 'hidden' map layer is temporary vector # map) if self.digit.OpenMap(mapLayer.GetName(), tmp=mapLayer.IsHidden()) is None: self.mapLayer = None self.StopEditing() return False # check feature type (only for OGR layers) self.fType = self.digit.GetFeatureType() self.EnableAll() self.EnableUndo(False) self.EnableRedo(False) if self.fType == "point": for tool in ( self.addLine, self.addArea, self.moveVertex, self.addVertex, self.removeVertex, self.editLine, ): self.EnableTool(tool, False) elif self.fType == "linestring": for tool in (self.addPoint, self.addArea): self.EnableTool(tool, False) elif self.fType == "polygon": for tool in (self.addPoint, self.addLine): self.EnableTool(tool, False) elif self.fType: GError( parent=self, message=_( "Unsupported feature type '%(type)s'. Unable to edit " "OGR layer <%(layer)s>." ) % {"type": self.fType, "layer": mapLayer.GetName()}, ) self.digit.CloseMap() self.mapLayer = None self.StopEditing() return False # update toolbar if self.combo: self.combo.SetValue(mapLayer.GetName()) if "map" in self.parent.toolbars: self.parent.toolbars["map"].combo.SetValue(_("Vector digitizer")) # here was dead code to enable vdigit button in toolbar # with if to ignore iclass # some signal (DigitizerStarted) can be emitted here Debug.msg(4, "VDigitToolbar.StartEditing(): layer=%s" % mapLayer.GetName()) # change cursor if self.MapWindow.mouse["use"] == "pointer": self.MapWindow.SetNamedCursor("cross") if not self.MapWindow.resize: self.MapWindow.UpdateMap(render=True) # respect opacity opacity = mapLayer.GetOpacity() if opacity < 1.0: alpha = int(opacity * 255) self.digit.GetDisplay().UpdateSettings(alpha=alpha) # emit signal layerTree = self._giface.GetLayerTree() if layerTree: item = layerTree.FindItemByData("maplayer", self.mapLayer) else: item = None self.editingStarted.emit( vectMap=mapLayer.GetName(), digit=self.digit, layerItem=item ) return True
def _pageContributors(self, extra=False): """Contributors info""" if extra: contribfile = os.path.join(os.getenv("GISBASE"), "contributors_extra.csv") else: contribfile = os.path.join(os.getenv("GISBASE"), "contributors.csv") if os.path.exists(contribfile): contribFile = codecs.open(contribfile, encoding='utf-8', mode='r') contribs = list() errLines = list() for line in contribFile.readlines()[1:]: line = line.rstrip('\n') try: if extra: name, email, country, rfc2_agreed = line.split(',') else: cvs_id, name, email, country, osgeo_id, rfc2_agreed = line.split( ',') except ValueError: errLines.append(line) continue if extra: contribs.append((name, email, country)) else: contribs.append((name, email, country, osgeo_id)) contribFile.close() if errLines: GError( parent=self, message=_("Error when reading file '%s'.") % contribfile + "\n\n" + _("Lines:") + " %s" % os.linesep.join(map(DecodeString, errLines))) else: contribs = None contribwin = ScrolledPanel(self.aboutNotebook) contribwin.SetAutoLayout(True) contribwin.SetupScrolling() contribwin.sizer = wx.BoxSizer(wx.VERTICAL) if not contribs: contribtxt = StaticText(contribwin, id=wx.ID_ANY, label=_('%s file missing') % contribfile) contribwin.sizer.Add(contribtxt, proportion=1, flag=wx.EXPAND | wx.ALL, border=3) else: if extra: items = (_('Name'), _('E-mail'), _('Country')) else: items = (_('Name'), _('E-mail'), _('Country'), _('OSGeo_ID')) contribBox = wx.FlexGridSizer(cols=len(items), vgap=5, hgap=5) for item in items: text = StaticText(parent=contribwin, id=wx.ID_ANY, label=item) text.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, "")) contribBox.Add(text) for vals in sorted(contribs, key=lambda x: x[0]): for item in vals: contribBox.Add( StaticText(parent=contribwin, id=wx.ID_ANY, label=item)) contribwin.sizer.Add(contribBox, proportion=1, flag=wx.EXPAND | wx.ALL, border=3) contribwin.SetSizer(contribwin.sizer) contribwin.Layout() return contribwin
def GetSQLString(self, updateValues=False): """Create SQL statement string based on self.sqlStatement Show error message when invalid values are entered. If updateValues is True, update dataFrame according to values in textfields. """ sqlCommands = [] # find updated values for each layer/category for layer in self.mapDBInfo.layers.keys(): # for each layer table = self.mapDBInfo.GetTable(layer) key = self.mapDBInfo.GetKeyColumn(layer) columns = self.mapDBInfo.GetTableDesc(table) for idx in range(len(columns[key]['values'])): # for each category updatedColumns = [] updatedValues = [] for name in columns.keys(): if name == key: cat = columns[name]['values'][idx] continue ctype = columns[name]['ctype'] value = columns[name]['values'][idx] id = columns[name]['ids'][idx] try: newvalue = self.FindWindowById(id).GetValue() except: newvalue = self.FindWindowById(id).GetLabel() if newvalue: try: if ctype == int: newvalue = int(newvalue) elif ctype == float: newvalue = float(newvalue) except ValueError: GError( parent=self, message= _("Column <%(col)s>: Value '%(value)s' needs to be entered as %(type)s." ) % { 'col': name, 'value': str(newvalue), 'type': columns[name]['type'].lower() }, showTraceback=False) sqlCommands.append(None) continue else: if self.action == 'add': continue if newvalue != value: updatedColumns.append(name) if newvalue == '': updatedValues.append('NULL') else: if ctype != str: updatedValues.append(str(newvalue)) else: updatedValues.append( "'" + newvalue.replace("'", "''") + "'") columns[name]['values'][idx] = newvalue if self.action != "add" and len(updatedValues) == 0: continue if self.action == "add": sqlString = "INSERT INTO %s (%s," % (table, key) else: sqlString = "UPDATE %s SET " % table for idx in range(len(updatedColumns)): name = updatedColumns[idx] if self.action == "add": sqlString += name + "," else: sqlString += name + "=" + updatedValues[idx] + "," sqlString = sqlString[:-1] # remove last comma if self.action == "add": sqlString += ") VALUES (%s," % cat for value in updatedValues: sqlString += value + "," sqlString = sqlString[:-1] # remove last comma sqlString += ")" else: sqlString += " WHERE %s=%s" % (key, cat) sqlCommands.append(sqlString) # for each category # for each layer END Debug.msg(3, "DisplayAttributesDialog.GetSQLString(): %s" % sqlCommands) return sqlCommands
def _getData(self, timeseries): """Load data and read properties""" self.timeData = {} mode = None unit = None for series in timeseries: name = series[0] + '@' + series[1] etype = series[2] sp = tgis.dataset_factory(etype, name) if not sp.is_in_db(dbif=self.dbif): GError( self, message=_("Dataset <%s> not found in temporal database") % (name)) return sp.select(dbif=self.dbif) self.timeData[name] = {} self.timeData[name]['elementType'] = series[2] self.timeData[name][ 'temporalType'] = sp.get_temporal_type() # abs/rel if mode is None: mode = self.timeData[name]['temporalType'] elif self.timeData[name]['temporalType'] != mode: GError( parent=self, message=_( "Datasets have different temporal type " "(absolute x relative), which is not allowed.")) return # check topology maps = sp.get_registered_maps_as_objects(dbif=self.dbif) self.timeData[name]['validTopology'] = sp.check_temporal_topology( maps=maps, dbif=self.dbif) self.timeData[name][ 'temporalMapType'] = sp.get_map_time() # point/interval self.timeData[name]['unit'] = None # only with relative if self.timeData[name]['temporalType'] == 'relative': start, end, self.timeData[name][ 'unit'] = sp.get_relative_time() if unit is None: unit = self.timeData[name]['unit'] elif self.timeData[name]['unit'] != unit: GError( self, _("Datasets have different time unit which is not allowed.")) return self.timeData[name]['start_datetime'] = [] # self.timeData[name]['start_plot'] = [] self.timeData[name]['end_datetime'] = [] # self.timeData[name]['end_plot'] = [] self.timeData[name]['names'] = [] self.timeData[name]['north'] = [] self.timeData[name]['south'] = [] self.timeData[name]['west'] = [] self.timeData[name]['east'] = [] columns = ','.join(['name', 'start_time', 'end_time', 'north', 'south', 'west', 'east']) rows = sp.get_registered_maps(columns=columns, where=None, order='start_time', dbif=self.dbif) if not rows: GError( parent=self, message=_("Dataset <{name}> is empty").format( name=series[0] + '@' + series[1])) return for row in rows: mapName, start, end, north, south, west, east = row self.timeData[name]['start_datetime'].append(start) self.timeData[name]['end_datetime'].append(end) self.timeData[name]['names'].append(mapName) self.timeData[name]['north'].append(north) self.timeData[name]['south'].append(south) self.timeData[name]['west'].append(west) self.timeData[name]['east'].append(east) self.temporalType = mode self.unit = unit
def _pageTranslators(self): """Translators info""" translatorsfile = os.path.join(os.getenv("GISBASE"), "translators.csv") if os.path.exists(translatorsfile): translatorsFile = codecs.open(translatorsfile, encoding='utf-8', mode='r') translators = dict() errLines = list() for line in translatorsFile.readlines()[1:]: line = line.rstrip('\n') try: name, email, languages = line.split(',') except ValueError: errLines.append(line) continue for language in languages.split(' '): if language not in translators: translators[language] = list() translators[language].append((name, email)) translatorsFile.close() if errLines: GError(parent=self, message=_("Error when reading file '%s'.") % translatorsfile + "\n\n" + _("Lines:") + " %s" % os.linesep.join(map(DecodeString, errLines))) else: translators = None translatorswin = ScrolledPanel(self.aboutNotebook) translatorswin.SetBackgroundColour('WHITE') translatorswin.SetAutoLayout(True) translatorswin.SetupScrolling() translatorswin.sizer = wx.BoxSizer(wx.VERTICAL) if not translators: translatorstxt = StaticText(translatorswin, id=wx.ID_ANY, label=_('%s file missing') % 'translators.csv') translatorswin.sizer.Add(translatorstxt, proportion=1, flag=wx.EXPAND | wx.ALL, border=3) else: translatorsBox = wx.FlexGridSizer(cols=4, vgap=5, hgap=5) languages = sorted(translators.keys()) tname = StaticText(parent=translatorswin, id=wx.ID_ANY, label=_('Name')) tname.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, "")) translatorsBox.Add(tname) temail = StaticText(parent=translatorswin, id=wx.ID_ANY, label=_('E-mail')) temail.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, "")) translatorsBox.Add(temail) tlang = StaticText(parent=translatorswin, id=wx.ID_ANY, label=_('Language')) tlang.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, "")) translatorsBox.Add(tlang) tnat = StaticText(parent=translatorswin, id=wx.ID_ANY, label=_('Nation')) tnat.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, "")) translatorsBox.Add(tnat) for lang in languages: for translator in translators[lang]: name, email = translator translatorsBox.Add( StaticText(parent=translatorswin, id=wx.ID_ANY, label=name)) translatorsBox.Add( StaticText(parent=translatorswin, id=wx.ID_ANY, label=email)) translatorsBox.Add( StaticText(parent=translatorswin, id=wx.ID_ANY, label=lang)) flag = os.path.join(globalvar.ICONDIR, "flags", "%s.png" % lang.lower()) if os.path.exists(flag): flagBitmap = wx.StaticBitmap( translatorswin, wx.ID_ANY, wx.Bitmap(name=flag, type=wx.BITMAP_TYPE_PNG)) translatorsBox.Add(flagBitmap) else: translatorsBox.Add( StaticText(parent=translatorswin, id=wx.ID_ANY, label=lang)) translatorswin.sizer.Add(translatorsBox, proportion=1, flag=wx.EXPAND | wx.ALL, border=3) translatorswin.SetSizer(translatorswin.sizer) translatorswin.Layout() return translatorswin