[GRASS-SVN] r61595 - in grass-addons/grass7/gui/wxpython/wx.metadata: . g.gui.metadata mdlib r.info.iso v.info.iso
svn_grass at osgeo.org
svn_grass at osgeo.org
Wed Aug 13 13:15:41 PDT 2014
Author: martinl
Date: 2014-08-13 13:15:41 -0700 (Wed, 13 Aug 2014)
New Revision: 61595
Added:
grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/
grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/editor.py
grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/g.gui.metadata.html
grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/g.gui.metadata.py
grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/
grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/jinjainfo.py
grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/mdgrass.py
grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/mdutil.py
grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso/
grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso/r.info.iso.html
grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso/r.info.iso.py
grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso/
grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso/v.info.iso.html
grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso/v.info.iso.py
Removed:
grass-addons/grass7/gui/wxpython/wx.metadata/editor.py
grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata.html
grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata.py
grass-addons/grass7/gui/wxpython/wx.metadata/jinjainfo.py
grass-addons/grass7/gui/wxpython/wx.metadata/mdgrass.py
grass-addons/grass7/gui/wxpython/wx.metadata/mdutil.py
grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso.html
grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso.py
grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso.html
grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso.py
Log:
wx.metadata: reorganization into dirs (first step for adding Makefiles, work in progress)
Deleted: grass-addons/grass7/gui/wxpython/wx.metadata/editor.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/editor.py 2014-08-13 15:54:00 UTC (rev 61594)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/editor.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -1,1349 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8
-"""
- at package editor
- at module g.gui.metadata
- at brief base editor, read/write ISO metadata, generator of widgets in editor
-
-Classes:
- - editor::MdFileWork
- - editor::MdBox
- - editor::MdWxDuplicator
- - editor::MdItem
- - editor::MdNotebookPage
- - editor::MdMainEditor
-
-(C) 2014 by 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.
-
- at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
-"""
-import re
-import os
-import sys
-import contextlib
-from lxml import etree
-
-import wx
-from wx import ID_ANY
-from wx import EVT_BUTTON
-import wx.lib.scrolledpanel as scrolled
-
-from owslib.iso import *
-from jinjainfo import JinjaTemplateParser
-from jinja2 import Environment, FileSystemLoader
-
-from core.gcmd import RunCommand, GError, GMessage
-from gui_core.widgets import IntegerValidator, NTCValidator, SimpleValidator,\
- TimeISOValidator, EmailValidator # ,EmptyValidator
-import mdutil
-
-#=========================================================================
-# MD filework
-#=========================================================================
-
-
-class MdFileWork():
-
- ''' initializer of metadata in OWSLib and export OWSLib object to xml by jinja templating system
- '''
-
- def __init__(self, pathToXml=None):
- self.path = pathToXml
- self.owslibInfo = None
-
- def initMD(self, path=None):
- '''
- @brief initialize metadata
- @param path: path to xml
- @return: initialized md object by input xml
- '''
- if path is None:
- self.md = MD_Metadata(md=None)
- return self.md
- else:
- io = open(path, 'r')
- str1 = ''
- for line in io.readlines():
- str1 += mdutil.removeNonAscii(line)
- io.close()
- io1 = open(path, 'w')
- io1.write(str1)
- io1.close()
-
- try:
- tree = etree.parse(path)
- root = tree.getroot()
- self.md = MD_Metadata(root)
-
- return self.md
-
- except Exception, e:
- GError('Error loading xml:\n' + str(e))
-
- def saveToXML(self, md, owsTagList, jinjaPath, outPath=None, xmlOutName=None, msg=True, rmTeplate=False):
- '''
- @note creator of xml with using OWSLib md object and jinja template
- @param md: owslib.iso.MD_Metadata
- @param owsTagList: in case if user definig template
- @param jinjaPath: path to jinja template
- @param outPath: path of exported xml
- @param xmlOutName: name of exported xml
- @param msg: gmesage info after export
- @param rmTeplate: remove template after use
- @return: initialized md object by input xml
- '''
- # if output file name is None, use map name and add postfix
- self.dirpath = os.path.dirname(os.path.realpath(__file__))
- self.md = md
- self.owsTagList = owsTagList
-
- if xmlOutName is None:
- xmlOutName = 'RANDExportMD' # TODO change to name of map
- if not xmlOutName.lower().endswith('.xml'):
- xmlOutName += '.xml'
- # if path is None, use lunch. dir
- # TODO change default folder to mapset location
- if not outPath:
- outPath = os.path.join(self.dirpath, xmlOutName)
- else:
- outPath = os.path.join(outPath, xmlOutName)
- xml = open(jinjaPath, 'r')
-
- str1 = ''
- for line in xml.readlines():
- line = mdutil.removeNonAscii(line)
- str1 += line
- xml.close
- io = open(jinjaPath, 'w')
- io.write(str1)
- io.close()
-
- # generating xml using jinja tempaltes
- head, tail = os.path.split(jinjaPath)
- env = Environment(loader=FileSystemLoader(head))
- env.globals.update(zip=zip)
- template = env.get_template(tail)
- if self.owsTagList is None:
- iso_xml = template.render(md=self.md)
- else:
- iso_xml = template.render(md=self.md, owsTagList=self.owsTagList)
- xml_file = xmlOutName
-
- try:
- xml_file = open(outPath, "w")
- xml_file.write(iso_xml)
- xml_file.close()
-
- if msg:
- GMessage('File exported to: %s' % outPath)
-
- if rmTeplate:
- os.remove(jinjaPath)
-
- return outPath
-
- except Exception, e:
- GError('Error writing xml:\n' + str(e))
-
-#=========================================================================
-# CREATE BOX (staticbox+button(optional)
-#=========================================================================
-
-
-class MdBox(wx.Panel):
-
- '''widget(static box) which include metadata items (MdItem)
- '''
-
- def __init__(self, parent, label='label'):
- wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
- self.label = label
- self.mdItems = list()
- self.stbox = wx.StaticBox(self, label=label, id=ID_ANY, style=wx.RAISED_BORDER)
- self.stbox.SetForegroundColour((0, 0, 0))
- self.stbox.SetBackgroundColour((200, 200, 200))
- self.stbox.SetFont(wx.Font(12, wx.NORMAL, wx.NORMAL, wx.NORMAL))
-
- def addItems(self, items, multi=True, rmMulti=False, isFirstNum=-1):
- '''
- @param items: editor::MdItems
- @param multi: true in case when box has button for duplicating box and included items
- @param rmMulti: true in case when box has button for removing box and included items
- @param isFirstNum: handling with 'add' and 'remove' button of box.
- this param is necessary for generating editor in editor::MdEditor.generateGUI.inBlock()
- note: just firs generated box has 'add' buton (because is mandatory) and nex others has
- 'remove butt'
- '''
- if isFirstNum != 1:
- multi = False
- rmMulti = True
-
- # if not initialize in jinja template (default is true)
- if multi is None:
- multi = True
-
- self.panelSizer = wx.BoxSizer(wx.VERTICAL)
- self.SetSizer(self.panelSizer)
-
- self.boxButtonSizer = wx.BoxSizer(wx.HORIZONTAL)
-
- self.panelSizer.AddSpacer(10, 10, 1, wx.EXPAND)
- self.panelSizer.Add(self.boxButtonSizer, flag=wx.EXPAND, proportion=1)
-
- self.stBoxSizer = wx.StaticBoxSizer(self.stbox, orient=wx.VERTICAL)
- self.boxButtonSizer.Add(self.stBoxSizer, flag=wx.EXPAND, proportion=1)
-
- for item in items:
- self.mdItems.append(item)
- self.stBoxSizer.Add(item, flag=wx.EXPAND, proportion=1)
- self.stBoxSizer.AddSpacer(5, 5, 1, wx.EXPAND)
-
- if multi:
- self.addBoxButt = wx.Button(self, id=ID_ANY, size=(30, 30), label='+')
- self.boxButtonSizer.Add(self.addBoxButt, 0)
- self.addBoxButt.Bind(EVT_BUTTON, self.duplicateBox)
-
- if rmMulti:
- self.rmBoxButt = wx.Button(self, id=ID_ANY, size=(30, 30), label='-')
- self.boxButtonSizer.Add(self.rmBoxButt, 0)
- self.rmBoxButt.Bind(EVT_BUTTON, self.removeBox)
-
- def addDuplicatedItem(self, item):
- self.stBoxSizer.Add(item, flag=wx.EXPAND, proportion=1)
- self.stBoxSizer.AddSpacer(5, 5, 1, wx.EXPAND)
- self.GetParent().Layout()
-
- def getCtrlID(self):
- return self.GetId()
-
- def removeBox(self, evt):
- for item in self.mdItems:
- item.mdDescription.removeMdItem(item)
- self.GetParent().removeBox(self)
-
- def removeMdItem(self, mdItem, items):
- '''
- @param mdItem: object editor::MdItem
- @param items: widgets to destroy
- '''
- mdItem.mdDescription.removeMdItem(mdItem)
- for item in items:
- try:
- item.Destroy()
- except:
- pass
- self.stBoxSizer.RemovePos(-1) # remove wxSpacer
- self.stBoxSizer.Remove(mdItem)
- self.GetParent().Layout()
-
- def duplicateBox(self, evt):
- duplicator = MdWxDuplicator(self.mdItems, self.GetParent(), self.label)
- clonedBox = duplicator.mdBox
- self.GetParent().addDuplicatedItem(clonedBox, self.GetId())
-
-#===============================================================================
-# DUPLICATOR OF WIDGETS-mditem
-#===============================================================================
-
-
-class MdWxDuplicator():
-
- '''duplicator of MdBox and MdItem object
- '''
-
- def __init__(self, mdItems, parent, boxlabel=None, mdItemOld=None, template=None):
- '''
- @param mdItems: list of editor::MdItem
- @param parent: parent of new duplicated box
- @param boxlabel: label of static box
- @param mdItemOld: object which will be duplicated
- @param template: in case if 'template mode' is on in editor
- '''
- # duplicate box of items
- if boxlabel:
- itemList = list()
- self.mdBox = MdBox(parent, boxlabel)
- for i in mdItems:
- try: # check if item has multiple button
- i.addItemButt.GetLabel()
- multi = True
- except:
- multi = False
- try: # check if chckBoxEdit exists
- i.chckBoxEdit.GetValue()
- template = True
- except:
- template = False
-
- i = i.mdDescription # var mdDescription is jinjainfo::MdDescription
- mdItem1 = MdItem(parent=self.mdBox,
- item=i,
- multiplicity=multi,
- isFirstNum=1,
- chckBox=template)
-
- itemList.append(mdItem1)
-
- i.addMdItem(mdItem1) # add item with using jinjainfo::MDescription
- self.mdBox.addItems(itemList, False, True) # fill box
-
- else: # duplicate only MdItem
- self.mdItem = MdItem(parent=parent,
- item=mdItems,
- multiplicity=False,
- rmMulti=True,
- isFirstNum=-1,
- chckBox=template)
-
- try:
- if mdItems.inbox is not None:
- mdItems.addMdItem(self.mdItem, mdItemOld)
- else:
- mdItems.addMdItem(self.mdItem)
- except:
- mdItems.addMdItem(self.mdItem)
-#=========================================================================
-# METADATA ITEM (label+ctrlText+button(optional)+chckbox(template)
-#=========================================================================
-
-
-class MdItem(wx.BoxSizer):
-
- '''main building blocks of generated gui of editor
- '''
-
- def __init__(self, parent, item, multiplicity=None, rmMulti=False, isFirstNum=-1, chckBox=False):
- '''
- @param item: jinjainfo::MdDescription(initialized by parsing information from jinja template)
- @param multiplicity: if true- widget has button for duplicate self
- @param rmMulti: if true- widget has button for remove self
- @param isFirstNum: handling with 'add' and 'remove' button of box.
- this param is necessary for generating editor in editor::MdEditor.generateGUI.inBlock()
- note: just firs generated box has 'add' buton (because is mandatory) and nex others has
- 'remove butt'
- @param chckBox: in case-True 'template editor' is on and widget has checkobox.
- '''
- wx.BoxSizer.__init__(self, wx.VERTICAL)
- self.isValid = False
- self.isChecked = False
- self.mdDescription = item
- self.chckBox = chckBox
- self.multiple = multiplicity
-
- if multiplicity is None:
- self.multiple = item.multiplicity
-
- if isFirstNum != 1:
- self.multiple = False
-
- if isFirstNum != 1 and item.multiplicity:
- rmMulti = True
-
- self.tagText = wx.StaticText(parent=parent, id=ID_ANY, label=item.name)
-
- if self.chckBox == False:
- if item.multiline is True:
- self.valueCtrl = wx.TextCtrl(parent, id=ID_ANY, size=(0, 70),
- validator=self.validators(item.type),
- style=wx.VSCROLL |
- wx.TE_MULTILINE | wx.TE_WORDWRAP |
- wx.TAB_TRAVERSAL | wx.RAISED_BORDER)
- else:
- self.valueCtrl = wx.TextCtrl(parent, id=wx.ID_ANY,
- validator=self.validators(item.type),
- style=wx.VSCROLL | wx.TE_DONTWRAP |
- wx.TAB_TRAVERSAL | wx.RAISED_BORDER | wx.HSCROLL)
- else:
- if item.multiline is True:
- self.valueCtrl = wx.TextCtrl(parent, id=ID_ANY, size=(0, 70),
- style=wx.VSCROLL |
- wx.TE_MULTILINE | wx.TE_WORDWRAP |
- wx.TAB_TRAVERSAL | wx.RAISED_BORDER)
- else:
- self.valueCtrl = wx.TextCtrl(parent, id=wx.ID_ANY,
- style=wx.VSCROLL | wx.TE_DONTWRAP |
- wx.TAB_TRAVERSAL | wx.RAISED_BORDER | wx.HSCROLL)
-
- self.valueCtrl.Bind(wx.EVT_MOTION, self.onMove)
- self.valueCtrl.SetExtraStyle(wx.WS_EX_VALIDATE_RECURSIVELY)
-
- if self.multiple:
- self.addItemButt = wx.Button(parent, -1, size=(30, 30), label='+')
- self.addItemButt.Bind(EVT_BUTTON, self.duplicateItem)
-
- if rmMulti:
- self.rmItemButt = wx.Button(parent, -1, size=(30, 30), label='-')
- self.rmItemButt.Bind(EVT_BUTTON, self.removeItem)
-
- if self.chckBox:
- self.chckBoxEdit = wx.CheckBox(parent, -1, size=(30, 30))
- self.chckBoxEdit.Bind(wx.EVT_CHECKBOX, self.onChangeChckBox)
- self.chckBoxEdit.SetValue(False)
- self.isChecked = False
- self.valueCtrl.Disable()
-
- self.createInfo()
- self.tip = wx.ToolTip(self.infoTip)
-
- self._addItemLay(item.multiline, rmMulti)
-
- def validators(self, validationStyle):
-
- if validationStyle == 'email':
- return EmailValidator()
-
- if validationStyle == 'integer':
- return NTCValidator('DIGIT_ONLY')
-
- if validationStyle == 'decimal':
- return NTCValidator('DIGIT_ONLY')
-
- if validationStyle == 'date':
- return TimeISOValidator()
-
- # return EmptyValidator()
- return SimpleValidator('')
-
- def onChangeChckBox(self, evt):
- '''current implementation of editor mode for defining templates not allowed to check
- only single items in static box. There are two cases: all items in box are checked or not.
- '''
- if self.mdDescription.inbox: # MdItems are in box
- try:
- items = self.valueCtrl.GetParent().mdItems
- if self.isChecked:
- self.valueCtrl.Disable()
- self.isChecked = False
- else:
- self.valueCtrl.Enable()
- self.isChecked = True
-
- for item in items:
- if self.isChecked:
- item.valueCtrl.Enable()
- item.chckBoxEdit.SetValue(True)
- item.isChecked = True
- else:
- item.valueCtrl.Disable()
- item.chckBoxEdit.SetValue(False)
- item.isChecked = False
- except:
- pass
- else:
- if self.isChecked:
- self.valueCtrl.Disable()
- self.isChecked = False
- else:
- self.valueCtrl.Enable()
- self.isChecked = True
-
- def onMove(self, evt=None):
- self.valueCtrl.SetToolTip(self.tip)
-
- def createInfo(self):
- """Feed for tooltip
- """
- string = ''
- if self.mdDescription.ref is not None:
- string += self.mdDescription.ref + '\n\n'
- if self.mdDescription.name is not None:
- string += 'NAME: \n' + self.mdDescription.name + '\n\n'
- if self.mdDescription.desc is not None:
- string += 'DESCRIPTION: \n' + self.mdDescription.desc + '\n\n'
- if self.mdDescription.example is not None:
- string += 'EXAMPLE: \n' + self.mdDescription.example + '\n\n'
- if self.mdDescription.type is not None:
- string += 'DATA TYPE: \n' + self.mdDescription.type + '\n\n'
- string += '*' + '\n'
- if self.mdDescription.statements is not None:
- string += 'Jinja template info: \n' + self.mdDescription.statements + '\n'
-
- if self.mdDescription.statements1 is not None:
- string += self.mdDescription.statements1 + '\n'
- string += 'OWSLib info:\n' + self.mdDescription.tag
- self.infoTip = string
-
- def removeItem(self, evt):
- """adding all items in self(mdItem) to list and call parent remover
- """
- ilist = [self.valueCtrl, self.tagText]
- try:
- ilist.append(self.rmItemButt)
- except:
- pass
- try:
- ilist.append(self.chckBoxEdit)
- except:
- pass
- self.valueCtrl.GetParent().removeMdItem(self, ilist)
-
- def duplicateItem(self, evt):
- '''add Md item to parent(box or notebook page)
- '''
- parent = self.valueCtrl.GetParent()
- # if parent is box
- if self.mdDescription.inbox:
- duplicator = MdWxDuplicator(mdItems=self.mdDescription,
- parent=parent,
- mdItemOld=self,
- template=self.chckBox)
- else:
- duplicator = MdWxDuplicator(mdItems=self.mdDescription,
- parent=parent,
- template=self.chckBox)
-
- clonedMdItem = duplicator.mdItem
- # call parent "add" function
- self.valueCtrl.GetParent().addDuplicatedItem(clonedMdItem, self.valueCtrl.GetId())
-
- def setValue(self, value):
- '''Set value & color of widgets
- in case if is template creator 'on':
- yellow: in case if value is marked by $NULL(by mdgrass::GrassMD)
- red: if value is '' or object is not initialized. e.g. if user
- read non fully valid INSPIRE xml with INSPIRE jinja template,
- the gui generating mechanism will create GUI according to template
- and all missing tags(xml)-gui(TextCtrls) will be marked by red
- '''
- if value is None or value is '':
- if self.chckBox:
- self.chckBoxEdit.SetValue(True)
- self.isChecked = True
- try:
- self.onChangeChckBox(None)
- self.onChangeChckBox(None)
- except:
- pass
- self.valueCtrl.SetBackgroundColour((245, 204, 230)) # red
-
- self.valueCtrl.SetValue('')
- self.valueCtrl.Enable()
-
- elif self.chckBox and value == '$NULL':
- self.valueCtrl.SetBackgroundColour((255, 255, 82)) # yellow
- self.valueCtrl.SetValue('')
-
- if self.chckBox:
- self.chckBoxEdit.SetValue(True)
- self.isChecked = True
- self.valueCtrl.Enable()
- try:
- self.onChangeChckBox(None)
- self.onChangeChckBox(None)
- except:
- pass
-
- elif value == '$NULL':
- self.valueCtrl.SetValue('')
-
- else:
- self.isValid = True
- self.valueCtrl.SetValue(value)
-
- def getValue(self):
-
- value = mdutil.replaceXMLReservedChar(self.valueCtrl.GetValue())
- value = value.replace('\n', '')
- value = value.replace('"', '')
- value = value.replace("'", '')
- return value
-
- def getCtrlID(self):
- return self.valueCtrl.GetId()
-
- def _addItemLay(self, multiline, rmMulti):
- self.textFieldSizer = wx.BoxSizer(wx.HORIZONTAL)
- if multiline is True:
- self.textFieldSizer.Add(self.valueCtrl, proportion=1, flag=wx.EXPAND)
- else:
- self.textFieldSizer.Add(self.valueCtrl, proportion=1)
-
- if self.multiple:
- self.textFieldSizer.Add(self.addItemButt, 0)
-
- if rmMulti:
- self.textFieldSizer.Add(self.rmItemButt, 0)
-
- if self.chckBox:
- self.textFieldSizer.Add(self.chckBoxEdit, 0)
-
- self.Add(item=self.tagText, proportion=0)
- self.Add(item=self.textFieldSizer, proportion=0, flag=wx.EXPAND)
-
-#=========================================================================
-# ADD NOTEBOOK PAGE
-#=========================================================================
-
-
-class MdNotebookPage(scrolled.ScrolledPanel):
-
- """
- every notebook page is initialized by jinjainfo::MdDescription.group (label)
- """
-
- def __init__(self, parent):
- scrolled.ScrolledPanel.__init__(self, parent=parent, id=wx.ID_ANY)
- self.items = []
- self.SetupScrolling()
- self._addNotebookPageLay()
- self.sizerIndexDict = {}
- self.sizerIndex = 0
-
- def _addNotebookPageLay(self):
- self.mainSizer = wx.BoxSizer(wx.VERTICAL)
- self.SetSizer(self.mainSizer)
-
- def _getIndex(self):
- '''
- index for handling position of editor::MdBox,MdItem in editor::MdNotebookPage(self).
- Primary for correct duplicating Boxes or items on notebook page
- '''
- self.sizerIndex += 1
- return self.sizerIndex
-
- def addItem(self, item):
- '''
- @param item: can be editor::MdBox or editor::MDItem
- '''
- if isinstance(item, list):
- for i in item:
- if isinstance(i, list):
- for ii in i:
- self.sizerIndexDict[ii.getCtrlID()] = self._getIndex()
- self.mainSizer.Add(ii, proportion=0, flag=wx.EXPAND)
- else:
- self.sizerIndexDict[i.getCtrlID()] = self._getIndex()
- self.mainSizer.Add(i, proportion=0, flag=wx.EXPAND)
- else:
- self.sizerIndexDict[item.getCtrlID()] = self._getIndex()
- self.mainSizer.Add(item, proportion=0, flag=wx.EXPAND)
-
- def addDuplicatedItem(self, item, mId):
- '''adding duplicated object to sizer to position after parent
- '''
- self.items.append(item)
- posIndex = self.sizerIndexDict[mId]
- self.mainSizer.Insert(posIndex, item, proportion=0, flag=wx.EXPAND)
- self.SetSizerAndFit(self.mainSizer)
- self.GetParent().Refresh()
-
- def removeBox(self, box):
- box.Destroy()
- self.SetSizerAndFit(self.mainSizer)
-
- def removeMdItem(self, mdDes, items):
- '''Remove children
- @param mdDes: editor::MdItem.mdDescription
- @param items: all widgets to remove of MdItem
- '''
- mdDes.mdDescription.removeMdItem(mdDes) # remove from jinjainfi:MdDEscription object
- for item in items:
- item.Destroy()
- self.SetSizerAndFit(self.mainSizer)
-
-#=========================================================================
-# MAIN FRAME
-#=========================================================================
-
-
-class MdMainEditor(wx.Panel):
-
- '''
- main functions : self.generateGUI(): generating GUI from: editor:MdItem,MdBox,MdNotebookPage
- self.createNewMD(): filling OWSLib.iso.MD_Metadata by values from generated gui
- self.defineTemplate(): creator of predefined templates in template editor mode
- '''
-
- def __init__(self, parent, templatePath, xmlMdPath, templateEditor=False):
- '''
- @param templatePath: path to jinja template for generating gui of editor
- @param xmlMdPath: path of xml for init Editor
- @param templateEditor: mode-creator of template
- '''
- wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
- self.mdo = MdFileWork()
- self.md = self.mdo.initMD(xmlMdPath)
- self.templateEditor = templateEditor
- self.templatePath = templatePath
-
- self.jinj = JinjaTemplateParser(self.templatePath)
- # list of object MdDescription
- self.mdDescription = self.jinj.mdDescription
- # string of tags from jinja template (loops and OWSLib objects)
- self.mdOWSTagStr = self.jinj.mdOWSTagStr
- self.mdOWSTagStrList = self.jinj.mdOWSTagStrList #
-
- self.generateGUI()
- self._layout()
-
-#----------------------------------------------------------- GUI GENERATOR START
- def executeStr(self, stri, mdDescrObj):
- '''note- exec cannot be in sub function
- for easy understanding to product of self.generateGUI()- print stri
- '''
- # print stri
- exec stri
-
- def plusC(self, num=None):
- '''iterator for handling jinja teplate items in self.generateGUI and self.createNewMD
-
- '''
- if num is None:
- num = 1
- self.c += num
- if self.c >= self.max:
- self.c -= 1 # ensure to'list out of bounds'
- self.stop = True
-
- def minusC(self, num=None):
- '''iterator for handling jinja teplate items in self.generateGUI and self.createNewMD
- '''
- if num is None:
- num = 1
- self.c -= num
- if self.c <= self.max:
- self.stop = False
-
- def generateGUI(self):
- '''
- @var tagStringLst: tagStringLst is self.mdOWSTagStr in list.
- Item=line from jinja template(only lines with owslib objects and loops)
- @var mdDescrObj: list of MdDescription() objects inicialized\
- by information from jinja t.
- @var self.c: index of var: tagStringLst and var: self.mdDescription
- @var markgroup: markers of created list in GUI notebook
- @var self.max: length of tagStringLst and mdDescrObj
- @var self.stop: index self.c is increasing by function plusC(),\
- that care about not exceeding the index
- HINT: print param stri in self.executeStr()
- '''
- def prepareStatements():
- '''in jinja template are difining some py-function specificaly:
- e.g. |length=len
- also statements with pythonic 'zip' must be prepare specifically for generator of GUI
- '''
- for c in range(self.max):
- if '|length' in str(tagStringLst[c]):
- a = tagStringLst[c]
- a = a.replace('|length', ')').replace('if ', 'if len(self.')
- tagStringLst[c] = a
- if 'zip(' in tagStringLst[c]:
- sta = tagStringLst[c]
- tagStringLst[c] = sta.replace('md.', 'self.md.')
-
- def chckIfJumpToLoop(sta):
- '''if loaded xml not include tags(OWSLib object) from jinja template, this function will
- generate sample of item(marked by red in GUI-template mode).
- @note: in case of sub statements e.g. metadata-keywords is need to check booth statements
- @param sta: statements of the loop
- for understanding print param for self.executeStr()
- '''
- self.isValidS = False
- staTMP = sta
- if not '\t'in staTMP:
- tab = '\t'
- tab1 = ''
- staTMP = staTMP + ":\n" + tab + 'self.isValidS=True'
- else:
- tab = '\t'
- tab1 = '\t'
- staTMP = staTMP.replace('\t', '') + ":\n" + tab + 'self.isValidS=True'
-
- try: # if loop for in for
- self.executeStr(staTMP, False)
- except:
- staTMP = self.staTMP.replace('self.isValidS=True', '') + '\n\t' + staTMP.replace('\t', '\t\t')
- self.executeStr(staTMP, False)
-
- self.staTMP = staTMP
- if self.isValidS:
- return sta
- else:
- return tab1 + 'for n in range(1)'
-
- def inBlock():
- '''This part of code build string-code for executing. This can happend if is necassary to use statements
- to generate gui(OWSLib objects in list). The block of code is building from "statement" which is represended by OWSLib object.
- In case if OWSLib object is non initialized(metadata missing), function chckIfJumpToLoop() replace statements by "for n in range(1)".
- @var IFStatements: True= string is IF statements
- @var loop: current statements, mostly loop FOR
- @var str1: final string for execute
- @var box: True if editor::MdItems is in editor::MdBox
- @var isValid: True in case if OWSLib object in statement is initialized. False= statements is 'for n in range(1)'
- '''
- IFStatements = False
- statements = tagStringLst[self.c - 1]
- if 'if' in statements.split():
- IFStatements = True
- loop = statements.replace(' md.', ' self.md.')
- looptmp = chckIfJumpToLoop(loop)
- str2 = 'numOfSameBox=0\n'
- str2 += looptmp
-
- str2 += ':\n'
- str2 += '\t' + 'self.ItemList=list()\n' # initialize list
- str2 += '\t' + 'numOfSameBox+=1\n'
-
- box = False
- if self.mdDescription[self.c].inbox:
- box = True
- str2 += '\t' + 'box=MdBox(self.nbPage,mdDescrObj[' + str(self.c) + '].inbox)\n' # add box
-
- str1 = str2
- while '\t' in tagStringLst[self.c] and self.stop is False:
- if 'for' not in str(tagStringLst[self.c]).split()\
- and 'if' not in str(tagStringLst[self.c]).split():
-
- value = str(self.mdOWSTagStrList[self.c])
- str1 += '\t' + 'self.mdDescription[' + str(self.c) + "].addStatements('" + loop + "')\n"
-
- if box:
- str1 += '\t' + \
- 'it=MdItem(parent=box,item=mdDescrObj[' + str(self.c) + '],isFirstNum=numOfSameBox,chckBox=self.templateEditor)\n'
- else:
- str1 += '\t' + \
- 'it=MdItem(parent=self.nbPage,item=mdDescrObj[' + str(self.c) + '],isFirstNum=numOfSameBox,chckBox=self.templateEditor)\n'
-
- if self.isValidS: # if metatdata are loaded to owslib
- if IFStatements:
- str1 += '\t' + 'it.setValue(self.' + str(value) + ')\n'
- else:
- str1 += '\t' + 'it.setValue(' + str(value) + ')\n'
- else:
- if IFStatements:
- str1 += '\t' + 'it.setValue("")\n'
- else:
- str1 += '\t' + 'it.setValue("")\n'
-
- str1 += '\t' + 'self.mdDescription[' + str(self.c) + '].addMdItem(it)\n'
- str1 += '\t' + 'self.ItemList.append(it)\n'
- tab = '\t'
- self.plusC()
-
- else: # if statements in statements
- statements = tagStringLst[self.c]
- str2 = ''
- keyword = False
-
- if '["keywords"]' in statements:
- keyword = True
- str2 += '\t' + 'self.keywordsList=[]\n'
-
- str2 += '\t' + 'numOfSameItem=0\n'
- loop2 = statements.replace(' md.', ' self.md.')
- looptmp1 = chckIfJumpToLoop(loop2)
- str2 += looptmp1 + ':\n'
- self.plusC()
- str1 += str2
- while '\t\t' in tagStringLst[self.c] and self.stop is False:
- value = str(self.mdOWSTagStrList[self.c])
- # save information about loops
- str1 += '\t\t' + 'numOfSameItem+=1\n'
- str1 += '\t\t' + 'self.mdDescription[' + str(self.c) + "].addStatements('" + loop + "')\n"
- str1 += '\t\t' + 'self.mdDescription[' + str(self.c) + "].addStatements1('" + loop2 + "')\n"
-
- if box:
- str1 += '\t\t' + \
- 'it=MdItem(parent=box,item=mdDescrObj[' + str(self.c) + '],isFirstNum=numOfSameItem,chckBox=self.templateEditor)\n'
- else:
- str1 += '\t\t' + \
- 'it=MdItem(self.nbPage,mdDescrObj[' + str(self.c) + '],isFirstNum=numOfSameItem,chckBox=self.templateEditor)\n'
-
- if self.isValidS:
- str1 += '\t\t' + 'it.setValue(' + str(value) + ')\n'
- else:
- str1 += '\t\t' + 'it.setValue("")\n'
-
- str1 += '\t\t' + 'self.ItemList.append(it)\n'
- if keyword:
- str1 += '\t\t' + 'self.keywordsList.append(it)\n'
- str1 += '\t' + 'self.mdDescription[' + str(self.c) + '].addMdItem(self.keywordsList)\n'
- else:
- str1 += '\t\t' + 'self.mdDescription[' + str(self.c) + '].addMdItem(it)\n'
-
- tab = '\t\t'
- self.plusC()
- if box:
- str1 += tab +\
- 'box.addItems(items=self.ItemList,multi=mdDescrObj[self.c].inboxmulti,isFirstNum=numOfSameBox)\n'
- str1 += tab + 'self.nbPage.addItem(box)\n'
- else:
- str1 += tab + 'self.nbPage.addItem(self.ItemList)\n'
-
- self.executeStr(str1, mdDescrObj)
-
-#--------------------------------------------------------------------- INIT VARS
- self.notebook = wx.Notebook(self)
- markgroup = [] # notebok panel marker
- tagStringLst = self.mdOWSTagStrList
- mdDescrObj = self.mdDescription # from jinja
- self.c = 0
- self.stop = False
- self.max = len(mdDescrObj)
- prepareStatements()
- self.notebokDict = {}
-# --------------------------------------------- #START of the loop of genereator
- while self.stop is False: # self.stop is managed by def plusC(self):
- group = mdDescrObj[self.c].group
-
- if group not in markgroup: # if group is not created
- markgroup.append(group) # mark group
- self.nbPage = MdNotebookPage(self.notebook)
- self.notebook.AddPage(self.nbPage, mdDescrObj[self.c].group)
- self.notebokDict[mdDescrObj[self.c].group] = self.nbPage
- else:
- self.nbPage = self.notebokDict[mdDescrObj[self.c].group]
-
- # if statements started
- if '\t' in tagStringLst[self.c] and self.stop is False:
- inBlock()
- # if is just singe item without statements
- elif 'for' not in str(tagStringLst[self.c]).split() and 'if' not in str(tagStringLst[self.c]).split():
- it = MdItem(parent=self.nbPage, item=mdDescrObj[self.c], chckBox=self.templateEditor)
- value = 'self.' + str(self.mdOWSTagStrList[self.c]).replace('\n', '')
- value = eval(value)
- if value is None:
- value = ''
-
- it.setValue(value)
- self.mdDescription[self.c].addMdItem(it)
- self.nbPage.addItem(it)
- self.plusC()
- else:
- self.plusC()
- if self.templateEditor:
- self.refreshChkboxes()
-
- def refreshChkboxes(self):
- '''In case if template editor is on, after generateing gui si
- obligatory to refresh checkboxes
- '''
- for item in self.mdDescription:
- for i in item.mdItem:
- try:
- i.onChangeChckBox(None)
- i.onChangeChckBox(None)
- except:
- pass
-#----------------------------------------------------------- GUI GENERATOR END
-
- def defineTemplate(self):
- '''Main function for generating jinja template in mode "template editor"
- Every widget MdItem are represented by 'jinja tag'. Not checked widget= tag in jinja template will be replaced by
- listo of string with string of replaced tag. In rendering template this produce holding(non removing) jinja-tag from template.
- In case if widget is checked= rendering will replace OWSLib obect by filled values( like in normal editing mode)
- @var finalTemplate: string included final jinja template
- '''
- try:
- template = open(self.templatePath, 'r')
- except Exception, e:
- GError('Error loading template:\n' + str(e))
-
- owsTagList = list()
- indexowsTagList = 0
- finalTemplate = ''
- chcked = False
- forSTS = False
- ifSTS = False
-
- for line in template.readlines():
- if '{% for' in line:
- forSTS = True
-
- if '{% if' in line:
- ifSTS = True
-
- for r, item in enumerate(self.mdDescription):
- str1 = item.selfInfoString
- if str1 in line: # owslib definition in line
- try:
- if item.mdItem[0].isChecked == False:
- chcked = False
- except:
- try:
- if self.mdDescription[r + 1].mdItem[0].isChecked == False:
- chcked = False
- except:
- try:
- if self.mdDescription[r + 2].mdItem[0].isChecked == False:
- chcked = False
- except:
- try:
- if self.mdDescription[r + 3].mdItem[0].isChecked == False:
- chcked = False
- except:
- pass
- if not chcked: # chckbox in gui
-
- if forSTS:
- forSTS = False
-
- if ifSTS:
- ifSTS = False
-
- owsTagList.append(str1)
- templateStr = '{{ owsTagList[' + str(indexowsTagList) + '] }}'
- indexowsTagList += 1
-
- line = line.replace(str1, templateStr)
- tag = '{{ ' + item.tag + ' }}'
- line = line.replace(tag, templateStr)
-
- finalTemplate += line
- continue
-
- if chcked:
- if '{% endfor -%}' in line and forSTS == 0:
- str1 = '{% endfor -%}'
- owsTagList.append(str1)
- templateStr = '{{ owsTagList[' + str(indexowsTagList) + '] }}'
- indexowsTagList += 1
-
- line = line.replace(str1, templateStr)
- tag = '{{' + item.tag + '}}'
- line = line.replace(tag, templateStr)
- finalTemplate += line
-
- elif '{% endif -%}' in line and ifSTS == 0:
- str1 = '{% endif -%}'
- owsTagList.append(str1)
- templateStr = '{{ owsTagList[' + str(indexowsTagList) + '] }}'
- indexowsTagList += 1
-
- line = line.replace(str1, templateStr)
- tag = '{{' + item.tag + '}}'
- line = line.replace(tag, templateStr)
- finalTemplate += line
-
- else:
- finalTemplate += line
- chcked = True
-
- head, tail = os.path.split(self.templatePath)
- tail = 'EXPT' + tail
- self.templatePath = os.path.join(head, tail)
- templateOut = open(self.templatePath, 'w')
- templateOut.write(finalTemplate)
- templateOut.close()
-
- return owsTagList
-#----------------------------------------- FILL OWSLib BY EDITED METADATA IN GUI
-
- def executeStr1(self, stri, item):
- '''note- exec cannot be in sub function
- for easier understanding to product of self.createNewMD()- print stri
- '''
- # print stri
- exec stri
-
- def createNewMD(self, evt=None):
- '''Main function for exporting metadata from filled widgets .
- Initializing owslib object by metadata from gui(export of metadata)
- '''
- def prepareStatements():
- '''replacing some specific declaration of python function in jinja template
- '''
- for c in range(self.max):
- if '|length' in str(mdDes[c].tag):
- a = mdDes[c].tag
- a = a.replace('|length', ')').replace('if ', 'if len(self.')
- mdDes[c].tag = a
- if '|length' in str(mdDes[c].statements):
- a = mdDes[c].statements
- a = a.replace('|length', ')').replace('if ', 'if len(self.')
- mdDes[c].statements = a
- if '|length' in str(mdDes[c].statements1):
- a = mdDes[c].statements1
- a = a.replace('|length', ')').replace('if ', 'if len(self.')
- mdDes[c].statements1 = a
-
- def chckIf1Statements():
- '''Return true if next item in jinjainfo::MdDescription is statement
- '''
- try:
- if mdDes[self.c + 1].statement:
- return True
- else:
- return False
- except:
- return False
-
- def chckIf2xStatements():
- '''Return true if next two items in jinjainfo::MdDescription are reprsenting statements
- '''
- if 'if'in mdDes[self.c].tag.split() or 'for' in mdDes[self.c].tag.split():
- try:
- if 'if'in mdDes[self.c + 1].tag.split() or 'for'in mdDes[self.c + 1].tag.split():
- return True
- else:
- return False
- except:
- return False
-
- def noneStatements():
- '''Without condition or loop
- '''
- str1 = ''
- for wxCtrl in mdDes[self.c].mdItem:
- if wxCtrl.getValue() is not None:
- str1 += 'self.' + mdDes[self.c].tag + '="' + str(wxCtrl.getValue()) + '"\n'
- self.executeStr1(str1, mdDes[self.c])
- str1 = ''
- self.plusC()
-
- def inStatements():
- '''possible combinations of statements
- (1) IF
- item
- ----------------------------------------------------
- (2) for
- (2.1) item (with init OWSLib object)
- "or"
- (2.2) item (without init)
- item with ZIP
- '''
- cTmp = self.c
- tag = str(mdDes[cTmp].tag).split()
-
- tag1 = 'self.' + str(tag[-1])
- tag = 'self.' + str(tag[-1]) + '.append(self.val)\n'
-
- self.plusC()
- # statements of current item
- stat = mdDes[self.c].statements
- str1 = ''
- leng = len(mdDes[self.c].mdItem)
-
- # (2.1) IF NECESSARY TO INITIALIZE OWSLIB OBJECT
- if mdDes[cTmp].object and 'if' not in mdDes[cTmp].tag.split():
- objStr = 'self.val=' + mdDes[cTmp].object + '\n'
-
- for n in range(leng):
- numOfItems = 0
- str1 += objStr
- while mdDes[self.c].statements == stat and self.stop is False:
- metadata = re.split(r'[.]', mdDes[self.c].tag)
- metadata[0] = 'self.val.'
- str1 += ''.join(metadata) + "='"\
- + str(mdDes[self.c].mdItem[n].getValue()) + "'\n"
- self.plusC()
- numOfItems += 1
-
- str1 += tag
- self.executeStr1(str1, False)
- str1 = ''
- self.minusC(numOfItems)
-
- self.plusC(numOfItems)
- # (2.2)no init and py ZIP'
- elif 'for' in mdDes[cTmp].tag.split() and mdDes[cTmp].object is None and ' zip(' in mdDes[cTmp].tag:
- leng = len(mdDes[self.c].mdItem)
- tag1 = mdutil.findBetween(mdDes[cTmp].tag, 'zip(', ')').split(',')
-
- for n in range(leng):
- numOfItems = 0
- while mdDes[self.c].statements == stat and self.stop is False:
- str1 += 'self.' + tag1[numOfItems] + ".append('" + mdDes[self.c].mdItem[n].getValue() + "')\n"
- self.plusC()
- numOfItems += 1
-
- self.executeStr1(str1, False)
- str1 = ''
- self.minusC(numOfItems)
-
- self.plusC(numOfItems)
- # 'no init FOR'
- elif 'for' in mdDes[cTmp].tag.split() and mdDes[cTmp].object is None:
- leng = len(mdDes[self.c].mdItem)
- numOfItems = 0
- for n in range(leng):
- numOfItems = 0
- while mdDes[self.c].statements == stat and self.stop is False:
- str1 += tag1 + ".append('" + mdDes[self.c].mdItem[n].getValue() + "')\n"
- self.plusC()
- numOfItems += 1
-
- self.executeStr1(str1, False)
- str1 = ''
- self.minusC(numOfItems)
-
- self.plusC(numOfItems)
- # (1)'no init IF'
- elif 'if' in mdDes[cTmp].tag.split():
-
- objStr = mdDes[cTmp].tag.replace(' md.', ' self.md.') + ':\n'
-
- for n in range(leng):
- numOfItems = 0
- while mdDes[self.c].statements == stat and self.stop is False:
- metadata = 'self.' + mdDes[self.c].tag
- str1 += ''.join(metadata) + "='"\
- + str(mdDes[self.c].mdItem[n].getValue()) + "'\n"
- self.plusC()
- numOfItems += 1
-
- self.minusC(numOfItems)
- self.executeStr1(str1, False)
- str1 = ''
- self.plusC(numOfItems)
-
- def in2Statements():
- '''possible combinations of statements
- (1) IF:
- FOR:
- (1.1) item (with init OWSLib object)
- "or"
- (1.2) item (without init)
- ----------------------------------------------------
- (2) FOR:
- FOR:(implemented fixedly just for MD-keywords)
- (2.1) item (with init OWSLib object)
- "or"
- (2.2) item (without init)
- '''
- prepareStatements()
- cTmp = self.c
- cTmp1 = self.c + 1
- tag = str(mdDes[cTmp].tag).split()
- tag1 = str(mdDes[cTmp1].tag).split()
- stat = mdDes[self.c + 2].statements
-
- append = 'self.' + str(tag1[-1]) + '.append(self.val)\n'
- appendNoInit = 'self.' + str(tag1[-1])
- # (1)
- # if statements-if in jinja template=skip and do single loop
- if 'if' in tag and 'for' in tag1:
- leng = len(mdDes[self.c + 2].mdItem)
- # (1.1)
- if mdDes[cTmp1].object:
- condition = mdDes[cTmp].tag.replace(' md.', ' self.md.') + ':\n'
- objectOWSLib = '\t' + 'self.val=' + mdDes[cTmp1].object + '\n'
- condition2 = '\t' + mdDes[cTmp1].tag.replace(' md.', ' self.md.') + ':\n'
- self.plusC()
- self.plusC()
-
- for n in range(leng):
- numOfItems = 0
- str1 = condition + '\n'
- str1 += condition2 + '\n'
- str1 += '\t' + objectOWSLib + '\n'
-
- while mdDes[self.c].statements == stat and self.stop is False:
- metadata = re.split(r'[.]', mdDes[self.c].tag)
- metadata[0] = '\t\tself.val'
- str1 += ''.join(metadata) + "='" + str(mdDes[self.c].mdItem[n].getValue()) + "'\n"
- self.plusC()
- numOfItems += 1
-
- str1 += '\t\t' + append
- self.executeStr1(str1, False)
- str1 = ''
- self.minusC(numOfItems)
- self.plusC(numOfItems)
- # (1.2)"if and for "
- else:
- self.plusC()
- self.plusC()
- numOfItems = 0
- size = len(mdDes[self.c].mdItem)
- for n in range(size):
- numOfItems = 0
- str1 = ''
-
- while mdDes[self.c].statements == stat and self.stop is False:
- str1 += appendNoInit + '.append("' + mdDes[self.c].mdItem[n].getValue() + '")\n'
- self.plusC()
- numOfItems += 1
-
- self.executeStr1(str1, False)
- self.minusC(numOfItems)
- self.plusC(numOfItems)
- # (2) only keywords (dict)
- elif 'for' in tag and 'for' in tag1: #
- self.plusC() # skip staementes 2x
- self.plusC()
- numOfkwGroup = len(mdDes[self.c + 1].mdItem)
- for n in range(numOfkwGroup):
- kw = {}
- kw['keywords'] = []
- try:
- keyWordLen = len(mdDes[self.c].mdItem[n])
- for k in range(keyWordLen):
- kw['keywords'].append(mdDes[self.c].mdItem[n][k].getValue())
- except:
- kw['keywords'].append(mdDes[self.c].mdItem[n].getValue())
-
- kw['type'] = None
- kw['thesaurus'] = {}
- kw['thesaurus']['title'] = mdDes[self.c + 1].mdItem[n].getValue()
- kw['thesaurus']['date'] = mdDes[self.c + 2].mdItem[n].getValue()
- kw['thesaurus']['datetype'] = mdDes[self.c + 3].mdItem[n].getValue()
- self.md.identification.keywords.append(kw)
-
- self.plusC()
- self.plusC()
- self.plusC()
- self.plusC()
-#------------------------------------------------------------------------------ next function
- self.mdo = MdFileWork()
- self.md = self.mdo.initMD()
- # most of object from OWSLib is initialized in configure file
- dirpath = os.path.dirname(os.path.realpath(__file__))
- path = os.path.join(dirpath, 'config', 'init_md')
- mdInitData = open(path, 'r')
- mdExec = mdInitData.read()
- self.executeStr1(mdExec, None)
-
- self.c = 0
- self.stop = False
- self.max = len(self.mdDescription)
- mdDes = self.mdDescription
-
- while self.stop is False:
- # if no statements
- if mdDes[self.c].statements is None\
- and 'if' not in mdDes[self.c].tag.split()\
- and 'for' not in mdDes[self.c].tag.split():
- noneStatements()
-
- # if 2x statements
- elif chckIf2xStatements():
- in2Statements()
-
- # if 1x statements
- elif chckIf1Statements:
- inStatements()
-
- return self.md
-#------------------------------------ END- FILL OWSLib BY EDITED METADATA IN GUI
-
- def exportToXml(self, jinjaPath, outPath, xmlOutName, msg):
- self.createNewMD()
- self.mdo.saveToXML(self.md, None, jinjaPath, outPath, xmlOutName, msg)
-
- def exportTemplate(self, jinjaPath, outPath, xmlOutName):
- self.templatePath = jinjaPath
- owsTagList = self.defineTemplate()
- self.createNewMD()
- self.mdo.saveToXML(self.md, owsTagList,
- self.templatePath,
- outPath,
- xmlOutName,
- msg=True,
- rmTeplate=True)
-#------------------------------------------------------------------------ LAYOUT
-
- def _layout(self):
- self.mainSizer = wx.BoxSizer(wx.VERTICAL)
- self.SetSizer(self.mainSizer)
- noteSizer = wx.BoxSizer(wx.VERTICAL)
- self.notebook.SetSizer(noteSizer)
- self.mainSizer.Add(self.notebook, proportion=1, flag=wx.EXPAND)
- self.Show()
-#----------------------------------------------------------------------
-if __name__ == "__main__":
- app = wx.App(False)
- frame = MdMainEditor()
- app.MainLoop()
Copied: grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/editor.py (from rev 61594, grass-addons/grass7/gui/wxpython/wx.metadata/editor.py)
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/editor.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/editor.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -0,0 +1,1349 @@
+#!/usr/bin/env python
+# -*- coding: utf-8
+"""
+ at package editor
+ at module g.gui.metadata
+ at brief base editor, read/write ISO metadata, generator of widgets in editor
+
+Classes:
+ - editor::MdFileWork
+ - editor::MdBox
+ - editor::MdWxDuplicator
+ - editor::MdItem
+ - editor::MdNotebookPage
+ - editor::MdMainEditor
+
+(C) 2014 by 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.
+
+ at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
+"""
+import re
+import os
+import sys
+import contextlib
+from lxml import etree
+
+import wx
+from wx import ID_ANY
+from wx import EVT_BUTTON
+import wx.lib.scrolledpanel as scrolled
+
+from owslib.iso import *
+from jinjainfo import JinjaTemplateParser
+from jinja2 import Environment, FileSystemLoader
+
+from core.gcmd import RunCommand, GError, GMessage
+from gui_core.widgets import IntegerValidator, NTCValidator, SimpleValidator,\
+ TimeISOValidator, EmailValidator # ,EmptyValidator
+import mdutil
+
+#=========================================================================
+# MD filework
+#=========================================================================
+
+
+class MdFileWork():
+
+ ''' initializer of metadata in OWSLib and export OWSLib object to xml by jinja templating system
+ '''
+
+ def __init__(self, pathToXml=None):
+ self.path = pathToXml
+ self.owslibInfo = None
+
+ def initMD(self, path=None):
+ '''
+ @brief initialize metadata
+ @param path: path to xml
+ @return: initialized md object by input xml
+ '''
+ if path is None:
+ self.md = MD_Metadata(md=None)
+ return self.md
+ else:
+ io = open(path, 'r')
+ str1 = ''
+ for line in io.readlines():
+ str1 += mdutil.removeNonAscii(line)
+ io.close()
+ io1 = open(path, 'w')
+ io1.write(str1)
+ io1.close()
+
+ try:
+ tree = etree.parse(path)
+ root = tree.getroot()
+ self.md = MD_Metadata(root)
+
+ return self.md
+
+ except Exception, e:
+ GError('Error loading xml:\n' + str(e))
+
+ def saveToXML(self, md, owsTagList, jinjaPath, outPath=None, xmlOutName=None, msg=True, rmTeplate=False):
+ '''
+ @note creator of xml with using OWSLib md object and jinja template
+ @param md: owslib.iso.MD_Metadata
+ @param owsTagList: in case if user definig template
+ @param jinjaPath: path to jinja template
+ @param outPath: path of exported xml
+ @param xmlOutName: name of exported xml
+ @param msg: gmesage info after export
+ @param rmTeplate: remove template after use
+ @return: initialized md object by input xml
+ '''
+ # if output file name is None, use map name and add postfix
+ self.dirpath = os.path.dirname(os.path.realpath(__file__))
+ self.md = md
+ self.owsTagList = owsTagList
+
+ if xmlOutName is None:
+ xmlOutName = 'RANDExportMD' # TODO change to name of map
+ if not xmlOutName.lower().endswith('.xml'):
+ xmlOutName += '.xml'
+ # if path is None, use lunch. dir
+ # TODO change default folder to mapset location
+ if not outPath:
+ outPath = os.path.join(self.dirpath, xmlOutName)
+ else:
+ outPath = os.path.join(outPath, xmlOutName)
+ xml = open(jinjaPath, 'r')
+
+ str1 = ''
+ for line in xml.readlines():
+ line = mdutil.removeNonAscii(line)
+ str1 += line
+ xml.close
+ io = open(jinjaPath, 'w')
+ io.write(str1)
+ io.close()
+
+ # generating xml using jinja tempaltes
+ head, tail = os.path.split(jinjaPath)
+ env = Environment(loader=FileSystemLoader(head))
+ env.globals.update(zip=zip)
+ template = env.get_template(tail)
+ if self.owsTagList is None:
+ iso_xml = template.render(md=self.md)
+ else:
+ iso_xml = template.render(md=self.md, owsTagList=self.owsTagList)
+ xml_file = xmlOutName
+
+ try:
+ xml_file = open(outPath, "w")
+ xml_file.write(iso_xml)
+ xml_file.close()
+
+ if msg:
+ GMessage('File exported to: %s' % outPath)
+
+ if rmTeplate:
+ os.remove(jinjaPath)
+
+ return outPath
+
+ except Exception, e:
+ GError('Error writing xml:\n' + str(e))
+
+#=========================================================================
+# CREATE BOX (staticbox+button(optional)
+#=========================================================================
+
+
+class MdBox(wx.Panel):
+
+ '''widget(static box) which include metadata items (MdItem)
+ '''
+
+ def __init__(self, parent, label='label'):
+ wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
+ self.label = label
+ self.mdItems = list()
+ self.stbox = wx.StaticBox(self, label=label, id=ID_ANY, style=wx.RAISED_BORDER)
+ self.stbox.SetForegroundColour((0, 0, 0))
+ self.stbox.SetBackgroundColour((200, 200, 200))
+ self.stbox.SetFont(wx.Font(12, wx.NORMAL, wx.NORMAL, wx.NORMAL))
+
+ def addItems(self, items, multi=True, rmMulti=False, isFirstNum=-1):
+ '''
+ @param items: editor::MdItems
+ @param multi: true in case when box has button for duplicating box and included items
+ @param rmMulti: true in case when box has button for removing box and included items
+ @param isFirstNum: handling with 'add' and 'remove' button of box.
+ this param is necessary for generating editor in editor::MdEditor.generateGUI.inBlock()
+ note: just firs generated box has 'add' buton (because is mandatory) and nex others has
+ 'remove butt'
+ '''
+ if isFirstNum != 1:
+ multi = False
+ rmMulti = True
+
+ # if not initialize in jinja template (default is true)
+ if multi is None:
+ multi = True
+
+ self.panelSizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(self.panelSizer)
+
+ self.boxButtonSizer = wx.BoxSizer(wx.HORIZONTAL)
+
+ self.panelSizer.AddSpacer(10, 10, 1, wx.EXPAND)
+ self.panelSizer.Add(self.boxButtonSizer, flag=wx.EXPAND, proportion=1)
+
+ self.stBoxSizer = wx.StaticBoxSizer(self.stbox, orient=wx.VERTICAL)
+ self.boxButtonSizer.Add(self.stBoxSizer, flag=wx.EXPAND, proportion=1)
+
+ for item in items:
+ self.mdItems.append(item)
+ self.stBoxSizer.Add(item, flag=wx.EXPAND, proportion=1)
+ self.stBoxSizer.AddSpacer(5, 5, 1, wx.EXPAND)
+
+ if multi:
+ self.addBoxButt = wx.Button(self, id=ID_ANY, size=(30, 30), label='+')
+ self.boxButtonSizer.Add(self.addBoxButt, 0)
+ self.addBoxButt.Bind(EVT_BUTTON, self.duplicateBox)
+
+ if rmMulti:
+ self.rmBoxButt = wx.Button(self, id=ID_ANY, size=(30, 30), label='-')
+ self.boxButtonSizer.Add(self.rmBoxButt, 0)
+ self.rmBoxButt.Bind(EVT_BUTTON, self.removeBox)
+
+ def addDuplicatedItem(self, item):
+ self.stBoxSizer.Add(item, flag=wx.EXPAND, proportion=1)
+ self.stBoxSizer.AddSpacer(5, 5, 1, wx.EXPAND)
+ self.GetParent().Layout()
+
+ def getCtrlID(self):
+ return self.GetId()
+
+ def removeBox(self, evt):
+ for item in self.mdItems:
+ item.mdDescription.removeMdItem(item)
+ self.GetParent().removeBox(self)
+
+ def removeMdItem(self, mdItem, items):
+ '''
+ @param mdItem: object editor::MdItem
+ @param items: widgets to destroy
+ '''
+ mdItem.mdDescription.removeMdItem(mdItem)
+ for item in items:
+ try:
+ item.Destroy()
+ except:
+ pass
+ self.stBoxSizer.RemovePos(-1) # remove wxSpacer
+ self.stBoxSizer.Remove(mdItem)
+ self.GetParent().Layout()
+
+ def duplicateBox(self, evt):
+ duplicator = MdWxDuplicator(self.mdItems, self.GetParent(), self.label)
+ clonedBox = duplicator.mdBox
+ self.GetParent().addDuplicatedItem(clonedBox, self.GetId())
+
+#===============================================================================
+# DUPLICATOR OF WIDGETS-mditem
+#===============================================================================
+
+
+class MdWxDuplicator():
+
+ '''duplicator of MdBox and MdItem object
+ '''
+
+ def __init__(self, mdItems, parent, boxlabel=None, mdItemOld=None, template=None):
+ '''
+ @param mdItems: list of editor::MdItem
+ @param parent: parent of new duplicated box
+ @param boxlabel: label of static box
+ @param mdItemOld: object which will be duplicated
+ @param template: in case if 'template mode' is on in editor
+ '''
+ # duplicate box of items
+ if boxlabel:
+ itemList = list()
+ self.mdBox = MdBox(parent, boxlabel)
+ for i in mdItems:
+ try: # check if item has multiple button
+ i.addItemButt.GetLabel()
+ multi = True
+ except:
+ multi = False
+ try: # check if chckBoxEdit exists
+ i.chckBoxEdit.GetValue()
+ template = True
+ except:
+ template = False
+
+ i = i.mdDescription # var mdDescription is jinjainfo::MdDescription
+ mdItem1 = MdItem(parent=self.mdBox,
+ item=i,
+ multiplicity=multi,
+ isFirstNum=1,
+ chckBox=template)
+
+ itemList.append(mdItem1)
+
+ i.addMdItem(mdItem1) # add item with using jinjainfo::MDescription
+ self.mdBox.addItems(itemList, False, True) # fill box
+
+ else: # duplicate only MdItem
+ self.mdItem = MdItem(parent=parent,
+ item=mdItems,
+ multiplicity=False,
+ rmMulti=True,
+ isFirstNum=-1,
+ chckBox=template)
+
+ try:
+ if mdItems.inbox is not None:
+ mdItems.addMdItem(self.mdItem, mdItemOld)
+ else:
+ mdItems.addMdItem(self.mdItem)
+ except:
+ mdItems.addMdItem(self.mdItem)
+#=========================================================================
+# METADATA ITEM (label+ctrlText+button(optional)+chckbox(template)
+#=========================================================================
+
+
+class MdItem(wx.BoxSizer):
+
+ '''main building blocks of generated gui of editor
+ '''
+
+ def __init__(self, parent, item, multiplicity=None, rmMulti=False, isFirstNum=-1, chckBox=False):
+ '''
+ @param item: jinjainfo::MdDescription(initialized by parsing information from jinja template)
+ @param multiplicity: if true- widget has button for duplicate self
+ @param rmMulti: if true- widget has button for remove self
+ @param isFirstNum: handling with 'add' and 'remove' button of box.
+ this param is necessary for generating editor in editor::MdEditor.generateGUI.inBlock()
+ note: just firs generated box has 'add' buton (because is mandatory) and nex others has
+ 'remove butt'
+ @param chckBox: in case-True 'template editor' is on and widget has checkobox.
+ '''
+ wx.BoxSizer.__init__(self, wx.VERTICAL)
+ self.isValid = False
+ self.isChecked = False
+ self.mdDescription = item
+ self.chckBox = chckBox
+ self.multiple = multiplicity
+
+ if multiplicity is None:
+ self.multiple = item.multiplicity
+
+ if isFirstNum != 1:
+ self.multiple = False
+
+ if isFirstNum != 1 and item.multiplicity:
+ rmMulti = True
+
+ self.tagText = wx.StaticText(parent=parent, id=ID_ANY, label=item.name)
+
+ if self.chckBox == False:
+ if item.multiline is True:
+ self.valueCtrl = wx.TextCtrl(parent, id=ID_ANY, size=(0, 70),
+ validator=self.validators(item.type),
+ style=wx.VSCROLL |
+ wx.TE_MULTILINE | wx.TE_WORDWRAP |
+ wx.TAB_TRAVERSAL | wx.RAISED_BORDER)
+ else:
+ self.valueCtrl = wx.TextCtrl(parent, id=wx.ID_ANY,
+ validator=self.validators(item.type),
+ style=wx.VSCROLL | wx.TE_DONTWRAP |
+ wx.TAB_TRAVERSAL | wx.RAISED_BORDER | wx.HSCROLL)
+ else:
+ if item.multiline is True:
+ self.valueCtrl = wx.TextCtrl(parent, id=ID_ANY, size=(0, 70),
+ style=wx.VSCROLL |
+ wx.TE_MULTILINE | wx.TE_WORDWRAP |
+ wx.TAB_TRAVERSAL | wx.RAISED_BORDER)
+ else:
+ self.valueCtrl = wx.TextCtrl(parent, id=wx.ID_ANY,
+ style=wx.VSCROLL | wx.TE_DONTWRAP |
+ wx.TAB_TRAVERSAL | wx.RAISED_BORDER | wx.HSCROLL)
+
+ self.valueCtrl.Bind(wx.EVT_MOTION, self.onMove)
+ self.valueCtrl.SetExtraStyle(wx.WS_EX_VALIDATE_RECURSIVELY)
+
+ if self.multiple:
+ self.addItemButt = wx.Button(parent, -1, size=(30, 30), label='+')
+ self.addItemButt.Bind(EVT_BUTTON, self.duplicateItem)
+
+ if rmMulti:
+ self.rmItemButt = wx.Button(parent, -1, size=(30, 30), label='-')
+ self.rmItemButt.Bind(EVT_BUTTON, self.removeItem)
+
+ if self.chckBox:
+ self.chckBoxEdit = wx.CheckBox(parent, -1, size=(30, 30))
+ self.chckBoxEdit.Bind(wx.EVT_CHECKBOX, self.onChangeChckBox)
+ self.chckBoxEdit.SetValue(False)
+ self.isChecked = False
+ self.valueCtrl.Disable()
+
+ self.createInfo()
+ self.tip = wx.ToolTip(self.infoTip)
+
+ self._addItemLay(item.multiline, rmMulti)
+
+ def validators(self, validationStyle):
+
+ if validationStyle == 'email':
+ return EmailValidator()
+
+ if validationStyle == 'integer':
+ return NTCValidator('DIGIT_ONLY')
+
+ if validationStyle == 'decimal':
+ return NTCValidator('DIGIT_ONLY')
+
+ if validationStyle == 'date':
+ return TimeISOValidator()
+
+ # return EmptyValidator()
+ return SimpleValidator('')
+
+ def onChangeChckBox(self, evt):
+ '''current implementation of editor mode for defining templates not allowed to check
+ only single items in static box. There are two cases: all items in box are checked or not.
+ '''
+ if self.mdDescription.inbox: # MdItems are in box
+ try:
+ items = self.valueCtrl.GetParent().mdItems
+ if self.isChecked:
+ self.valueCtrl.Disable()
+ self.isChecked = False
+ else:
+ self.valueCtrl.Enable()
+ self.isChecked = True
+
+ for item in items:
+ if self.isChecked:
+ item.valueCtrl.Enable()
+ item.chckBoxEdit.SetValue(True)
+ item.isChecked = True
+ else:
+ item.valueCtrl.Disable()
+ item.chckBoxEdit.SetValue(False)
+ item.isChecked = False
+ except:
+ pass
+ else:
+ if self.isChecked:
+ self.valueCtrl.Disable()
+ self.isChecked = False
+ else:
+ self.valueCtrl.Enable()
+ self.isChecked = True
+
+ def onMove(self, evt=None):
+ self.valueCtrl.SetToolTip(self.tip)
+
+ def createInfo(self):
+ """Feed for tooltip
+ """
+ string = ''
+ if self.mdDescription.ref is not None:
+ string += self.mdDescription.ref + '\n\n'
+ if self.mdDescription.name is not None:
+ string += 'NAME: \n' + self.mdDescription.name + '\n\n'
+ if self.mdDescription.desc is not None:
+ string += 'DESCRIPTION: \n' + self.mdDescription.desc + '\n\n'
+ if self.mdDescription.example is not None:
+ string += 'EXAMPLE: \n' + self.mdDescription.example + '\n\n'
+ if self.mdDescription.type is not None:
+ string += 'DATA TYPE: \n' + self.mdDescription.type + '\n\n'
+ string += '*' + '\n'
+ if self.mdDescription.statements is not None:
+ string += 'Jinja template info: \n' + self.mdDescription.statements + '\n'
+
+ if self.mdDescription.statements1 is not None:
+ string += self.mdDescription.statements1 + '\n'
+ string += 'OWSLib info:\n' + self.mdDescription.tag
+ self.infoTip = string
+
+ def removeItem(self, evt):
+ """adding all items in self(mdItem) to list and call parent remover
+ """
+ ilist = [self.valueCtrl, self.tagText]
+ try:
+ ilist.append(self.rmItemButt)
+ except:
+ pass
+ try:
+ ilist.append(self.chckBoxEdit)
+ except:
+ pass
+ self.valueCtrl.GetParent().removeMdItem(self, ilist)
+
+ def duplicateItem(self, evt):
+ '''add Md item to parent(box or notebook page)
+ '''
+ parent = self.valueCtrl.GetParent()
+ # if parent is box
+ if self.mdDescription.inbox:
+ duplicator = MdWxDuplicator(mdItems=self.mdDescription,
+ parent=parent,
+ mdItemOld=self,
+ template=self.chckBox)
+ else:
+ duplicator = MdWxDuplicator(mdItems=self.mdDescription,
+ parent=parent,
+ template=self.chckBox)
+
+ clonedMdItem = duplicator.mdItem
+ # call parent "add" function
+ self.valueCtrl.GetParent().addDuplicatedItem(clonedMdItem, self.valueCtrl.GetId())
+
+ def setValue(self, value):
+ '''Set value & color of widgets
+ in case if is template creator 'on':
+ yellow: in case if value is marked by $NULL(by mdgrass::GrassMD)
+ red: if value is '' or object is not initialized. e.g. if user
+ read non fully valid INSPIRE xml with INSPIRE jinja template,
+ the gui generating mechanism will create GUI according to template
+ and all missing tags(xml)-gui(TextCtrls) will be marked by red
+ '''
+ if value is None or value is '':
+ if self.chckBox:
+ self.chckBoxEdit.SetValue(True)
+ self.isChecked = True
+ try:
+ self.onChangeChckBox(None)
+ self.onChangeChckBox(None)
+ except:
+ pass
+ self.valueCtrl.SetBackgroundColour((245, 204, 230)) # red
+
+ self.valueCtrl.SetValue('')
+ self.valueCtrl.Enable()
+
+ elif self.chckBox and value == '$NULL':
+ self.valueCtrl.SetBackgroundColour((255, 255, 82)) # yellow
+ self.valueCtrl.SetValue('')
+
+ if self.chckBox:
+ self.chckBoxEdit.SetValue(True)
+ self.isChecked = True
+ self.valueCtrl.Enable()
+ try:
+ self.onChangeChckBox(None)
+ self.onChangeChckBox(None)
+ except:
+ pass
+
+ elif value == '$NULL':
+ self.valueCtrl.SetValue('')
+
+ else:
+ self.isValid = True
+ self.valueCtrl.SetValue(value)
+
+ def getValue(self):
+
+ value = mdutil.replaceXMLReservedChar(self.valueCtrl.GetValue())
+ value = value.replace('\n', '')
+ value = value.replace('"', '')
+ value = value.replace("'", '')
+ return value
+
+ def getCtrlID(self):
+ return self.valueCtrl.GetId()
+
+ def _addItemLay(self, multiline, rmMulti):
+ self.textFieldSizer = wx.BoxSizer(wx.HORIZONTAL)
+ if multiline is True:
+ self.textFieldSizer.Add(self.valueCtrl, proportion=1, flag=wx.EXPAND)
+ else:
+ self.textFieldSizer.Add(self.valueCtrl, proportion=1)
+
+ if self.multiple:
+ self.textFieldSizer.Add(self.addItemButt, 0)
+
+ if rmMulti:
+ self.textFieldSizer.Add(self.rmItemButt, 0)
+
+ if self.chckBox:
+ self.textFieldSizer.Add(self.chckBoxEdit, 0)
+
+ self.Add(item=self.tagText, proportion=0)
+ self.Add(item=self.textFieldSizer, proportion=0, flag=wx.EXPAND)
+
+#=========================================================================
+# ADD NOTEBOOK PAGE
+#=========================================================================
+
+
+class MdNotebookPage(scrolled.ScrolledPanel):
+
+ """
+ every notebook page is initialized by jinjainfo::MdDescription.group (label)
+ """
+
+ def __init__(self, parent):
+ scrolled.ScrolledPanel.__init__(self, parent=parent, id=wx.ID_ANY)
+ self.items = []
+ self.SetupScrolling()
+ self._addNotebookPageLay()
+ self.sizerIndexDict = {}
+ self.sizerIndex = 0
+
+ def _addNotebookPageLay(self):
+ self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(self.mainSizer)
+
+ def _getIndex(self):
+ '''
+ index for handling position of editor::MdBox,MdItem in editor::MdNotebookPage(self).
+ Primary for correct duplicating Boxes or items on notebook page
+ '''
+ self.sizerIndex += 1
+ return self.sizerIndex
+
+ def addItem(self, item):
+ '''
+ @param item: can be editor::MdBox or editor::MDItem
+ '''
+ if isinstance(item, list):
+ for i in item:
+ if isinstance(i, list):
+ for ii in i:
+ self.sizerIndexDict[ii.getCtrlID()] = self._getIndex()
+ self.mainSizer.Add(ii, proportion=0, flag=wx.EXPAND)
+ else:
+ self.sizerIndexDict[i.getCtrlID()] = self._getIndex()
+ self.mainSizer.Add(i, proportion=0, flag=wx.EXPAND)
+ else:
+ self.sizerIndexDict[item.getCtrlID()] = self._getIndex()
+ self.mainSizer.Add(item, proportion=0, flag=wx.EXPAND)
+
+ def addDuplicatedItem(self, item, mId):
+ '''adding duplicated object to sizer to position after parent
+ '''
+ self.items.append(item)
+ posIndex = self.sizerIndexDict[mId]
+ self.mainSizer.Insert(posIndex, item, proportion=0, flag=wx.EXPAND)
+ self.SetSizerAndFit(self.mainSizer)
+ self.GetParent().Refresh()
+
+ def removeBox(self, box):
+ box.Destroy()
+ self.SetSizerAndFit(self.mainSizer)
+
+ def removeMdItem(self, mdDes, items):
+ '''Remove children
+ @param mdDes: editor::MdItem.mdDescription
+ @param items: all widgets to remove of MdItem
+ '''
+ mdDes.mdDescription.removeMdItem(mdDes) # remove from jinjainfi:MdDEscription object
+ for item in items:
+ item.Destroy()
+ self.SetSizerAndFit(self.mainSizer)
+
+#=========================================================================
+# MAIN FRAME
+#=========================================================================
+
+
+class MdMainEditor(wx.Panel):
+
+ '''
+ main functions : self.generateGUI(): generating GUI from: editor:MdItem,MdBox,MdNotebookPage
+ self.createNewMD(): filling OWSLib.iso.MD_Metadata by values from generated gui
+ self.defineTemplate(): creator of predefined templates in template editor mode
+ '''
+
+ def __init__(self, parent, templatePath, xmlMdPath, templateEditor=False):
+ '''
+ @param templatePath: path to jinja template for generating gui of editor
+ @param xmlMdPath: path of xml for init Editor
+ @param templateEditor: mode-creator of template
+ '''
+ wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
+ self.mdo = MdFileWork()
+ self.md = self.mdo.initMD(xmlMdPath)
+ self.templateEditor = templateEditor
+ self.templatePath = templatePath
+
+ self.jinj = JinjaTemplateParser(self.templatePath)
+ # list of object MdDescription
+ self.mdDescription = self.jinj.mdDescription
+ # string of tags from jinja template (loops and OWSLib objects)
+ self.mdOWSTagStr = self.jinj.mdOWSTagStr
+ self.mdOWSTagStrList = self.jinj.mdOWSTagStrList #
+
+ self.generateGUI()
+ self._layout()
+
+#----------------------------------------------------------- GUI GENERATOR START
+ def executeStr(self, stri, mdDescrObj):
+ '''note- exec cannot be in sub function
+ for easy understanding to product of self.generateGUI()- print stri
+ '''
+ # print stri
+ exec stri
+
+ def plusC(self, num=None):
+ '''iterator for handling jinja teplate items in self.generateGUI and self.createNewMD
+
+ '''
+ if num is None:
+ num = 1
+ self.c += num
+ if self.c >= self.max:
+ self.c -= 1 # ensure to'list out of bounds'
+ self.stop = True
+
+ def minusC(self, num=None):
+ '''iterator for handling jinja teplate items in self.generateGUI and self.createNewMD
+ '''
+ if num is None:
+ num = 1
+ self.c -= num
+ if self.c <= self.max:
+ self.stop = False
+
+ def generateGUI(self):
+ '''
+ @var tagStringLst: tagStringLst is self.mdOWSTagStr in list.
+ Item=line from jinja template(only lines with owslib objects and loops)
+ @var mdDescrObj: list of MdDescription() objects inicialized\
+ by information from jinja t.
+ @var self.c: index of var: tagStringLst and var: self.mdDescription
+ @var markgroup: markers of created list in GUI notebook
+ @var self.max: length of tagStringLst and mdDescrObj
+ @var self.stop: index self.c is increasing by function plusC(),\
+ that care about not exceeding the index
+ HINT: print param stri in self.executeStr()
+ '''
+ def prepareStatements():
+ '''in jinja template are difining some py-function specificaly:
+ e.g. |length=len
+ also statements with pythonic 'zip' must be prepare specifically for generator of GUI
+ '''
+ for c in range(self.max):
+ if '|length' in str(tagStringLst[c]):
+ a = tagStringLst[c]
+ a = a.replace('|length', ')').replace('if ', 'if len(self.')
+ tagStringLst[c] = a
+ if 'zip(' in tagStringLst[c]:
+ sta = tagStringLst[c]
+ tagStringLst[c] = sta.replace('md.', 'self.md.')
+
+ def chckIfJumpToLoop(sta):
+ '''if loaded xml not include tags(OWSLib object) from jinja template, this function will
+ generate sample of item(marked by red in GUI-template mode).
+ @note: in case of sub statements e.g. metadata-keywords is need to check booth statements
+ @param sta: statements of the loop
+ for understanding print param for self.executeStr()
+ '''
+ self.isValidS = False
+ staTMP = sta
+ if not '\t'in staTMP:
+ tab = '\t'
+ tab1 = ''
+ staTMP = staTMP + ":\n" + tab + 'self.isValidS=True'
+ else:
+ tab = '\t'
+ tab1 = '\t'
+ staTMP = staTMP.replace('\t', '') + ":\n" + tab + 'self.isValidS=True'
+
+ try: # if loop for in for
+ self.executeStr(staTMP, False)
+ except:
+ staTMP = self.staTMP.replace('self.isValidS=True', '') + '\n\t' + staTMP.replace('\t', '\t\t')
+ self.executeStr(staTMP, False)
+
+ self.staTMP = staTMP
+ if self.isValidS:
+ return sta
+ else:
+ return tab1 + 'for n in range(1)'
+
+ def inBlock():
+ '''This part of code build string-code for executing. This can happend if is necassary to use statements
+ to generate gui(OWSLib objects in list). The block of code is building from "statement" which is represended by OWSLib object.
+ In case if OWSLib object is non initialized(metadata missing), function chckIfJumpToLoop() replace statements by "for n in range(1)".
+ @var IFStatements: True= string is IF statements
+ @var loop: current statements, mostly loop FOR
+ @var str1: final string for execute
+ @var box: True if editor::MdItems is in editor::MdBox
+ @var isValid: True in case if OWSLib object in statement is initialized. False= statements is 'for n in range(1)'
+ '''
+ IFStatements = False
+ statements = tagStringLst[self.c - 1]
+ if 'if' in statements.split():
+ IFStatements = True
+ loop = statements.replace(' md.', ' self.md.')
+ looptmp = chckIfJumpToLoop(loop)
+ str2 = 'numOfSameBox=0\n'
+ str2 += looptmp
+
+ str2 += ':\n'
+ str2 += '\t' + 'self.ItemList=list()\n' # initialize list
+ str2 += '\t' + 'numOfSameBox+=1\n'
+
+ box = False
+ if self.mdDescription[self.c].inbox:
+ box = True
+ str2 += '\t' + 'box=MdBox(self.nbPage,mdDescrObj[' + str(self.c) + '].inbox)\n' # add box
+
+ str1 = str2
+ while '\t' in tagStringLst[self.c] and self.stop is False:
+ if 'for' not in str(tagStringLst[self.c]).split()\
+ and 'if' not in str(tagStringLst[self.c]).split():
+
+ value = str(self.mdOWSTagStrList[self.c])
+ str1 += '\t' + 'self.mdDescription[' + str(self.c) + "].addStatements('" + loop + "')\n"
+
+ if box:
+ str1 += '\t' + \
+ 'it=MdItem(parent=box,item=mdDescrObj[' + str(self.c) + '],isFirstNum=numOfSameBox,chckBox=self.templateEditor)\n'
+ else:
+ str1 += '\t' + \
+ 'it=MdItem(parent=self.nbPage,item=mdDescrObj[' + str(self.c) + '],isFirstNum=numOfSameBox,chckBox=self.templateEditor)\n'
+
+ if self.isValidS: # if metatdata are loaded to owslib
+ if IFStatements:
+ str1 += '\t' + 'it.setValue(self.' + str(value) + ')\n'
+ else:
+ str1 += '\t' + 'it.setValue(' + str(value) + ')\n'
+ else:
+ if IFStatements:
+ str1 += '\t' + 'it.setValue("")\n'
+ else:
+ str1 += '\t' + 'it.setValue("")\n'
+
+ str1 += '\t' + 'self.mdDescription[' + str(self.c) + '].addMdItem(it)\n'
+ str1 += '\t' + 'self.ItemList.append(it)\n'
+ tab = '\t'
+ self.plusC()
+
+ else: # if statements in statements
+ statements = tagStringLst[self.c]
+ str2 = ''
+ keyword = False
+
+ if '["keywords"]' in statements:
+ keyword = True
+ str2 += '\t' + 'self.keywordsList=[]\n'
+
+ str2 += '\t' + 'numOfSameItem=0\n'
+ loop2 = statements.replace(' md.', ' self.md.')
+ looptmp1 = chckIfJumpToLoop(loop2)
+ str2 += looptmp1 + ':\n'
+ self.plusC()
+ str1 += str2
+ while '\t\t' in tagStringLst[self.c] and self.stop is False:
+ value = str(self.mdOWSTagStrList[self.c])
+ # save information about loops
+ str1 += '\t\t' + 'numOfSameItem+=1\n'
+ str1 += '\t\t' + 'self.mdDescription[' + str(self.c) + "].addStatements('" + loop + "')\n"
+ str1 += '\t\t' + 'self.mdDescription[' + str(self.c) + "].addStatements1('" + loop2 + "')\n"
+
+ if box:
+ str1 += '\t\t' + \
+ 'it=MdItem(parent=box,item=mdDescrObj[' + str(self.c) + '],isFirstNum=numOfSameItem,chckBox=self.templateEditor)\n'
+ else:
+ str1 += '\t\t' + \
+ 'it=MdItem(self.nbPage,mdDescrObj[' + str(self.c) + '],isFirstNum=numOfSameItem,chckBox=self.templateEditor)\n'
+
+ if self.isValidS:
+ str1 += '\t\t' + 'it.setValue(' + str(value) + ')\n'
+ else:
+ str1 += '\t\t' + 'it.setValue("")\n'
+
+ str1 += '\t\t' + 'self.ItemList.append(it)\n'
+ if keyword:
+ str1 += '\t\t' + 'self.keywordsList.append(it)\n'
+ str1 += '\t' + 'self.mdDescription[' + str(self.c) + '].addMdItem(self.keywordsList)\n'
+ else:
+ str1 += '\t\t' + 'self.mdDescription[' + str(self.c) + '].addMdItem(it)\n'
+
+ tab = '\t\t'
+ self.plusC()
+ if box:
+ str1 += tab +\
+ 'box.addItems(items=self.ItemList,multi=mdDescrObj[self.c].inboxmulti,isFirstNum=numOfSameBox)\n'
+ str1 += tab + 'self.nbPage.addItem(box)\n'
+ else:
+ str1 += tab + 'self.nbPage.addItem(self.ItemList)\n'
+
+ self.executeStr(str1, mdDescrObj)
+
+#--------------------------------------------------------------------- INIT VARS
+ self.notebook = wx.Notebook(self)
+ markgroup = [] # notebok panel marker
+ tagStringLst = self.mdOWSTagStrList
+ mdDescrObj = self.mdDescription # from jinja
+ self.c = 0
+ self.stop = False
+ self.max = len(mdDescrObj)
+ prepareStatements()
+ self.notebokDict = {}
+# --------------------------------------------- #START of the loop of genereator
+ while self.stop is False: # self.stop is managed by def plusC(self):
+ group = mdDescrObj[self.c].group
+
+ if group not in markgroup: # if group is not created
+ markgroup.append(group) # mark group
+ self.nbPage = MdNotebookPage(self.notebook)
+ self.notebook.AddPage(self.nbPage, mdDescrObj[self.c].group)
+ self.notebokDict[mdDescrObj[self.c].group] = self.nbPage
+ else:
+ self.nbPage = self.notebokDict[mdDescrObj[self.c].group]
+
+ # if statements started
+ if '\t' in tagStringLst[self.c] and self.stop is False:
+ inBlock()
+ # if is just singe item without statements
+ elif 'for' not in str(tagStringLst[self.c]).split() and 'if' not in str(tagStringLst[self.c]).split():
+ it = MdItem(parent=self.nbPage, item=mdDescrObj[self.c], chckBox=self.templateEditor)
+ value = 'self.' + str(self.mdOWSTagStrList[self.c]).replace('\n', '')
+ value = eval(value)
+ if value is None:
+ value = ''
+
+ it.setValue(value)
+ self.mdDescription[self.c].addMdItem(it)
+ self.nbPage.addItem(it)
+ self.plusC()
+ else:
+ self.plusC()
+ if self.templateEditor:
+ self.refreshChkboxes()
+
+ def refreshChkboxes(self):
+ '''In case if template editor is on, after generateing gui si
+ obligatory to refresh checkboxes
+ '''
+ for item in self.mdDescription:
+ for i in item.mdItem:
+ try:
+ i.onChangeChckBox(None)
+ i.onChangeChckBox(None)
+ except:
+ pass
+#----------------------------------------------------------- GUI GENERATOR END
+
+ def defineTemplate(self):
+ '''Main function for generating jinja template in mode "template editor"
+ Every widget MdItem are represented by 'jinja tag'. Not checked widget= tag in jinja template will be replaced by
+ listo of string with string of replaced tag. In rendering template this produce holding(non removing) jinja-tag from template.
+ In case if widget is checked= rendering will replace OWSLib obect by filled values( like in normal editing mode)
+ @var finalTemplate: string included final jinja template
+ '''
+ try:
+ template = open(self.templatePath, 'r')
+ except Exception, e:
+ GError('Error loading template:\n' + str(e))
+
+ owsTagList = list()
+ indexowsTagList = 0
+ finalTemplate = ''
+ chcked = False
+ forSTS = False
+ ifSTS = False
+
+ for line in template.readlines():
+ if '{% for' in line:
+ forSTS = True
+
+ if '{% if' in line:
+ ifSTS = True
+
+ for r, item in enumerate(self.mdDescription):
+ str1 = item.selfInfoString
+ if str1 in line: # owslib definition in line
+ try:
+ if item.mdItem[0].isChecked == False:
+ chcked = False
+ except:
+ try:
+ if self.mdDescription[r + 1].mdItem[0].isChecked == False:
+ chcked = False
+ except:
+ try:
+ if self.mdDescription[r + 2].mdItem[0].isChecked == False:
+ chcked = False
+ except:
+ try:
+ if self.mdDescription[r + 3].mdItem[0].isChecked == False:
+ chcked = False
+ except:
+ pass
+ if not chcked: # chckbox in gui
+
+ if forSTS:
+ forSTS = False
+
+ if ifSTS:
+ ifSTS = False
+
+ owsTagList.append(str1)
+ templateStr = '{{ owsTagList[' + str(indexowsTagList) + '] }}'
+ indexowsTagList += 1
+
+ line = line.replace(str1, templateStr)
+ tag = '{{ ' + item.tag + ' }}'
+ line = line.replace(tag, templateStr)
+
+ finalTemplate += line
+ continue
+
+ if chcked:
+ if '{% endfor -%}' in line and forSTS == 0:
+ str1 = '{% endfor -%}'
+ owsTagList.append(str1)
+ templateStr = '{{ owsTagList[' + str(indexowsTagList) + '] }}'
+ indexowsTagList += 1
+
+ line = line.replace(str1, templateStr)
+ tag = '{{' + item.tag + '}}'
+ line = line.replace(tag, templateStr)
+ finalTemplate += line
+
+ elif '{% endif -%}' in line and ifSTS == 0:
+ str1 = '{% endif -%}'
+ owsTagList.append(str1)
+ templateStr = '{{ owsTagList[' + str(indexowsTagList) + '] }}'
+ indexowsTagList += 1
+
+ line = line.replace(str1, templateStr)
+ tag = '{{' + item.tag + '}}'
+ line = line.replace(tag, templateStr)
+ finalTemplate += line
+
+ else:
+ finalTemplate += line
+ chcked = True
+
+ head, tail = os.path.split(self.templatePath)
+ tail = 'EXPT' + tail
+ self.templatePath = os.path.join(head, tail)
+ templateOut = open(self.templatePath, 'w')
+ templateOut.write(finalTemplate)
+ templateOut.close()
+
+ return owsTagList
+#----------------------------------------- FILL OWSLib BY EDITED METADATA IN GUI
+
+ def executeStr1(self, stri, item):
+ '''note- exec cannot be in sub function
+ for easier understanding to product of self.createNewMD()- print stri
+ '''
+ # print stri
+ exec stri
+
+ def createNewMD(self, evt=None):
+ '''Main function for exporting metadata from filled widgets .
+ Initializing owslib object by metadata from gui(export of metadata)
+ '''
+ def prepareStatements():
+ '''replacing some specific declaration of python function in jinja template
+ '''
+ for c in range(self.max):
+ if '|length' in str(mdDes[c].tag):
+ a = mdDes[c].tag
+ a = a.replace('|length', ')').replace('if ', 'if len(self.')
+ mdDes[c].tag = a
+ if '|length' in str(mdDes[c].statements):
+ a = mdDes[c].statements
+ a = a.replace('|length', ')').replace('if ', 'if len(self.')
+ mdDes[c].statements = a
+ if '|length' in str(mdDes[c].statements1):
+ a = mdDes[c].statements1
+ a = a.replace('|length', ')').replace('if ', 'if len(self.')
+ mdDes[c].statements1 = a
+
+ def chckIf1Statements():
+ '''Return true if next item in jinjainfo::MdDescription is statement
+ '''
+ try:
+ if mdDes[self.c + 1].statement:
+ return True
+ else:
+ return False
+ except:
+ return False
+
+ def chckIf2xStatements():
+ '''Return true if next two items in jinjainfo::MdDescription are reprsenting statements
+ '''
+ if 'if'in mdDes[self.c].tag.split() or 'for' in mdDes[self.c].tag.split():
+ try:
+ if 'if'in mdDes[self.c + 1].tag.split() or 'for'in mdDes[self.c + 1].tag.split():
+ return True
+ else:
+ return False
+ except:
+ return False
+
+ def noneStatements():
+ '''Without condition or loop
+ '''
+ str1 = ''
+ for wxCtrl in mdDes[self.c].mdItem:
+ if wxCtrl.getValue() is not None:
+ str1 += 'self.' + mdDes[self.c].tag + '="' + str(wxCtrl.getValue()) + '"\n'
+ self.executeStr1(str1, mdDes[self.c])
+ str1 = ''
+ self.plusC()
+
+ def inStatements():
+ '''possible combinations of statements
+ (1) IF
+ item
+ ----------------------------------------------------
+ (2) for
+ (2.1) item (with init OWSLib object)
+ "or"
+ (2.2) item (without init)
+ item with ZIP
+ '''
+ cTmp = self.c
+ tag = str(mdDes[cTmp].tag).split()
+
+ tag1 = 'self.' + str(tag[-1])
+ tag = 'self.' + str(tag[-1]) + '.append(self.val)\n'
+
+ self.plusC()
+ # statements of current item
+ stat = mdDes[self.c].statements
+ str1 = ''
+ leng = len(mdDes[self.c].mdItem)
+
+ # (2.1) IF NECESSARY TO INITIALIZE OWSLIB OBJECT
+ if mdDes[cTmp].object and 'if' not in mdDes[cTmp].tag.split():
+ objStr = 'self.val=' + mdDes[cTmp].object + '\n'
+
+ for n in range(leng):
+ numOfItems = 0
+ str1 += objStr
+ while mdDes[self.c].statements == stat and self.stop is False:
+ metadata = re.split(r'[.]', mdDes[self.c].tag)
+ metadata[0] = 'self.val.'
+ str1 += ''.join(metadata) + "='"\
+ + str(mdDes[self.c].mdItem[n].getValue()) + "'\n"
+ self.plusC()
+ numOfItems += 1
+
+ str1 += tag
+ self.executeStr1(str1, False)
+ str1 = ''
+ self.minusC(numOfItems)
+
+ self.plusC(numOfItems)
+ # (2.2)no init and py ZIP'
+ elif 'for' in mdDes[cTmp].tag.split() and mdDes[cTmp].object is None and ' zip(' in mdDes[cTmp].tag:
+ leng = len(mdDes[self.c].mdItem)
+ tag1 = mdutil.findBetween(mdDes[cTmp].tag, 'zip(', ')').split(',')
+
+ for n in range(leng):
+ numOfItems = 0
+ while mdDes[self.c].statements == stat and self.stop is False:
+ str1 += 'self.' + tag1[numOfItems] + ".append('" + mdDes[self.c].mdItem[n].getValue() + "')\n"
+ self.plusC()
+ numOfItems += 1
+
+ self.executeStr1(str1, False)
+ str1 = ''
+ self.minusC(numOfItems)
+
+ self.plusC(numOfItems)
+ # 'no init FOR'
+ elif 'for' in mdDes[cTmp].tag.split() and mdDes[cTmp].object is None:
+ leng = len(mdDes[self.c].mdItem)
+ numOfItems = 0
+ for n in range(leng):
+ numOfItems = 0
+ while mdDes[self.c].statements == stat and self.stop is False:
+ str1 += tag1 + ".append('" + mdDes[self.c].mdItem[n].getValue() + "')\n"
+ self.plusC()
+ numOfItems += 1
+
+ self.executeStr1(str1, False)
+ str1 = ''
+ self.minusC(numOfItems)
+
+ self.plusC(numOfItems)
+ # (1)'no init IF'
+ elif 'if' in mdDes[cTmp].tag.split():
+
+ objStr = mdDes[cTmp].tag.replace(' md.', ' self.md.') + ':\n'
+
+ for n in range(leng):
+ numOfItems = 0
+ while mdDes[self.c].statements == stat and self.stop is False:
+ metadata = 'self.' + mdDes[self.c].tag
+ str1 += ''.join(metadata) + "='"\
+ + str(mdDes[self.c].mdItem[n].getValue()) + "'\n"
+ self.plusC()
+ numOfItems += 1
+
+ self.minusC(numOfItems)
+ self.executeStr1(str1, False)
+ str1 = ''
+ self.plusC(numOfItems)
+
+ def in2Statements():
+ '''possible combinations of statements
+ (1) IF:
+ FOR:
+ (1.1) item (with init OWSLib object)
+ "or"
+ (1.2) item (without init)
+ ----------------------------------------------------
+ (2) FOR:
+ FOR:(implemented fixedly just for MD-keywords)
+ (2.1) item (with init OWSLib object)
+ "or"
+ (2.2) item (without init)
+ '''
+ prepareStatements()
+ cTmp = self.c
+ cTmp1 = self.c + 1
+ tag = str(mdDes[cTmp].tag).split()
+ tag1 = str(mdDes[cTmp1].tag).split()
+ stat = mdDes[self.c + 2].statements
+
+ append = 'self.' + str(tag1[-1]) + '.append(self.val)\n'
+ appendNoInit = 'self.' + str(tag1[-1])
+ # (1)
+ # if statements-if in jinja template=skip and do single loop
+ if 'if' in tag and 'for' in tag1:
+ leng = len(mdDes[self.c + 2].mdItem)
+ # (1.1)
+ if mdDes[cTmp1].object:
+ condition = mdDes[cTmp].tag.replace(' md.', ' self.md.') + ':\n'
+ objectOWSLib = '\t' + 'self.val=' + mdDes[cTmp1].object + '\n'
+ condition2 = '\t' + mdDes[cTmp1].tag.replace(' md.', ' self.md.') + ':\n'
+ self.plusC()
+ self.plusC()
+
+ for n in range(leng):
+ numOfItems = 0
+ str1 = condition + '\n'
+ str1 += condition2 + '\n'
+ str1 += '\t' + objectOWSLib + '\n'
+
+ while mdDes[self.c].statements == stat and self.stop is False:
+ metadata = re.split(r'[.]', mdDes[self.c].tag)
+ metadata[0] = '\t\tself.val'
+ str1 += ''.join(metadata) + "='" + str(mdDes[self.c].mdItem[n].getValue()) + "'\n"
+ self.plusC()
+ numOfItems += 1
+
+ str1 += '\t\t' + append
+ self.executeStr1(str1, False)
+ str1 = ''
+ self.minusC(numOfItems)
+ self.plusC(numOfItems)
+ # (1.2)"if and for "
+ else:
+ self.plusC()
+ self.plusC()
+ numOfItems = 0
+ size = len(mdDes[self.c].mdItem)
+ for n in range(size):
+ numOfItems = 0
+ str1 = ''
+
+ while mdDes[self.c].statements == stat and self.stop is False:
+ str1 += appendNoInit + '.append("' + mdDes[self.c].mdItem[n].getValue() + '")\n'
+ self.plusC()
+ numOfItems += 1
+
+ self.executeStr1(str1, False)
+ self.minusC(numOfItems)
+ self.plusC(numOfItems)
+ # (2) only keywords (dict)
+ elif 'for' in tag and 'for' in tag1: #
+ self.plusC() # skip staementes 2x
+ self.plusC()
+ numOfkwGroup = len(mdDes[self.c + 1].mdItem)
+ for n in range(numOfkwGroup):
+ kw = {}
+ kw['keywords'] = []
+ try:
+ keyWordLen = len(mdDes[self.c].mdItem[n])
+ for k in range(keyWordLen):
+ kw['keywords'].append(mdDes[self.c].mdItem[n][k].getValue())
+ except:
+ kw['keywords'].append(mdDes[self.c].mdItem[n].getValue())
+
+ kw['type'] = None
+ kw['thesaurus'] = {}
+ kw['thesaurus']['title'] = mdDes[self.c + 1].mdItem[n].getValue()
+ kw['thesaurus']['date'] = mdDes[self.c + 2].mdItem[n].getValue()
+ kw['thesaurus']['datetype'] = mdDes[self.c + 3].mdItem[n].getValue()
+ self.md.identification.keywords.append(kw)
+
+ self.plusC()
+ self.plusC()
+ self.plusC()
+ self.plusC()
+#------------------------------------------------------------------------------ next function
+ self.mdo = MdFileWork()
+ self.md = self.mdo.initMD()
+ # most of object from OWSLib is initialized in configure file
+ dirpath = os.path.dirname(os.path.realpath(__file__))
+ path = os.path.join(dirpath, 'config', 'init_md')
+ mdInitData = open(path, 'r')
+ mdExec = mdInitData.read()
+ self.executeStr1(mdExec, None)
+
+ self.c = 0
+ self.stop = False
+ self.max = len(self.mdDescription)
+ mdDes = self.mdDescription
+
+ while self.stop is False:
+ # if no statements
+ if mdDes[self.c].statements is None\
+ and 'if' not in mdDes[self.c].tag.split()\
+ and 'for' not in mdDes[self.c].tag.split():
+ noneStatements()
+
+ # if 2x statements
+ elif chckIf2xStatements():
+ in2Statements()
+
+ # if 1x statements
+ elif chckIf1Statements:
+ inStatements()
+
+ return self.md
+#------------------------------------ END- FILL OWSLib BY EDITED METADATA IN GUI
+
+ def exportToXml(self, jinjaPath, outPath, xmlOutName, msg):
+ self.createNewMD()
+ self.mdo.saveToXML(self.md, None, jinjaPath, outPath, xmlOutName, msg)
+
+ def exportTemplate(self, jinjaPath, outPath, xmlOutName):
+ self.templatePath = jinjaPath
+ owsTagList = self.defineTemplate()
+ self.createNewMD()
+ self.mdo.saveToXML(self.md, owsTagList,
+ self.templatePath,
+ outPath,
+ xmlOutName,
+ msg=True,
+ rmTeplate=True)
+#------------------------------------------------------------------------ LAYOUT
+
+ def _layout(self):
+ self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(self.mainSizer)
+ noteSizer = wx.BoxSizer(wx.VERTICAL)
+ self.notebook.SetSizer(noteSizer)
+ self.mainSizer.Add(self.notebook, proportion=1, flag=wx.EXPAND)
+ self.Show()
+#----------------------------------------------------------------------
+if __name__ == "__main__":
+ app = wx.App(False)
+ frame = MdMainEditor()
+ app.MainLoop()
Copied: grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/g.gui.metadata.html (from rev 61594, grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata.html)
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/g.gui.metadata.html (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/g.gui.metadata.html 2014-08-13 20:15:41 UTC (rev 61595)
@@ -0,0 +1,5 @@
+<h2>DESCRIPTION</h2>
+Metadata editor according to EN ISO 19115 and EN ISO 19119
+<h2>AUTHOR</h2>
+
+Matej Krejci, Czech Technical University in Prague, Czech Republic
Copied: grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/g.gui.metadata.py (from rev 61594, grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata.py)
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/g.gui.metadata.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata/g.gui.metadata.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -0,0 +1,1155 @@
+#!/usr/bin/env python
+# -*- coding: utf-8
+"""
+ at module g.gui.metadata
+ at brief GUI components of metadata editor
+
+Classes:
+ - g.gui.metadata::MdMainFrame
+ - g.gui.metadata::MdDataCatalog
+ - g.gui.metadata::NotebookRight
+ - g.gui.metadata::MDHelp
+ - g.gui.metadata::TreeBrowser
+ - g.gui.metadata::MdValidator
+ - g.gui.metadata::MdEditConfigPanel
+ - g.gui.metadata::MdToolbar
+
+(C) 2014 by 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.
+
+ at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
+"""
+
+import wx
+from wx.lib.buttons import ThemedGenBitmapTextButton as BitmapBtnTxt
+from wx import SplitterWindow, EVT_BUTTON
+from wx.lib.pubsub import setupkwargs, pub
+from editor import MdMainEditor
+
+import glob
+import os
+import sys
+import mdgrass
+import mdutil
+from lxml import etree
+
+import grass.script as grass
+import grass.script.setup as gsetup
+from lmgr import datacatalog
+from core.gcmd import RunCommand, GError, GMessage
+
+#===============================================================================
+# MAIN FRAME
+#===============================================================================
+
+
+class MdMainFrame(wx.Frame):
+
+ '''Main frame of metadata editor
+ '''
+
+ def __init__(self, jinjaPath=None, xmlPath=None, init=False):
+ '''
+ @param jinjaPath: path to jinja template
+ @param xmlPath: path to xml with will be read by editor
+ @var first,firstAfterChoice,second,secondAfterChoice,secondMultiEdit: initMultipleEditor() and onInitEditor() handler
+ @var self. initMultipleEditor() and onInitEditor() handler
+ @var self.templateEditor: true= Editor is in mode 'Template creator(widgets with chkbox)'
+ @var nameTMPtemplate: in case if 'template editor is on' this var holds name oof temporaly jinja template
+ @var batch: if true multiple editing metadata of maps is ON
+ '''
+ wx.Frame.__init__(self, None, title="Metadata Editor", size=(650, 500))
+ self.initDefaultPathStorageMetadata()
+
+ self.jinjaPath = jinjaPath
+ self.xmlPath = xmlPath
+ self.first = True
+ self.firstAfterChoice = False
+ self.second = False
+ self.secondAfterChoice = False
+ self.secondMultiEdit = False
+
+ self.templateEditor = False
+ self.sb = self.CreateStatusBar()
+
+ self.cres = 0 # resizeFrame
+ self.nameTMPteplate = None
+ self.batch = False
+
+ self.onInitEditor()
+
+ pub.subscribe(self.initNewMD, 'NEW_MD.create')
+ pub.subscribe(self.onEditingMode, 'EDITING_MODE.update')
+ pub.subscribe(self.setStatusbarText, 'STATUS_BAR_TEXT.update')
+ pub.subscribe(self.onExportTemplate, 'EXPORT_TEMPLATE.create')
+ pub.subscribe(self.onExportXML, 'EXPORT_XML.create')
+ pub.subscribe(self.onEditMapMetadata, 'EDIT_MAP_METADATA.create')
+ pub.subscribe(self.onInitEditor, 'INIT_EDITOR.create')
+ pub.subscribe(self.onTemplateEditor, 'TEMPLATE_EDITOR_STATUS.update')
+ pub.subscribe(self.onHideLeftPanel, 'HIDE_LEFT_PANEL.update')
+ pub.subscribe(self.onRefreshTreeBrowser, 'REFRESH_TREE_BROWSER.update')
+ pub.subscribe(self.onChangeEditMapProfile, 'ISO_PROFILE.update')
+ pub.subscribe(self.onUpdateGrassMetadata, 'GRASS_METADATA.update')
+ pub.subscribe(self.setMdDestionation, 'MD_DESTINATION.update')
+ pub.subscribe(self.onSetJaX, 'SET_JINJA_AND_XML.update')
+
+ def onSetJaX(self, jinja, xml):
+ '''Set template ad xml paths
+ '''
+ self.jinjaPath = jinja
+ self.xmlPath = xml
+
+ def setMdDestionation(self, value):
+ '''Set md
+ '''
+ self.mdDestination = value
+
+ def initDefaultPathStorageMetadata(self):
+ '''set working folder
+ '''
+ self.mdDestination = os.path.join(mdutil.pathToMapset(), 'metadata')
+ if not os.path.exists(self.mdDestination):
+ os.makedirs(self.mdDestination)
+
+ def onUpdateGrassMetadata(self):
+ '''Update r.support and v.support
+ '''
+ md = self.editor.createNewMD()
+ self.mdCreator.updateGrassMd(md)
+ GMessage('Grass metadata has been updated')
+
+ def onChangeEditMapProfile(self):
+ '''Update vars
+ '''
+ self.templateChoice = self.configPanelLeft.comboBoxProfile.GetValue()
+ self.ntbRight.profile = self.templateChoice
+
+ def onExportTemplate(self, outPath, outFileName):
+ '''Export defined(pre-filled) template
+ '''
+ self.editor.exportTemplate(self.jinjaPath,
+ outPath=outPath,
+ xmlOutName=outFileName)
+
+ def onExportXML(self, outPath, outFileName):
+ '''Save metadta xml file
+ '''
+ if outPath is None and outFileName is None:
+ XMLhead, XMLtail = os.path.split(self.xmlPath)
+ self.editor.exportToXml(self.jinjaPath,
+ outPath=XMLhead,
+ xmlOutName=XMLtail,
+ msg=False)
+ else:
+ self.editor.exportToXml(self.jinjaPath,
+ outPath=outPath,
+ xmlOutName=outFileName,
+ msg=True)
+
+ def onRefreshTreeBrowser(self):
+ '''Update changes from editor in tree browser
+ '''
+ path = os.path.dirname(os.path.realpath(__file__))
+ name = 'refreshTreeBrowser.xml'
+ self.editor.exportToXml(self.jinjaPath,
+ outPath=path,
+ xmlOutName=name,
+ msg=False)
+
+ pathName = os.path.join(path, name)
+ self.ntbRight.refreshXmlBrowser(pathName)
+ os.remove(pathName)
+
+ def setStatusbarText(self, text):
+ '''Set status text
+ '''
+ self.sb.SetStatusText(text)
+
+ def onTemplateEditor(self, value, template=None):
+ '''Update local var
+ '''
+ self.templateEditor = value
+ if template == None:
+ self.nameTMPteplate = 'TMPtemplate'
+ if template == False:
+ self.nameTMPteplate = None
+
+ def initNewMD(self):
+ '''Init new md OWSLib object
+ '''
+ self.editor.createNewMD()
+ self.ntbRight.md = self.editor.md
+
+ def resizeFrame(self, x1=1, y1=0):
+ '''Some widgets need refresh frame for proper working
+ '''
+ self.cres += 1
+ if (self.cres % 2 == 0) and x1 == 1 and y1 == 0:
+ x1 = -1
+ x, y = self.GetSize()
+ self.SetSize((x + x1, y + y1))
+
+ def onHideLeftPanel(self):
+ '''in editing mode is config panel hidden
+ '''
+ self.toolbar.bttNew.Enable()
+ self.Hsizer.Remove(self.leftPanel)
+ self.Hsizer.Layout()
+ self.leftPanel.SetSize((1, 1))
+
+ def onEditingMode(self, editStatus):
+ self.resizeFrame()
+ self.Layout()
+
+ if editStatus:
+ self.MdDataCatalogPanelLeft.Show()
+ self.toolbar.bttLoad.Disable()
+ self.toolbar.bttLoadXml.Disable()
+ else:
+ self.MdDataCatalogPanelLeft.Hide()
+ self.toolbar.bttEdit.Disable()
+ self.toolbar.bttCreateTemplate.Disable()
+ self.toolbar.bttLoad.Enable()
+ self.toolbar.bttLoadXml.Enable()
+ self.sb.SetStatusText('')
+ self.MdDataCatalogPanelLeft.UnselectAll()
+
+ def onEditMapMetadata(self, multipleEditing=False):
+ '''Initialize editor by selection of grass map in data catalog
+ @param multipleEditing: if user select more than one map mutlipleEditing=True
+ @param numOfMap: hold information about number of selected maps for editing
+ @param ListOfMapTypeDict: list of dict sttored names of selected maps in dict. dict['cell/vector']=nameofmaps
+ '''
+ if not multipleEditing:
+ self.ListOfMapTypeDict = self.MdDataCatalogPanelLeft.ListOfMapTypeDict
+
+ self.templateChoice = self.configPanelLeft.comboBoxProfile.GetValue()
+ self.numOfMap = len(self.ListOfMapTypeDict)
+
+ if self.numOfMap == 0 and multipleEditing is False:
+ GMessage('Select map in data catalog...')
+ return
+
+ # if editing just one map
+ if self.numOfMap == 1 and multipleEditing is False:
+ self.mdCreator = mdgrass.GrassMD(self.ListOfMapTypeDict[-1][self.ListOfMapTypeDict[-1].keys()[0]],
+ self.ListOfMapTypeDict[-1].keys()[0])
+ if self.templateChoice == 'INSPIRE':
+ self.mdCreator.createGrassInspireISO()
+ self.jinjaPath = self.mdCreator.templatePathAbs
+ self.xmlPath = self.mdCreator.saveXML(self.mdDestination, self.nameTMPteplate, self)
+ self.onInitEditor()
+
+ elif self.templateChoice == 'GRASS BASIC':
+ self.mdCreator.createGrassBasicISO()
+ self.jinjaPath = self.mdCreator.templatePathAbs
+ self.xmlPath = self.mdCreator.saveXML(self.mdDestination, self.nameTMPteplate, self)
+ self.onInitEditor()
+
+ # if editing multiple maps or just one but with loading own custom template
+ if self.templateChoice == 'Load Custom' and self.numOfMap != 0:
+ # load template. IF for just one map ELSE for multiple editing
+ if multipleEditing is False:
+ dlg = wx.FileDialog(self, "Select template", os.getcwd(), "", "*.xml", wx.OPEN)
+ if dlg.ShowModal() == wx.ID_OK:
+ self.mdCreator = mdgrass.GrassMD(self.ListOfMapTypeDict[-1][self.ListOfMapTypeDict[-1].keys()[0]],
+ self.ListOfMapTypeDict[-1].keys()[0])
+ self.mdCreator.createGrassInspireISO()
+ self.jinjaPath = dlg.GetPath()
+ self.xmlPath = self.mdCreator.saveXML(self.mdDestination, self.nameTMPteplate, self)
+ # if multiple map are selected
+ if self.numOfMap > 1:
+ self.toolbar.xmlPath = self.xmlPath
+ self.toolbar.jinjaPath = self.jinjaPath
+ self.batch = True
+ self.ListOfMapTypeDict.pop()
+ self.initMultipleEditor()
+ else:
+ self.ListOfMapTypeDict.pop()
+ self.onInitEditor()
+ else: # do nothing
+ return False
+ else:
+ self.mdCreator = mdgrass.GrassMD(self.ListOfMapTypeDict[-1][self.ListOfMapTypeDict[-1].keys()[0]],
+ self.ListOfMapTypeDict[-1].keys()[0])
+ self.mdCreator.createGrassInspireISO()
+ self.xmlPath = self.mdCreator.saveXML(self.mdDestination, self.nameTMPteplate, self)
+ self.toolbar.xmlPath = self.xmlPath
+ self.toolbar.jinjaPath = self.jinjaPath
+ self.ListOfMapTypeDict
+ self.initMultipleEditor()
+ self.ListOfMapTypeDict.pop()
+
+ if not multipleEditing:
+ self.onHideLeftPanel()
+
+ if self.numOfMap == 0 and multipleEditing is True:
+ multipleEditing = False
+ self.toolbar.onNewSession(None)
+ GMessage('All selected maps are edited')
+ self.secondMultiEdit = True
+
+ if self.batch and multipleEditing:
+ XMLhead, XMLtail = os.path.split(self.xmlPath)
+ self.batch = mdutil.yesNo(self, 'Do you want to save metadata of : %s without editing ? ' % XMLtail, 'Multiple editing')
+
+ if self.batch:
+ self.toolbar.batch = True
+ self.toolbar.onSaveXML()
+ return True
+
+ def initMultipleEditor(self):
+ '''initialize multiple editing mode
+ '''
+ if self.firstAfterChoice and not self.secondMultiEdit:
+ self.splitter = SplitterWindow(self, style=wx.SP_3D |
+ wx.SP_LIVE_UPDATE | wx.SP_BORDER)
+ self.Hsizer.Add(self.splitter, proportion=1, flag=wx.EXPAND)
+
+ self.firstAfterChoice = False
+ self.secondAfterChoice = True
+ self.toolbar.bttsave.SetLabel('next')
+ self.toolbar.hideMultipleEdit()
+ self.mainSizer.Layout()
+ self.editor = MdMainEditor(self.splitter,
+ self.jinjaPath,
+ self.xmlPath,
+ self.templateEditor)
+ self.ntbRight = NotebookRight(self.splitter, self.xmlPath)
+ self.splitter.SplitVertically(self.editor, self.ntbRight, sashPosition=0.65)
+ self.splitter.SetSashGravity(0.65)
+ self.resizeFrame()
+ self.Show()
+
+ elif self.secondAfterChoice or self.secondMultiEdit:
+ if self.secondMultiEdit:
+ self.toolbar.bttsave.SetLabel('next')
+ self.toolbar.hideMultipleEdit()
+ self.second = False
+ self.secondAfterChoice = True
+ self.onInitEditor()
+
+ def onInitEditor(self,):
+ '''Initialize editor
+ @var first: True= First initialize main frame
+ @var firstAfterChoice: True=Init editor editor after set configuration and click onEdit in toolbar
+ @var second: init editor after first initialize
+ @var secondAfterChoice: init edito onemore time
+ '''
+ if self.first:
+ self.first = False
+ self.firstAfterChoice = True
+ self.toolbar = MdToolbar(self,
+ self.jinjaPath,
+ self.xmlPath,
+ self.sb,
+ self.mdDestination)
+
+ self.leftPanel = wx.Panel(self, id=wx.ID_ANY)
+ self.configPanelLeft = MdEditConfigPanel(self.leftPanel)
+ self.MdDataCatalogPanelLeft = MdDataCatalog(self.leftPanel)
+
+ self._layout()
+ self.Show()
+
+ elif self.firstAfterChoice:
+ self.splitter = SplitterWindow(self, style=wx.SP_3D | wx.SP_LIVE_UPDATE | wx.SP_BORDER)
+ self.secondMultiEdit = True
+ self.firstAfterChoice = False
+ self.second = True
+
+ self.editor = MdMainEditor(parent=self.splitter,
+ templatePath=self.jinjaPath,
+ xmlMdPath=self.xmlPath,
+ templateEditor=self.templateEditor)
+
+ self.ntbRight = NotebookRight(self.splitter, self.xmlPath)
+
+ self.splitter.SplitVertically(self.editor, self.ntbRight, sashPosition=0.65)
+ self.splitter.SetSashGravity(0.65)
+ self.Hsizer.Add(self.splitter, proportion=1, flag=wx.EXPAND)
+ self.splitter.SizeWindows()
+ self.resizeFrame()
+ self.Show()
+
+ elif self.second: # if next initializing of editor
+ self.second = False
+ self.secondAfterChoice = True
+ self.splitter.Hide()
+ self.toolbar.bttNew.Disable()
+ self.toolbar.bttsave.Disable()
+
+ self.Hsizer.Insert(0, self.leftPanel, proportion=1, flag=wx.EXPAND)
+ self.resizeFrame()
+
+ elif self.secondAfterChoice:
+ self.secondAfterChoice = False
+ self.second = True
+ self.splitter.Show()
+ self.toolbar.bttNew.Enable()
+ self.toolbar.bttsave.Enable()
+
+ ntbRightBCK = self.ntbRight
+ self.ntbRight = NotebookRight(self.splitter, self.xmlPath)
+ self.splitter.ReplaceWindow(ntbRightBCK, self.ntbRight)
+
+ editorTMP = self.editor
+ self.editor = MdMainEditor(parent=self.splitter,
+ templatePath=self.jinjaPath,
+ xmlMdPath=self.xmlPath,
+ templateEditor=self.templateEditor)
+
+ self.splitter.ReplaceWindow(editorTMP, self.editor)
+ ntbRightBCK.Destroy()
+ editorTMP.Destroy()
+ self.resizeFrame()
+ self.Show()
+ self.splitter.SetSashGravity(0.35)
+ else:
+ GMessage('Select map in data catalog...')
+
+ self.toolbar.xmlPath = self.xmlPath
+ self.toolbar.jinjaPath = self.jinjaPath
+
+ def _layout(self):
+
+ self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(self.mainSizer)
+
+ self.mainSizer.Add(self.toolbar)
+ self.mainSizer.Add(wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL, size=(10000, 5)))
+ self.mainSizer.AddSpacer(5, 5, 1, wx.EXPAND)
+
+ self.leftPanelSizer = wx.BoxSizer(wx.VERTICAL)
+ self.leftPanel.SetSizer(self.leftPanelSizer)
+ self.leftPanelSizer.Add(self.configPanelLeft, proportion=0, flag=wx.EXPAND)
+ self.leftPanelSizer.AddSpacer(5, 5, 1, wx.EXPAND)
+ self.leftPanelSizer.Add(self.MdDataCatalogPanelLeft, proportion=1, flag=wx.EXPAND)
+
+ self.Hsizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.mainSizer.Add(self.Hsizer, proportion=1, flag=wx.EXPAND)
+
+ self.Hsizer.Add(self.leftPanel, proportion=1, flag=wx.EXPAND)
+
+ self.resizeFrame(300, 0)
+ self.Layout()
+#===============================================================================
+# DATA CATALOG
+#===============================================================================
+
+
+class MdDataCatalog(datacatalog.LocationMapTree):
+
+ '''Data catalog for selecting GRASS maps for editing
+ '''
+
+ def __init__(self, parent):
+ """Test Tree constructor."""
+ super(MdDataCatalog, self).__init__(parent=parent,
+ style=wx.TR_MULTIPLE | wx.TR_HIDE_ROOT | wx.TR_HAS_BUTTONS |
+ wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_COLUMN_LINES)
+ self.InitTreeItems()
+ self.map = None
+ self.mapType = None
+
+ def InitTreeItems(self):
+ """Add locations and layers to the tree."""
+ gisenv = grass.gisenv()
+ location = gisenv['LOCATION_NAME']
+ self.mapset = gisenv['MAPSET']
+
+ self._initTreeItems(locations=[location], mapsets=[self.mapset])
+ self.ExpandAll()
+ self.Bind(wx.EVT_TREE_SEL_CHANGED, self.onChanged)
+ self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.onChanged)
+
+ def onChanged(self, evt=None):
+ '''
+ @var ListOfMapTypeDict: list of dic with maps and map-type values
+ @var MapTypeDict: keys= type of map(cell/vector), value=<map name>
+ '''
+ self.ListOfMapTypeDict = list()
+ maps = list()
+ if self.GetChildrenCount(evt.Item) == 0: # is selected map
+ for item in self.GetSelections():
+ MapTypeDict = {}
+ maps.append(self.GetItemText(item))
+ map = self.GetItemText(item) + '@' + self.mapset
+ mapType = self.GetItemParent(item)
+ mapType = self.GetItemText(mapType)
+
+ if mapType == 'vect':
+ mapType = 'vector'
+ elif mapType == 'rast':
+ mapType = 'cell'
+ MapTypeDict[mapType] = map
+
+ self.ListOfMapTypeDict.append(MapTypeDict)
+ pub.sendMessage('bttEdit.enable')
+ pub.sendMessage('bttCreateTemplate.enable')
+
+ else:
+ self.Unselect()
+ GMessage('Please select map.')
+
+ if len(maps) == 0:
+ pub.sendMessage('bttEdit.disable')
+ pub.sendMessage('bttCreateTemplate.disable')
+ str1 = ''
+
+ for map in maps:
+ str1 += map + ' '
+
+ if len(maps) > 1:
+ pub.sendMessage('SET_PROFILE.update', profile='Load Custom')
+
+ pub.sendMessage('comboBoxProfile.disable')
+ pub.sendMessage('bttCreateTemplate.disable')
+ else:
+ pub.sendMessage('comboBoxProfile.enable')
+ pub.sendMessage('bttCreateTemplate.enable')
+
+ pub.sendMessage('STATUS_BAR_TEXT.update', text=str1)
+
+#===============================================================================
+# NOTEBOOK ON THE RIGHT SIDE-xml browser+validator
+#===============================================================================
+
+
+class NotebookRight(wx.Notebook):
+
+ '''Include pages with xml tree browser and validator of metadata
+ '''
+
+ def __init__(self, parent, path):
+
+ wx.Notebook.__init__(self, parent=parent, id=wx.ID_ANY)
+ # first panel
+ self.notebookValidator = wx.Panel(self, wx.ID_ANY)
+ self.validator = MdValidator(self.notebookValidator)
+ self.xmlPath = path
+ self.profile = None
+ self.buttValidate = wx.Button(self.notebookValidator,
+ id=wx.ID_ANY,
+ size=(70, 50),
+ label='validate')
+
+ self.notebook_panel1 = wx.Panel(self, wx.ID_ANY)
+ self.tree = TreeBrowser(self.notebook_panel1, self.xmlPath)
+ self.buttRefresh = wx.Button(
+ self.notebook_panel1,
+ id=wx.ID_ANY,
+ size=(70, 50),
+ label='refresh')
+
+ self.AddPage(self.notebookValidator, "Validator")
+ self.AddPage(self.notebook_panel1, "Tree browser")
+ # self.AddPage(self.notebook_panel2, "Help")
+
+ self.buttValidate.Bind(wx.EVT_BUTTON, self.validate)
+ self.buttRefresh.Bind(wx.EVT_BUTTON, self.onRefreshXmlBrowser)
+ self._layout()
+
+ def onActive(self):
+ pass
+
+ def onRefreshXmlBrowser(self, evt=None):
+ pub.sendMessage('REFRESH_TREE_BROWSER.update')
+
+ def refreshXmlBrowser(self, path):
+ treeBCK = self.tree
+ self.tree = TreeBrowser(self.notebook_panel1, path)
+ self.panelSizer1.Replace(treeBCK, self.tree)
+ # self.panelSizer1.Add(self.tree, flag=wx.EXPAND, proportion=1)
+ self.panelSizer1.Layout()
+ treeBCK.Destroy()
+
+ def validate(self, evt):
+ self.md = None
+ pub.sendMessage('NEW_MD.create')
+ pub.sendMessage('ISO_PROFILE.update')
+ self.validator.validate(self.md, self.profile)
+
+ def _layout(self):
+ panelSizer0 = wx.BoxSizer(wx.VERTICAL)
+ self.notebookValidator.SetSizer(panelSizer0)
+
+ panelSizer0.Add(self.validator, flag=wx.EXPAND, proportion=1)
+ panelSizer0.Add(self.buttValidate)
+
+ self.panelSizer1 = wx.BoxSizer(wx.VERTICAL)
+ self.notebook_panel1.SetSizer(self.panelSizer1)
+ self.panelSizer1.Add(self.tree, flag=wx.EXPAND, proportion=1)
+ self.panelSizer1.Add(self.buttRefresh)
+
+ panelSizer2 = wx.BoxSizer(wx.VERTICAL)
+ # self.notebook_panel2.SetSizer(panelSizer2)
+ # panelSizer2.Add(self.notebook_panel2,flag=wx.EXPAND, proportion=1)
+#===============================================================================
+# HELP
+#===============================================================================
+
+
+class MDHelp(wx.Panel):
+
+ """
+ class MyHtmlPanel inherits wx.Panel and adds a button and HtmlWindow
+ """
+
+ def __init__(self, parent):
+ wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
+ self.html1 = wx.html.HtmlWindow(self, id=wx.ID_ANY)
+ try:
+ self.html1.LoadFile('help/help.html')
+ # self.html1.LoadPage('http://inspire-geoportal.ec.europa.eu/EUOSME_GEOPORTAL/userguide/eurlex_en.htm')
+ except:
+ pass
+
+ self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(self.mainSizer)
+ self.mainSizer.Add(self.html1, proportion=1, flag=wx.EXPAND)
+#===============================================================================
+# TREE EDITOR
+#===============================================================================
+
+
+class TreeBrowser(wx.TreeCtrl):
+
+ '''Filling text tree by xml file.
+ @note: to enable editing mode of init xml uncoment blocks below
+ '''
+
+ def __init__(self, parent, xmlPath=False, xmlEtree=False):
+ wx.TreeCtrl.__init__(self, parent=parent, id=wx.ID_ANY,
+ style=wx.TR_HAS_BUTTONS | wx.TR_FULL_ROW_HIGHLIGHT)
+ tree = self
+ if xmlPath:
+ xml = etree.parse(xmlPath)
+ self.xml = xml.getroot()
+
+ self.root = tree.AddRoot(self.xml.tag)
+ else:
+ self.xml = xmlEtree
+ self.root = xmlEtree.getroot()
+
+ root = self.fillTree()
+ self.Expand(root)
+
+ #=======================================================================
+ # self.Bind(wx.EVT_CLOSE, self.OnClose)
+ # self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEdit)
+ #=======================================================================
+ self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRClickAllChildren)
+
+ def fillTree(self):
+ root = self.root
+ xml = self.xml
+ tree = self
+
+ def add(parent, elem):
+ for e in elem:
+ if str(e).find("<!--") != -1: # skip comments
+ continue
+ tag = etree.QName(e)
+ item = tree.AppendItem(parent, tag.localname, data=None)
+ if self.GetChildrenCount(item) == 0:
+ self.SetItemBackgroundColour(item, (242, 242, 242))
+ if e.text:
+ text = e.text.strip()
+ else:
+ text = e.text
+ if text:
+ val = tree.AppendItem(item, text)
+ tree.SetPyData(val, e)
+
+ add(item, e)
+
+ add(root, xml)
+ return root
+
+ #=========================================================================
+ # def OnEdit(self, evt):
+ # elm = self.GetPyData(evt.Item)
+ #
+ # print evt.Label
+ # if elm is not None:
+ # elm.text = evt.Label
+ # self.xml.write(self.fpath, encoding="UTF-8", xml_declaration=True)
+ # self.validate()
+ #=========================================================================
+
+ #=========================================================================
+ # def OnClose(self, evt):
+ # self.Destroy()
+ #=========================================================================
+
+ def OnRClickAllChildren(self, evt):
+ if not self.IsExpanded(evt.Item):
+ self.ExpandAllChildren(evt.Item)
+ else:
+ self.CollapseAllChildren(evt.Item)
+
+#===============================================================================
+# INSPIRE VALIDATOR PANEL
+#===============================================================================
+
+
+class MdValidator(wx.Panel):
+
+ '''wx panel of notebook which support validating two natively implemented profiles
+ '''
+
+ def __init__(self, parent):
+ wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
+ self.text = wx.TextCtrl(parent, id=wx.ID_ANY, size=(0, 55),
+ style=wx.VSCROLL |
+ wx.TE_MULTILINE | wx.TE_NO_VSCROLL |
+ wx.TAB_TRAVERSAL | wx.RAISED_BORDER | wx.HSCROLL)
+ self._layout()
+
+ def _layout(self):
+ self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(self.mainSizer)
+ self.mainSizer.Add(self.text, proportion=1, flag=wx.EXPAND)
+
+ def validate(self, md, profile):
+ '''For externaly load xml file is by default inspire validator
+ '''
+ if profile == 'INSPIRE' or profile == 'Load Custom':
+ result = mdutil.isnpireValidator(md)
+ str1 = 'INSPIRE VALIDATOR\n'
+
+ if profile == 'GRASS BASIC':
+ result = mdutil.grassProfileValidator(md)
+ str1 = 'GRASS BASIC PROFILE VALIDATOR\n'
+
+ str1 += 'Status of validation: ' + result["status"] + '\n'
+ str1 += 'Numbers of errors: ' + result["num_of_errors"] + '\n'
+
+ if result["status"] != 'succeded':
+ str1 += 'Errors:\n'
+ for item in result["errors"]:
+ str1 += '\t' + str(item) + '\n'
+
+ self.text.SetValue(str1)
+
+#===============================================================================
+# CONFIGURATION PANEL ON THE LEFT SIDE
+#===============================================================================
+
+
+class MdEditConfigPanel(wx.Panel):
+
+ '''Configuration pane for selection editing mode.
+ @var mapGrassEdit: True = editing metadata of GRASS maps, false= editing externally loaded xml and template
+ '''
+
+ def __init__(self, parent):
+ wx.Panel.__init__(self, parent, id=wx.ID_ANY)
+ self.SetMinSize((240, -1))
+ self.mapGrassEdit = True
+
+ self.rbGrass = wx.RadioButton(self, id=wx.ID_ANY, label='Metadata map editor', style=wx.RB_GROUP)
+ self.rbExternal = wx.RadioButton(self, id=wx.ID_ANY, label='Metadata external editor')
+
+ self.comboBoxProfile = wx.ComboBox(self, choices=['INSPIRE', 'GRASS BASIC', 'Load Custom'])
+ pub.subscribe(self.onComboboxDisable, "comboBoxProfile.disable")
+ pub.subscribe(self.onComboboxEnable, "comboBoxProfile.enable")
+ pub.subscribe(self.onSetProfile, "SET_PROFILE.update")
+ self.comboBoxProfile.SetStringSelection('GRASS BASIC')
+
+ self.Bind(wx.EVT_RADIOBUTTON, self.onSetRadioType, id=self.rbGrass.GetId())
+ self.Bind(wx.EVT_RADIOBUTTON, self.onSetRadioType, id=self.rbExternal.GetId())
+ self.comboBoxProfile.Bind(wx.EVT_COMBOBOX, self.onChangeComboBoxProfile)
+
+ self._layout()
+
+ def onChangeComboBoxProfile(self, evt):
+ pass
+
+ def onComboboxDisable(self):
+ self.comboBoxProfile.Disable()
+
+ def onComboboxEnable(self):
+ self.comboBoxProfile.Enable()
+
+ def onSetProfile(self, profile):
+ self.comboBoxProfile.SetStringSelection(profile)
+
+ def SetVal(self, event):
+ state1 = str()
+ state2 = str(self.rb2.GetValue())
+
+ self.statusbar.SetStatusText(state1, 0)
+ self.statusbar.SetStatusText(state2, 1)
+
+ def onSetRadioType(self, evt=None):
+ self.mapGrassEdit = self.rbGrass.GetValue()
+ if self.mapGrassEdit == False:
+ self.comboBoxProfile.Hide()
+ else:
+ self.comboBoxProfile.Show()
+ pub.sendMessage('EDITING_MODE.update', editStatus=self.mapGrassEdit)
+
+ def _layout(self):
+ self.mainsizer = wx.BoxSizer(wx.VERTICAL)
+ self.SetSizer(self.mainsizer)
+ self.mainsizer.Add(self.rbGrass)
+ self.mainsizer.Add(self.rbExternal)
+ self.mainsizer.Add(self.comboBoxProfile)
+#===============================================================================
+# TOOLBAR
+#===============================================================================
+
+
+class MdToolbar(wx.Panel):
+
+ '''Main toolbar of editor
+ '''
+
+ def __init__(self, parent, jinjaPath, xmlPath, sb, mdDestionation):
+ wx.Panel.__init__(self, parent, id=wx.ID_ANY)
+ self.mdDestination = mdDestionation
+ self.batch = False
+ self.jinjaPath = jinjaPath
+ self.statusBar = sb
+ self.xmlPath = xmlPath
+ self.extendEdit = False
+ self.toolbar = wx.ToolBar(self, 1, wx.DefaultPosition, (-1, -1))
+
+ bitmapSave = wx.Image(
+ os.path.join(os.environ['GISBASE'], 'gui', 'icons', 'grass', 'save.png'),
+ wx.BITMAP_TYPE_PNG).ConvertToBitmap()
+ bitmapNew = wx.Image(
+ os.path.join(os.environ['GISBASE'], 'gui', 'icons', 'grass', 'create.png'),
+ wx.BITMAP_TYPE_PNG).ConvertToBitmap()
+ bitmapLoad = wx.Image(
+ os.path.join(os.environ['GISBASE'], 'gui', 'icons', 'grass', 'open.png'),
+ wx.BITMAP_TYPE_PNG).ConvertToBitmap()
+ bitmaSettings = wx.Image(
+ os.path.join(os.environ['GISBASE'], 'gui', 'icons', 'grass', 'settings.png'),
+ wx.BITMAP_TYPE_PNG).ConvertToBitmap()
+#-------------------------------------------------------------------- EDIT
+ self.toolbar.AddSeparator()
+ bitmapEdit = wx.Image(
+ os.path.join(os.environ['GISBASE'], 'gui', 'icons', 'grass', 'edit.png'),
+ wx.BITMAP_TYPE_PNG).ConvertToBitmap()
+ self.bttEdit = BitmapBtnTxt(
+ self.toolbar, -1, bitmapEdit, 'edit')
+ self.toolbar.AddControl(control=self.bttEdit)
+ self.bttEdit.Disable()
+#-------------------------------------------------------------------- NEW SESION
+ self.toolbar.AddSeparator()
+ self.bttNew = BitmapBtnTxt(self.toolbar, -1, bitmapNew, 'session')
+ self.toolbar.AddControl(control=self.bttNew)
+ self.bttNew.Disable()
+#-------------------------------------------------------------------------- SAVE
+ self.bttsave = BitmapBtnTxt(self.toolbar, -1, bitmapSave, "XML")
+ self.bttsave.Disable()
+ self.toolbar.AddControl(control=self.bttsave)
+ self.toolbar.AddSeparator()
+#----------------------------------------------------------------- OPEN TEMPLATE
+ self.bttLoad = BitmapBtnTxt(self.toolbar, -1, bitmapLoad, "template", size=(100, -1))
+ self.toolbar.AddControl(control=self.bttLoad)
+ self.bttLoad.Disable()
+#---------------------------------------------------------------------- OPEN XML
+ self.bttLoadXml = BitmapBtnTxt(self.toolbar, -1, bitmapLoad, "XML")
+ self.toolbar.AddControl(control=self.bttLoadXml)
+ self.bttLoadXml.Disable()
+ self.toolbar.AddSeparator()
+#-------------------------------------------------------------------- NEW TEMPLATE
+ self.bttCreateTemplate = BitmapBtnTxt(self.toolbar, -1, bitmapNew, "template", size=(100, -1))
+ self.toolbar.AddControl(control=self.bttCreateTemplate)
+ self.bttCreateTemplate.Disable()
+#-------------------------------------------------------------------------- SAVE
+ self.bttSaveTemplate = BitmapBtnTxt(self.toolbar, -1, bitmapSave, "template", size=(100, -1))
+ self.bttSaveTemplate.Disable()
+ self.toolbar.AddControl(control=self.bttSaveTemplate)
+ self.toolbar.AddSeparator()
+#-------------------------------------------------------------------------- SAVE
+ self.bttUpdateGRASS = BitmapBtnTxt(self.toolbar, -1, bitmapSave, "GRASS", size=(100, -1))
+ self.bttUpdateGRASS.Disable()
+ self.toolbar.AddControl(control=self.bttUpdateGRASS)
+ self.toolbar.AddSeparator()
+#-------------------------------------------------------------------------- Config
+ self.bttConfig = BitmapBtnTxt(self.toolbar, -1, bitmaSettings, "workdir", size=(100, -1))
+ self.toolbar.AddControl(control=self.bttConfig)
+ self.toolbar.AddSeparator()
+
+ self.toolbar.Realize()
+ self._layout()
+
+ self.bttLoad.Bind(wx.EVT_BUTTON, self.OnLoadTemplate)
+ pub.subscribe(self.onBttSaveEnable, "bttLoad.enable")
+ pub.subscribe(self.onBttSaveDisable, "bttLoad.disable")
+
+ self.bttsave.Bind(wx.EVT_BUTTON, self.onSaveXML)
+ pub.subscribe(self.onBttLoadEnable, "bttSave.enable")
+ pub.subscribe(self.onBttLoadDisable, "bttSave.disable")
+
+ self.bttLoadXml.Bind(wx.EVT_BUTTON, self.onLoadXml)
+ pub.subscribe(self.onBttLoadXmlEnable, "bttLoadXml.enable")
+ pub.subscribe(self.onBttLoadXmlDisable, "bttLoadXml.disable")
+
+ self.bttNew.Bind(wx.EVT_BUTTON, self.onNewSession)
+ pub.subscribe(self.onBttNewEnable, "bttNew.enable")
+ pub.subscribe(self.onBttNewDisable, "bttNew.disable")
+
+ self.bttEdit.Bind(wx.EVT_BUTTON, self.onEdit)
+ pub.subscribe(self.onBtEditEnable, "bttEdit.enable")
+ pub.subscribe(self.onBttEditDisable, "bttEdit.disable")
+
+ self.bttCreateTemplate.Bind(wx.EVT_BUTTON, self.onCreateTemplate)
+ pub.subscribe(self.onBttCreateTemplateEnable, "bttCreateTemplate.enable")
+ pub.subscribe(self.onBttCreateTemplateDisable, "bttCreateTemplate.disable")
+
+ self.bttSaveTemplate.Bind(wx.EVT_BUTTON, self.onSaveTemplate)
+ pub.subscribe(self.onBttSaveTemplateEnable, "bttSaveTemplate.enable")
+ pub.subscribe(self.onBttSaveTemplateDisable, "bttSaveTemplate.disable")
+
+ self.bttUpdateGRASS.Bind(wx.EVT_BUTTON, self.onUpdateGRASS)
+ pub.subscribe(self.onBttUpdateGRASSEnable, "bttSaveTemplate.enable")
+ pub.subscribe(self.onBttUpdateGRASSDisable, "bttSaveTemplate.disable")
+
+ self.bttConfig.Bind(wx.EVT_BUTTON, self.onSettings)
+
+ def onBttSaveDisable(self):
+ self.bttSave.Disable()
+
+ def onBttSaveEnable(self):
+ self.bttSave.Enable()
+
+ def onBttLoadDisable(self):
+ self.bttLoad.Disable()
+
+ def onBttLoadEnable(self):
+ self.bttLoad.Enable()
+
+ def onBttLoadXmlDisable(self):
+ self.bttLoadXml.Disable()
+
+ def onBttLoadXmlEnable(self):
+ self.bttLoadXml.Enable()
+
+ def onBttNewDisable(self):
+ self.bttNew.Disable()
+
+ def onBttNewEnable(self):
+ self.bttNew.Enable()
+
+ def onBttEditDisable(self):
+ self.bttEdit.Disable()
+
+ def onBtEditEnable(self):
+ self.bttEdit.Enable()
+
+ def onBttCreateTemplateDisable(self):
+ self.bttCreateTemplate.Disable()
+
+ def onBttCreateTemplateEnable(self):
+ self.bttCreateTemplate.Enable()
+
+ def onBttSaveTemplateDisable(self):
+ self.bttSaveTemplate.Disable()
+
+ def onBttSaveTemplateEnable(self):
+ self.bttSaveTemplate.Enable()
+
+ def onBttUpdateGRASSDisable(self):
+ self.bttUpdateGRASS.Disable()
+
+ def onBttUpdateGRASSEnable(self):
+ self.bttUpdateGRASS.Enable()
+
+ def onUpdateGRASS(self, evt):
+ pub.sendMessage('GRASS_METADATA.update')
+
+ def onSettings(self, evt):
+ dlg = wx.DirDialog(self,
+ message="Select metadata working directory",
+ defaultPath=self.mdDestination,
+ style=wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ self.mdDestination = dlg.GetPath()
+ pub.sendMessage('MD_DESTINATION.update', value=self.mdDestination)
+ dlg.Destroy()
+
+ GMessage('Metadata destinatnion: %s' % self.mdDestination)
+
+ def hideMultipleEdit(self):
+ '''Multiple editor is off
+ '''
+
+ self.bttLoad.Hide()
+ self.bttLoadXml.Hide()
+ self.bttNew.Hide()
+ self.bttEdit.Hide()
+ self.bttCreateTemplate.Hide()
+ self.bttSaveTemplate.Hide()
+ self.bttUpdateGRASS.Hide()
+
+ def showMultipleEdit(self):
+ '''Multiple editor is on
+ '''
+ self.bttLoad.Show()
+ self.bttLoadXml.Show()
+ self.bttNew.Show()
+ self.bttEdit.Show()
+ self.bttCreateTemplate.Show()
+ self.bttSaveTemplate.Show()
+ self.bttUpdateGRASS.Show()
+
+ def onCreateTemplate(self, evt):
+ pub.sendMessage('TEMPLATE_EDITOR_STATUS.update', value=True)
+ self.onEdit(evt=None)
+ self.bttCreateTemplate.Disable()
+ self.bttSaveTemplate.Enable()
+
+ def onEdit(self, evt=None):
+ '''
+ @var : extendEdit if xml and jinja is loaded from file
+ '''
+ if self.extendEdit:
+ pub.sendMessage('SET_JINJA_AND_XML.update', jinja=self.jinjaPath, xml=self.xmlPath)
+ self.bttUpdateGRASS.Disable()
+
+ if self.GetParent().configPanelLeft.rbGrass.GetValue():
+ ok = self.GetParent().onEditMapMetadata()
+ if not ok:
+ return
+ else:
+ pub.sendMessage('INIT_EDITOR.create')
+
+ self.bttCreateTemplate.Disable()
+ self.bttEdit.Disable()
+ self.bttsave.Enable()
+ if not self.extendEdit:
+ self.bttUpdateGRASS.Enable()
+
+ try: # if multiediting mode ON
+ if self.GetParent().numOfMap > 1:
+ XMLhead, XMLtail = os.path.split(self.xmlPath)
+ self.batch = mdutil.yesNo(self, 'Do you want to save metadata of : %s without editing ? ' % XMLtail, 'Multiple editing')
+ if self.batch:
+ self.onSaveXML()
+ except:
+ pass
+
+ def onNewSession(self, evt):
+ pub.sendMessage('INIT_EDITOR.create')
+ pub.sendMessage('TEMPLATE_EDITOR_STATUS.update', value=False, template=False)
+ # chck current editing mode(grass or external xml editor)
+ if self.GetParent().configPanelLeft.rbGrass is False:
+ self.bttLoad.Enable()
+ self.bttLoadXml.Enable()
+ self.statusBar.SetStatusText('')
+ self.bttsave.Disable()
+ self.bttUpdateGRASS.Disable()
+ self.jinjaPath = None
+ self.xmlPath = None
+ self.bttsave.SetLabel('XML')
+ self.showMultipleEdit()
+
+ self.bttSaveTemplate.Disable()
+
+ def onChangeXmlorTemplate(self, evt=None):
+ '''in case if path of template and xml path are initialized-> enable buttons for next step
+ '''
+ if self.jinjaPath is not None and self.xmlPath is not None:
+ pub.sendMessage('HIDE_LEFT_PANEL.update')
+ self.bttEdit.Enable()
+ self.bttCreateTemplate.Enable()
+ self.bttLoad.Disable()
+ self.bttLoadXml.Disable()
+ self.extendEdit = True
+
+ def onLoadXml(self, evt=None):
+ dlg = wx.FileDialog(self,
+ "Select xml metadata file",
+ self.mdDestination,
+ "",
+ "*.xml",
+ wx.OPEN)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ self.xmlPath = dlg.GetPath()
+ tx = self.statusBar.GetStatusText()
+ self.statusBar.SetStatusText(tx + ' Selected XML: ' + self.xmlPath)
+ self.onChangeXmlorTemplate()
+ dlg.Destroy()
+
+ def onSaveTemplate(self, evt=None):
+ self.xmlPath=self.GetParent().xmlPath
+
+ dlg = wx.FileDialog(self,
+ "Select output file",
+ self.mdDestination,
+ "",
+ "*.xml",
+ wx.SAVE)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ pub.sendMessage('EXPORT_TEMPLATE.create',
+ outPath=dlg.GetDirectory(),
+ outFileName=dlg.GetFilename())
+
+ def OnLoadTemplate(self, evt):
+ dlg = wx.FileDialog(self,
+ "Select template of ISO profile",
+ self.mdDestination,
+ "",
+ "*.xml",
+ wx.OPEN)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ self.jinjaPath = dlg.GetPath()
+ tx = self.statusBar.GetStatusText()
+ self.statusBar.SetStatusText(tx + ' Selected template: ' + self.jinjaPath)
+ self.onChangeXmlorTemplate()
+
+ dlg.Destroy()
+
+ def onSaveXML(self, evt=None):
+ self.xmlPath=self.GetParent().xmlPath
+ self.XMLhead, self.XMLtail = os.path.split(self.xmlPath)
+ if not self.batch: # if normal saving with user-task-dialog
+
+ dlg = wx.FileDialog(self,
+ message="Set output file",
+ defaultDir=self.mdDestination,
+ defaultFile=self.XMLtail,
+ wildcard="*.xml",
+ style=wx.SAVE | wx.FD_OVERWRITE_PROMPT)
+
+ if dlg.ShowModal() == wx.ID_OK:
+ pub.sendMessage('EXPORT_XML.create', outPath=dlg.GetDirectory(), outFileName=dlg.GetFilename())
+ if self.bttsave.GetLabelText() == 'next':
+ pub.sendMessage('EDIT_MAP_METADATA.create', multipleEditing=True)
+
+ else:
+ if self.bttsave.GetLabelText() == 'next':
+ ask = mdutil.yesNo(self, 'File is not saved. Do you want to save it? ', 'Save dialog')
+ if ask:
+ self.onSaveXML()
+ pub.sendMessage('EDIT_MAP_METADATA.create', multipleEditing=True)
+
+ else:
+ GMessage('File not save.')
+ dlg.Destroy()
+
+ else:
+ pub.sendMessage('EXPORT_XML.create', outPath=None, outFileName=None)
+ pub.sendMessage('EDIT_MAP_METADATA.create', multipleEditing=True)
+
+ def _layout(self):
+ self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
+ self.SetSizer(self.mainsizer)
+ self.mainsizer.Add(self.toolbar)
+
+#----------------------------------------------------------------------
+if __name__ == "__main__":
+ app = wx.App(False)
+ frame = MdMainFrame()
+ app.MainLoop()
Deleted: grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata.html
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata.html 2014-08-13 15:54:00 UTC (rev 61594)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata.html 2014-08-13 20:15:41 UTC (rev 61595)
@@ -1,5 +0,0 @@
-<h2>DESCRIPTION</h2>
-Metadata editor according to EN ISO 19115 and EN ISO 19119
-<h2>AUTHOR</h2>
-
-Matej Krejci, Czech Technical University in Prague, Czech Republic
Deleted: grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata.py 2014-08-13 15:54:00 UTC (rev 61594)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/g.gui.metadata.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -1,1155 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8
-"""
- at module g.gui.metadata
- at brief GUI components of metadata editor
-
-Classes:
- - g.gui.metadata::MdMainFrame
- - g.gui.metadata::MdDataCatalog
- - g.gui.metadata::NotebookRight
- - g.gui.metadata::MDHelp
- - g.gui.metadata::TreeBrowser
- - g.gui.metadata::MdValidator
- - g.gui.metadata::MdEditConfigPanel
- - g.gui.metadata::MdToolbar
-
-(C) 2014 by 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.
-
- at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
-"""
-
-import wx
-from wx.lib.buttons import ThemedGenBitmapTextButton as BitmapBtnTxt
-from wx import SplitterWindow, EVT_BUTTON
-from wx.lib.pubsub import setupkwargs, pub
-from editor import MdMainEditor
-
-import glob
-import os
-import sys
-import mdgrass
-import mdutil
-from lxml import etree
-
-import grass.script as grass
-import grass.script.setup as gsetup
-from lmgr import datacatalog
-from core.gcmd import RunCommand, GError, GMessage
-
-#===============================================================================
-# MAIN FRAME
-#===============================================================================
-
-
-class MdMainFrame(wx.Frame):
-
- '''Main frame of metadata editor
- '''
-
- def __init__(self, jinjaPath=None, xmlPath=None, init=False):
- '''
- @param jinjaPath: path to jinja template
- @param xmlPath: path to xml with will be read by editor
- @var first,firstAfterChoice,second,secondAfterChoice,secondMultiEdit: initMultipleEditor() and onInitEditor() handler
- @var self. initMultipleEditor() and onInitEditor() handler
- @var self.templateEditor: true= Editor is in mode 'Template creator(widgets with chkbox)'
- @var nameTMPtemplate: in case if 'template editor is on' this var holds name oof temporaly jinja template
- @var batch: if true multiple editing metadata of maps is ON
- '''
- wx.Frame.__init__(self, None, title="Metadata Editor", size=(650, 500))
- self.initDefaultPathStorageMetadata()
-
- self.jinjaPath = jinjaPath
- self.xmlPath = xmlPath
- self.first = True
- self.firstAfterChoice = False
- self.second = False
- self.secondAfterChoice = False
- self.secondMultiEdit = False
-
- self.templateEditor = False
- self.sb = self.CreateStatusBar()
-
- self.cres = 0 # resizeFrame
- self.nameTMPteplate = None
- self.batch = False
-
- self.onInitEditor()
-
- pub.subscribe(self.initNewMD, 'NEW_MD.create')
- pub.subscribe(self.onEditingMode, 'EDITING_MODE.update')
- pub.subscribe(self.setStatusbarText, 'STATUS_BAR_TEXT.update')
- pub.subscribe(self.onExportTemplate, 'EXPORT_TEMPLATE.create')
- pub.subscribe(self.onExportXML, 'EXPORT_XML.create')
- pub.subscribe(self.onEditMapMetadata, 'EDIT_MAP_METADATA.create')
- pub.subscribe(self.onInitEditor, 'INIT_EDITOR.create')
- pub.subscribe(self.onTemplateEditor, 'TEMPLATE_EDITOR_STATUS.update')
- pub.subscribe(self.onHideLeftPanel, 'HIDE_LEFT_PANEL.update')
- pub.subscribe(self.onRefreshTreeBrowser, 'REFRESH_TREE_BROWSER.update')
- pub.subscribe(self.onChangeEditMapProfile, 'ISO_PROFILE.update')
- pub.subscribe(self.onUpdateGrassMetadata, 'GRASS_METADATA.update')
- pub.subscribe(self.setMdDestionation, 'MD_DESTINATION.update')
- pub.subscribe(self.onSetJaX, 'SET_JINJA_AND_XML.update')
-
- def onSetJaX(self, jinja, xml):
- '''Set template ad xml paths
- '''
- self.jinjaPath = jinja
- self.xmlPath = xml
-
- def setMdDestionation(self, value):
- '''Set md
- '''
- self.mdDestination = value
-
- def initDefaultPathStorageMetadata(self):
- '''set working folder
- '''
- self.mdDestination = os.path.join(mdutil.pathToMapset(), 'metadata')
- if not os.path.exists(self.mdDestination):
- os.makedirs(self.mdDestination)
-
- def onUpdateGrassMetadata(self):
- '''Update r.support and v.support
- '''
- md = self.editor.createNewMD()
- self.mdCreator.updateGrassMd(md)
- GMessage('Grass metadata has been updated')
-
- def onChangeEditMapProfile(self):
- '''Update vars
- '''
- self.templateChoice = self.configPanelLeft.comboBoxProfile.GetValue()
- self.ntbRight.profile = self.templateChoice
-
- def onExportTemplate(self, outPath, outFileName):
- '''Export defined(pre-filled) template
- '''
- self.editor.exportTemplate(self.jinjaPath,
- outPath=outPath,
- xmlOutName=outFileName)
-
- def onExportXML(self, outPath, outFileName):
- '''Save metadta xml file
- '''
- if outPath is None and outFileName is None:
- XMLhead, XMLtail = os.path.split(self.xmlPath)
- self.editor.exportToXml(self.jinjaPath,
- outPath=XMLhead,
- xmlOutName=XMLtail,
- msg=False)
- else:
- self.editor.exportToXml(self.jinjaPath,
- outPath=outPath,
- xmlOutName=outFileName,
- msg=True)
-
- def onRefreshTreeBrowser(self):
- '''Update changes from editor in tree browser
- '''
- path = os.path.dirname(os.path.realpath(__file__))
- name = 'refreshTreeBrowser.xml'
- self.editor.exportToXml(self.jinjaPath,
- outPath=path,
- xmlOutName=name,
- msg=False)
-
- pathName = os.path.join(path, name)
- self.ntbRight.refreshXmlBrowser(pathName)
- os.remove(pathName)
-
- def setStatusbarText(self, text):
- '''Set status text
- '''
- self.sb.SetStatusText(text)
-
- def onTemplateEditor(self, value, template=None):
- '''Update local var
- '''
- self.templateEditor = value
- if template == None:
- self.nameTMPteplate = 'TMPtemplate'
- if template == False:
- self.nameTMPteplate = None
-
- def initNewMD(self):
- '''Init new md OWSLib object
- '''
- self.editor.createNewMD()
- self.ntbRight.md = self.editor.md
-
- def resizeFrame(self, x1=1, y1=0):
- '''Some widgets need refresh frame for proper working
- '''
- self.cres += 1
- if (self.cres % 2 == 0) and x1 == 1 and y1 == 0:
- x1 = -1
- x, y = self.GetSize()
- self.SetSize((x + x1, y + y1))
-
- def onHideLeftPanel(self):
- '''in editing mode is config panel hidden
- '''
- self.toolbar.bttNew.Enable()
- self.Hsizer.Remove(self.leftPanel)
- self.Hsizer.Layout()
- self.leftPanel.SetSize((1, 1))
-
- def onEditingMode(self, editStatus):
- self.resizeFrame()
- self.Layout()
-
- if editStatus:
- self.MdDataCatalogPanelLeft.Show()
- self.toolbar.bttLoad.Disable()
- self.toolbar.bttLoadXml.Disable()
- else:
- self.MdDataCatalogPanelLeft.Hide()
- self.toolbar.bttEdit.Disable()
- self.toolbar.bttCreateTemplate.Disable()
- self.toolbar.bttLoad.Enable()
- self.toolbar.bttLoadXml.Enable()
- self.sb.SetStatusText('')
- self.MdDataCatalogPanelLeft.UnselectAll()
-
- def onEditMapMetadata(self, multipleEditing=False):
- '''Initialize editor by selection of grass map in data catalog
- @param multipleEditing: if user select more than one map mutlipleEditing=True
- @param numOfMap: hold information about number of selected maps for editing
- @param ListOfMapTypeDict: list of dict sttored names of selected maps in dict. dict['cell/vector']=nameofmaps
- '''
- if not multipleEditing:
- self.ListOfMapTypeDict = self.MdDataCatalogPanelLeft.ListOfMapTypeDict
-
- self.templateChoice = self.configPanelLeft.comboBoxProfile.GetValue()
- self.numOfMap = len(self.ListOfMapTypeDict)
-
- if self.numOfMap == 0 and multipleEditing is False:
- GMessage('Select map in data catalog...')
- return
-
- # if editing just one map
- if self.numOfMap == 1 and multipleEditing is False:
- self.mdCreator = mdgrass.GrassMD(self.ListOfMapTypeDict[-1][self.ListOfMapTypeDict[-1].keys()[0]],
- self.ListOfMapTypeDict[-1].keys()[0])
- if self.templateChoice == 'INSPIRE':
- self.mdCreator.createGrassInspireISO()
- self.jinjaPath = self.mdCreator.templatePathAbs
- self.xmlPath = self.mdCreator.saveXML(self.mdDestination, self.nameTMPteplate, self)
- self.onInitEditor()
-
- elif self.templateChoice == 'GRASS BASIC':
- self.mdCreator.createGrassBasicISO()
- self.jinjaPath = self.mdCreator.templatePathAbs
- self.xmlPath = self.mdCreator.saveXML(self.mdDestination, self.nameTMPteplate, self)
- self.onInitEditor()
-
- # if editing multiple maps or just one but with loading own custom template
- if self.templateChoice == 'Load Custom' and self.numOfMap != 0:
- # load template. IF for just one map ELSE for multiple editing
- if multipleEditing is False:
- dlg = wx.FileDialog(self, "Select template", os.getcwd(), "", "*.xml", wx.OPEN)
- if dlg.ShowModal() == wx.ID_OK:
- self.mdCreator = mdgrass.GrassMD(self.ListOfMapTypeDict[-1][self.ListOfMapTypeDict[-1].keys()[0]],
- self.ListOfMapTypeDict[-1].keys()[0])
- self.mdCreator.createGrassInspireISO()
- self.jinjaPath = dlg.GetPath()
- self.xmlPath = self.mdCreator.saveXML(self.mdDestination, self.nameTMPteplate, self)
- # if multiple map are selected
- if self.numOfMap > 1:
- self.toolbar.xmlPath = self.xmlPath
- self.toolbar.jinjaPath = self.jinjaPath
- self.batch = True
- self.ListOfMapTypeDict.pop()
- self.initMultipleEditor()
- else:
- self.ListOfMapTypeDict.pop()
- self.onInitEditor()
- else: # do nothing
- return False
- else:
- self.mdCreator = mdgrass.GrassMD(self.ListOfMapTypeDict[-1][self.ListOfMapTypeDict[-1].keys()[0]],
- self.ListOfMapTypeDict[-1].keys()[0])
- self.mdCreator.createGrassInspireISO()
- self.xmlPath = self.mdCreator.saveXML(self.mdDestination, self.nameTMPteplate, self)
- self.toolbar.xmlPath = self.xmlPath
- self.toolbar.jinjaPath = self.jinjaPath
- self.ListOfMapTypeDict
- self.initMultipleEditor()
- self.ListOfMapTypeDict.pop()
-
- if not multipleEditing:
- self.onHideLeftPanel()
-
- if self.numOfMap == 0 and multipleEditing is True:
- multipleEditing = False
- self.toolbar.onNewSession(None)
- GMessage('All selected maps are edited')
- self.secondMultiEdit = True
-
- if self.batch and multipleEditing:
- XMLhead, XMLtail = os.path.split(self.xmlPath)
- self.batch = mdutil.yesNo(self, 'Do you want to save metadata of : %s without editing ? ' % XMLtail, 'Multiple editing')
-
- if self.batch:
- self.toolbar.batch = True
- self.toolbar.onSaveXML()
- return True
-
- def initMultipleEditor(self):
- '''initialize multiple editing mode
- '''
- if self.firstAfterChoice and not self.secondMultiEdit:
- self.splitter = SplitterWindow(self, style=wx.SP_3D |
- wx.SP_LIVE_UPDATE | wx.SP_BORDER)
- self.Hsizer.Add(self.splitter, proportion=1, flag=wx.EXPAND)
-
- self.firstAfterChoice = False
- self.secondAfterChoice = True
- self.toolbar.bttsave.SetLabel('next')
- self.toolbar.hideMultipleEdit()
- self.mainSizer.Layout()
- self.editor = MdMainEditor(self.splitter,
- self.jinjaPath,
- self.xmlPath,
- self.templateEditor)
- self.ntbRight = NotebookRight(self.splitter, self.xmlPath)
- self.splitter.SplitVertically(self.editor, self.ntbRight, sashPosition=0.65)
- self.splitter.SetSashGravity(0.65)
- self.resizeFrame()
- self.Show()
-
- elif self.secondAfterChoice or self.secondMultiEdit:
- if self.secondMultiEdit:
- self.toolbar.bttsave.SetLabel('next')
- self.toolbar.hideMultipleEdit()
- self.second = False
- self.secondAfterChoice = True
- self.onInitEditor()
-
- def onInitEditor(self,):
- '''Initialize editor
- @var first: True= First initialize main frame
- @var firstAfterChoice: True=Init editor editor after set configuration and click onEdit in toolbar
- @var second: init editor after first initialize
- @var secondAfterChoice: init edito onemore time
- '''
- if self.first:
- self.first = False
- self.firstAfterChoice = True
- self.toolbar = MdToolbar(self,
- self.jinjaPath,
- self.xmlPath,
- self.sb,
- self.mdDestination)
-
- self.leftPanel = wx.Panel(self, id=wx.ID_ANY)
- self.configPanelLeft = MdEditConfigPanel(self.leftPanel)
- self.MdDataCatalogPanelLeft = MdDataCatalog(self.leftPanel)
-
- self._layout()
- self.Show()
-
- elif self.firstAfterChoice:
- self.splitter = SplitterWindow(self, style=wx.SP_3D | wx.SP_LIVE_UPDATE | wx.SP_BORDER)
- self.secondMultiEdit = True
- self.firstAfterChoice = False
- self.second = True
-
- self.editor = MdMainEditor(parent=self.splitter,
- templatePath=self.jinjaPath,
- xmlMdPath=self.xmlPath,
- templateEditor=self.templateEditor)
-
- self.ntbRight = NotebookRight(self.splitter, self.xmlPath)
-
- self.splitter.SplitVertically(self.editor, self.ntbRight, sashPosition=0.65)
- self.splitter.SetSashGravity(0.65)
- self.Hsizer.Add(self.splitter, proportion=1, flag=wx.EXPAND)
- self.splitter.SizeWindows()
- self.resizeFrame()
- self.Show()
-
- elif self.second: # if next initializing of editor
- self.second = False
- self.secondAfterChoice = True
- self.splitter.Hide()
- self.toolbar.bttNew.Disable()
- self.toolbar.bttsave.Disable()
-
- self.Hsizer.Insert(0, self.leftPanel, proportion=1, flag=wx.EXPAND)
- self.resizeFrame()
-
- elif self.secondAfterChoice:
- self.secondAfterChoice = False
- self.second = True
- self.splitter.Show()
- self.toolbar.bttNew.Enable()
- self.toolbar.bttsave.Enable()
-
- ntbRightBCK = self.ntbRight
- self.ntbRight = NotebookRight(self.splitter, self.xmlPath)
- self.splitter.ReplaceWindow(ntbRightBCK, self.ntbRight)
-
- editorTMP = self.editor
- self.editor = MdMainEditor(parent=self.splitter,
- templatePath=self.jinjaPath,
- xmlMdPath=self.xmlPath,
- templateEditor=self.templateEditor)
-
- self.splitter.ReplaceWindow(editorTMP, self.editor)
- ntbRightBCK.Destroy()
- editorTMP.Destroy()
- self.resizeFrame()
- self.Show()
- self.splitter.SetSashGravity(0.35)
- else:
- GMessage('Select map in data catalog...')
-
- self.toolbar.xmlPath = self.xmlPath
- self.toolbar.jinjaPath = self.jinjaPath
-
- def _layout(self):
-
- self.mainSizer = wx.BoxSizer(wx.VERTICAL)
- self.SetSizer(self.mainSizer)
-
- self.mainSizer.Add(self.toolbar)
- self.mainSizer.Add(wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL, size=(10000, 5)))
- self.mainSizer.AddSpacer(5, 5, 1, wx.EXPAND)
-
- self.leftPanelSizer = wx.BoxSizer(wx.VERTICAL)
- self.leftPanel.SetSizer(self.leftPanelSizer)
- self.leftPanelSizer.Add(self.configPanelLeft, proportion=0, flag=wx.EXPAND)
- self.leftPanelSizer.AddSpacer(5, 5, 1, wx.EXPAND)
- self.leftPanelSizer.Add(self.MdDataCatalogPanelLeft, proportion=1, flag=wx.EXPAND)
-
- self.Hsizer = wx.BoxSizer(wx.HORIZONTAL)
- self.mainSizer.Add(self.Hsizer, proportion=1, flag=wx.EXPAND)
-
- self.Hsizer.Add(self.leftPanel, proportion=1, flag=wx.EXPAND)
-
- self.resizeFrame(300, 0)
- self.Layout()
-#===============================================================================
-# DATA CATALOG
-#===============================================================================
-
-
-class MdDataCatalog(datacatalog.LocationMapTree):
-
- '''Data catalog for selecting GRASS maps for editing
- '''
-
- def __init__(self, parent):
- """Test Tree constructor."""
- super(MdDataCatalog, self).__init__(parent=parent,
- style=wx.TR_MULTIPLE | wx.TR_HIDE_ROOT | wx.TR_HAS_BUTTONS |
- wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_COLUMN_LINES)
- self.InitTreeItems()
- self.map = None
- self.mapType = None
-
- def InitTreeItems(self):
- """Add locations and layers to the tree."""
- gisenv = grass.gisenv()
- location = gisenv['LOCATION_NAME']
- self.mapset = gisenv['MAPSET']
-
- self._initTreeItems(locations=[location], mapsets=[self.mapset])
- self.ExpandAll()
- self.Bind(wx.EVT_TREE_SEL_CHANGED, self.onChanged)
- self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.onChanged)
-
- def onChanged(self, evt=None):
- '''
- @var ListOfMapTypeDict: list of dic with maps and map-type values
- @var MapTypeDict: keys= type of map(cell/vector), value=<map name>
- '''
- self.ListOfMapTypeDict = list()
- maps = list()
- if self.GetChildrenCount(evt.Item) == 0: # is selected map
- for item in self.GetSelections():
- MapTypeDict = {}
- maps.append(self.GetItemText(item))
- map = self.GetItemText(item) + '@' + self.mapset
- mapType = self.GetItemParent(item)
- mapType = self.GetItemText(mapType)
-
- if mapType == 'vect':
- mapType = 'vector'
- elif mapType == 'rast':
- mapType = 'cell'
- MapTypeDict[mapType] = map
-
- self.ListOfMapTypeDict.append(MapTypeDict)
- pub.sendMessage('bttEdit.enable')
- pub.sendMessage('bttCreateTemplate.enable')
-
- else:
- self.Unselect()
- GMessage('Please select map.')
-
- if len(maps) == 0:
- pub.sendMessage('bttEdit.disable')
- pub.sendMessage('bttCreateTemplate.disable')
- str1 = ''
-
- for map in maps:
- str1 += map + ' '
-
- if len(maps) > 1:
- pub.sendMessage('SET_PROFILE.update', profile='Load Custom')
-
- pub.sendMessage('comboBoxProfile.disable')
- pub.sendMessage('bttCreateTemplate.disable')
- else:
- pub.sendMessage('comboBoxProfile.enable')
- pub.sendMessage('bttCreateTemplate.enable')
-
- pub.sendMessage('STATUS_BAR_TEXT.update', text=str1)
-
-#===============================================================================
-# NOTEBOOK ON THE RIGHT SIDE-xml browser+validator
-#===============================================================================
-
-
-class NotebookRight(wx.Notebook):
-
- '''Include pages with xml tree browser and validator of metadata
- '''
-
- def __init__(self, parent, path):
-
- wx.Notebook.__init__(self, parent=parent, id=wx.ID_ANY)
- # first panel
- self.notebookValidator = wx.Panel(self, wx.ID_ANY)
- self.validator = MdValidator(self.notebookValidator)
- self.xmlPath = path
- self.profile = None
- self.buttValidate = wx.Button(self.notebookValidator,
- id=wx.ID_ANY,
- size=(70, 50),
- label='validate')
-
- self.notebook_panel1 = wx.Panel(self, wx.ID_ANY)
- self.tree = TreeBrowser(self.notebook_panel1, self.xmlPath)
- self.buttRefresh = wx.Button(
- self.notebook_panel1,
- id=wx.ID_ANY,
- size=(70, 50),
- label='refresh')
-
- self.AddPage(self.notebookValidator, "Validator")
- self.AddPage(self.notebook_panel1, "Tree browser")
- # self.AddPage(self.notebook_panel2, "Help")
-
- self.buttValidate.Bind(wx.EVT_BUTTON, self.validate)
- self.buttRefresh.Bind(wx.EVT_BUTTON, self.onRefreshXmlBrowser)
- self._layout()
-
- def onActive(self):
- pass
-
- def onRefreshXmlBrowser(self, evt=None):
- pub.sendMessage('REFRESH_TREE_BROWSER.update')
-
- def refreshXmlBrowser(self, path):
- treeBCK = self.tree
- self.tree = TreeBrowser(self.notebook_panel1, path)
- self.panelSizer1.Replace(treeBCK, self.tree)
- # self.panelSizer1.Add(self.tree, flag=wx.EXPAND, proportion=1)
- self.panelSizer1.Layout()
- treeBCK.Destroy()
-
- def validate(self, evt):
- self.md = None
- pub.sendMessage('NEW_MD.create')
- pub.sendMessage('ISO_PROFILE.update')
- self.validator.validate(self.md, self.profile)
-
- def _layout(self):
- panelSizer0 = wx.BoxSizer(wx.VERTICAL)
- self.notebookValidator.SetSizer(panelSizer0)
-
- panelSizer0.Add(self.validator, flag=wx.EXPAND, proportion=1)
- panelSizer0.Add(self.buttValidate)
-
- self.panelSizer1 = wx.BoxSizer(wx.VERTICAL)
- self.notebook_panel1.SetSizer(self.panelSizer1)
- self.panelSizer1.Add(self.tree, flag=wx.EXPAND, proportion=1)
- self.panelSizer1.Add(self.buttRefresh)
-
- panelSizer2 = wx.BoxSizer(wx.VERTICAL)
- # self.notebook_panel2.SetSizer(panelSizer2)
- # panelSizer2.Add(self.notebook_panel2,flag=wx.EXPAND, proportion=1)
-#===============================================================================
-# HELP
-#===============================================================================
-
-
-class MDHelp(wx.Panel):
-
- """
- class MyHtmlPanel inherits wx.Panel and adds a button and HtmlWindow
- """
-
- def __init__(self, parent):
- wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
- self.html1 = wx.html.HtmlWindow(self, id=wx.ID_ANY)
- try:
- self.html1.LoadFile('help/help.html')
- # self.html1.LoadPage('http://inspire-geoportal.ec.europa.eu/EUOSME_GEOPORTAL/userguide/eurlex_en.htm')
- except:
- pass
-
- self.mainSizer = wx.BoxSizer(wx.VERTICAL)
- self.SetSizer(self.mainSizer)
- self.mainSizer.Add(self.html1, proportion=1, flag=wx.EXPAND)
-#===============================================================================
-# TREE EDITOR
-#===============================================================================
-
-
-class TreeBrowser(wx.TreeCtrl):
-
- '''Filling text tree by xml file.
- @note: to enable editing mode of init xml uncoment blocks below
- '''
-
- def __init__(self, parent, xmlPath=False, xmlEtree=False):
- wx.TreeCtrl.__init__(self, parent=parent, id=wx.ID_ANY,
- style=wx.TR_HAS_BUTTONS | wx.TR_FULL_ROW_HIGHLIGHT)
- tree = self
- if xmlPath:
- xml = etree.parse(xmlPath)
- self.xml = xml.getroot()
-
- self.root = tree.AddRoot(self.xml.tag)
- else:
- self.xml = xmlEtree
- self.root = xmlEtree.getroot()
-
- root = self.fillTree()
- self.Expand(root)
-
- #=======================================================================
- # self.Bind(wx.EVT_CLOSE, self.OnClose)
- # self.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEdit)
- #=======================================================================
- self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.OnRClickAllChildren)
-
- def fillTree(self):
- root = self.root
- xml = self.xml
- tree = self
-
- def add(parent, elem):
- for e in elem:
- if str(e).find("<!--") != -1: # skip comments
- continue
- tag = etree.QName(e)
- item = tree.AppendItem(parent, tag.localname, data=None)
- if self.GetChildrenCount(item) == 0:
- self.SetItemBackgroundColour(item, (242, 242, 242))
- if e.text:
- text = e.text.strip()
- else:
- text = e.text
- if text:
- val = tree.AppendItem(item, text)
- tree.SetPyData(val, e)
-
- add(item, e)
-
- add(root, xml)
- return root
-
- #=========================================================================
- # def OnEdit(self, evt):
- # elm = self.GetPyData(evt.Item)
- #
- # print evt.Label
- # if elm is not None:
- # elm.text = evt.Label
- # self.xml.write(self.fpath, encoding="UTF-8", xml_declaration=True)
- # self.validate()
- #=========================================================================
-
- #=========================================================================
- # def OnClose(self, evt):
- # self.Destroy()
- #=========================================================================
-
- def OnRClickAllChildren(self, evt):
- if not self.IsExpanded(evt.Item):
- self.ExpandAllChildren(evt.Item)
- else:
- self.CollapseAllChildren(evt.Item)
-
-#===============================================================================
-# INSPIRE VALIDATOR PANEL
-#===============================================================================
-
-
-class MdValidator(wx.Panel):
-
- '''wx panel of notebook which support validating two natively implemented profiles
- '''
-
- def __init__(self, parent):
- wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
- self.text = wx.TextCtrl(parent, id=wx.ID_ANY, size=(0, 55),
- style=wx.VSCROLL |
- wx.TE_MULTILINE | wx.TE_NO_VSCROLL |
- wx.TAB_TRAVERSAL | wx.RAISED_BORDER | wx.HSCROLL)
- self._layout()
-
- def _layout(self):
- self.mainSizer = wx.BoxSizer(wx.VERTICAL)
- self.SetSizer(self.mainSizer)
- self.mainSizer.Add(self.text, proportion=1, flag=wx.EXPAND)
-
- def validate(self, md, profile):
- '''For externaly load xml file is by default inspire validator
- '''
- if profile == 'INSPIRE' or profile == 'Load Custom':
- result = mdutil.isnpireValidator(md)
- str1 = 'INSPIRE VALIDATOR\n'
-
- if profile == 'GRASS BASIC':
- result = mdutil.grassProfileValidator(md)
- str1 = 'GRASS BASIC PROFILE VALIDATOR\n'
-
- str1 += 'Status of validation: ' + result["status"] + '\n'
- str1 += 'Numbers of errors: ' + result["num_of_errors"] + '\n'
-
- if result["status"] != 'succeded':
- str1 += 'Errors:\n'
- for item in result["errors"]:
- str1 += '\t' + str(item) + '\n'
-
- self.text.SetValue(str1)
-
-#===============================================================================
-# CONFIGURATION PANEL ON THE LEFT SIDE
-#===============================================================================
-
-
-class MdEditConfigPanel(wx.Panel):
-
- '''Configuration pane for selection editing mode.
- @var mapGrassEdit: True = editing metadata of GRASS maps, false= editing externally loaded xml and template
- '''
-
- def __init__(self, parent):
- wx.Panel.__init__(self, parent, id=wx.ID_ANY)
- self.SetMinSize((240, -1))
- self.mapGrassEdit = True
-
- self.rbGrass = wx.RadioButton(self, id=wx.ID_ANY, label='Metadata map editor', style=wx.RB_GROUP)
- self.rbExternal = wx.RadioButton(self, id=wx.ID_ANY, label='Metadata external editor')
-
- self.comboBoxProfile = wx.ComboBox(self, choices=['INSPIRE', 'GRASS BASIC', 'Load Custom'])
- pub.subscribe(self.onComboboxDisable, "comboBoxProfile.disable")
- pub.subscribe(self.onComboboxEnable, "comboBoxProfile.enable")
- pub.subscribe(self.onSetProfile, "SET_PROFILE.update")
- self.comboBoxProfile.SetStringSelection('GRASS BASIC')
-
- self.Bind(wx.EVT_RADIOBUTTON, self.onSetRadioType, id=self.rbGrass.GetId())
- self.Bind(wx.EVT_RADIOBUTTON, self.onSetRadioType, id=self.rbExternal.GetId())
- self.comboBoxProfile.Bind(wx.EVT_COMBOBOX, self.onChangeComboBoxProfile)
-
- self._layout()
-
- def onChangeComboBoxProfile(self, evt):
- pass
-
- def onComboboxDisable(self):
- self.comboBoxProfile.Disable()
-
- def onComboboxEnable(self):
- self.comboBoxProfile.Enable()
-
- def onSetProfile(self, profile):
- self.comboBoxProfile.SetStringSelection(profile)
-
- def SetVal(self, event):
- state1 = str()
- state2 = str(self.rb2.GetValue())
-
- self.statusbar.SetStatusText(state1, 0)
- self.statusbar.SetStatusText(state2, 1)
-
- def onSetRadioType(self, evt=None):
- self.mapGrassEdit = self.rbGrass.GetValue()
- if self.mapGrassEdit == False:
- self.comboBoxProfile.Hide()
- else:
- self.comboBoxProfile.Show()
- pub.sendMessage('EDITING_MODE.update', editStatus=self.mapGrassEdit)
-
- def _layout(self):
- self.mainsizer = wx.BoxSizer(wx.VERTICAL)
- self.SetSizer(self.mainsizer)
- self.mainsizer.Add(self.rbGrass)
- self.mainsizer.Add(self.rbExternal)
- self.mainsizer.Add(self.comboBoxProfile)
-#===============================================================================
-# TOOLBAR
-#===============================================================================
-
-
-class MdToolbar(wx.Panel):
-
- '''Main toolbar of editor
- '''
-
- def __init__(self, parent, jinjaPath, xmlPath, sb, mdDestionation):
- wx.Panel.__init__(self, parent, id=wx.ID_ANY)
- self.mdDestination = mdDestionation
- self.batch = False
- self.jinjaPath = jinjaPath
- self.statusBar = sb
- self.xmlPath = xmlPath
- self.extendEdit = False
- self.toolbar = wx.ToolBar(self, 1, wx.DefaultPosition, (-1, -1))
-
- bitmapSave = wx.Image(
- os.path.join(os.environ['GISBASE'], 'gui', 'icons', 'grass', 'save.png'),
- wx.BITMAP_TYPE_PNG).ConvertToBitmap()
- bitmapNew = wx.Image(
- os.path.join(os.environ['GISBASE'], 'gui', 'icons', 'grass', 'create.png'),
- wx.BITMAP_TYPE_PNG).ConvertToBitmap()
- bitmapLoad = wx.Image(
- os.path.join(os.environ['GISBASE'], 'gui', 'icons', 'grass', 'open.png'),
- wx.BITMAP_TYPE_PNG).ConvertToBitmap()
- bitmaSettings = wx.Image(
- os.path.join(os.environ['GISBASE'], 'gui', 'icons', 'grass', 'settings.png'),
- wx.BITMAP_TYPE_PNG).ConvertToBitmap()
-#-------------------------------------------------------------------- EDIT
- self.toolbar.AddSeparator()
- bitmapEdit = wx.Image(
- os.path.join(os.environ['GISBASE'], 'gui', 'icons', 'grass', 'edit.png'),
- wx.BITMAP_TYPE_PNG).ConvertToBitmap()
- self.bttEdit = BitmapBtnTxt(
- self.toolbar, -1, bitmapEdit, 'edit')
- self.toolbar.AddControl(control=self.bttEdit)
- self.bttEdit.Disable()
-#-------------------------------------------------------------------- NEW SESION
- self.toolbar.AddSeparator()
- self.bttNew = BitmapBtnTxt(self.toolbar, -1, bitmapNew, 'session')
- self.toolbar.AddControl(control=self.bttNew)
- self.bttNew.Disable()
-#-------------------------------------------------------------------------- SAVE
- self.bttsave = BitmapBtnTxt(self.toolbar, -1, bitmapSave, "XML")
- self.bttsave.Disable()
- self.toolbar.AddControl(control=self.bttsave)
- self.toolbar.AddSeparator()
-#----------------------------------------------------------------- OPEN TEMPLATE
- self.bttLoad = BitmapBtnTxt(self.toolbar, -1, bitmapLoad, "template", size=(100, -1))
- self.toolbar.AddControl(control=self.bttLoad)
- self.bttLoad.Disable()
-#---------------------------------------------------------------------- OPEN XML
- self.bttLoadXml = BitmapBtnTxt(self.toolbar, -1, bitmapLoad, "XML")
- self.toolbar.AddControl(control=self.bttLoadXml)
- self.bttLoadXml.Disable()
- self.toolbar.AddSeparator()
-#-------------------------------------------------------------------- NEW TEMPLATE
- self.bttCreateTemplate = BitmapBtnTxt(self.toolbar, -1, bitmapNew, "template", size=(100, -1))
- self.toolbar.AddControl(control=self.bttCreateTemplate)
- self.bttCreateTemplate.Disable()
-#-------------------------------------------------------------------------- SAVE
- self.bttSaveTemplate = BitmapBtnTxt(self.toolbar, -1, bitmapSave, "template", size=(100, -1))
- self.bttSaveTemplate.Disable()
- self.toolbar.AddControl(control=self.bttSaveTemplate)
- self.toolbar.AddSeparator()
-#-------------------------------------------------------------------------- SAVE
- self.bttUpdateGRASS = BitmapBtnTxt(self.toolbar, -1, bitmapSave, "GRASS", size=(100, -1))
- self.bttUpdateGRASS.Disable()
- self.toolbar.AddControl(control=self.bttUpdateGRASS)
- self.toolbar.AddSeparator()
-#-------------------------------------------------------------------------- Config
- self.bttConfig = BitmapBtnTxt(self.toolbar, -1, bitmaSettings, "workdir", size=(100, -1))
- self.toolbar.AddControl(control=self.bttConfig)
- self.toolbar.AddSeparator()
-
- self.toolbar.Realize()
- self._layout()
-
- self.bttLoad.Bind(wx.EVT_BUTTON, self.OnLoadTemplate)
- pub.subscribe(self.onBttSaveEnable, "bttLoad.enable")
- pub.subscribe(self.onBttSaveDisable, "bttLoad.disable")
-
- self.bttsave.Bind(wx.EVT_BUTTON, self.onSaveXML)
- pub.subscribe(self.onBttLoadEnable, "bttSave.enable")
- pub.subscribe(self.onBttLoadDisable, "bttSave.disable")
-
- self.bttLoadXml.Bind(wx.EVT_BUTTON, self.onLoadXml)
- pub.subscribe(self.onBttLoadXmlEnable, "bttLoadXml.enable")
- pub.subscribe(self.onBttLoadXmlDisable, "bttLoadXml.disable")
-
- self.bttNew.Bind(wx.EVT_BUTTON, self.onNewSession)
- pub.subscribe(self.onBttNewEnable, "bttNew.enable")
- pub.subscribe(self.onBttNewDisable, "bttNew.disable")
-
- self.bttEdit.Bind(wx.EVT_BUTTON, self.onEdit)
- pub.subscribe(self.onBtEditEnable, "bttEdit.enable")
- pub.subscribe(self.onBttEditDisable, "bttEdit.disable")
-
- self.bttCreateTemplate.Bind(wx.EVT_BUTTON, self.onCreateTemplate)
- pub.subscribe(self.onBttCreateTemplateEnable, "bttCreateTemplate.enable")
- pub.subscribe(self.onBttCreateTemplateDisable, "bttCreateTemplate.disable")
-
- self.bttSaveTemplate.Bind(wx.EVT_BUTTON, self.onSaveTemplate)
- pub.subscribe(self.onBttSaveTemplateEnable, "bttSaveTemplate.enable")
- pub.subscribe(self.onBttSaveTemplateDisable, "bttSaveTemplate.disable")
-
- self.bttUpdateGRASS.Bind(wx.EVT_BUTTON, self.onUpdateGRASS)
- pub.subscribe(self.onBttUpdateGRASSEnable, "bttSaveTemplate.enable")
- pub.subscribe(self.onBttUpdateGRASSDisable, "bttSaveTemplate.disable")
-
- self.bttConfig.Bind(wx.EVT_BUTTON, self.onSettings)
-
- def onBttSaveDisable(self):
- self.bttSave.Disable()
-
- def onBttSaveEnable(self):
- self.bttSave.Enable()
-
- def onBttLoadDisable(self):
- self.bttLoad.Disable()
-
- def onBttLoadEnable(self):
- self.bttLoad.Enable()
-
- def onBttLoadXmlDisable(self):
- self.bttLoadXml.Disable()
-
- def onBttLoadXmlEnable(self):
- self.bttLoadXml.Enable()
-
- def onBttNewDisable(self):
- self.bttNew.Disable()
-
- def onBttNewEnable(self):
- self.bttNew.Enable()
-
- def onBttEditDisable(self):
- self.bttEdit.Disable()
-
- def onBtEditEnable(self):
- self.bttEdit.Enable()
-
- def onBttCreateTemplateDisable(self):
- self.bttCreateTemplate.Disable()
-
- def onBttCreateTemplateEnable(self):
- self.bttCreateTemplate.Enable()
-
- def onBttSaveTemplateDisable(self):
- self.bttSaveTemplate.Disable()
-
- def onBttSaveTemplateEnable(self):
- self.bttSaveTemplate.Enable()
-
- def onBttUpdateGRASSDisable(self):
- self.bttUpdateGRASS.Disable()
-
- def onBttUpdateGRASSEnable(self):
- self.bttUpdateGRASS.Enable()
-
- def onUpdateGRASS(self, evt):
- pub.sendMessage('GRASS_METADATA.update')
-
- def onSettings(self, evt):
- dlg = wx.DirDialog(self,
- message="Select metadata working directory",
- defaultPath=self.mdDestination,
- style=wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
-
- if dlg.ShowModal() == wx.ID_OK:
- self.mdDestination = dlg.GetPath()
- pub.sendMessage('MD_DESTINATION.update', value=self.mdDestination)
- dlg.Destroy()
-
- GMessage('Metadata destinatnion: %s' % self.mdDestination)
-
- def hideMultipleEdit(self):
- '''Multiple editor is off
- '''
-
- self.bttLoad.Hide()
- self.bttLoadXml.Hide()
- self.bttNew.Hide()
- self.bttEdit.Hide()
- self.bttCreateTemplate.Hide()
- self.bttSaveTemplate.Hide()
- self.bttUpdateGRASS.Hide()
-
- def showMultipleEdit(self):
- '''Multiple editor is on
- '''
- self.bttLoad.Show()
- self.bttLoadXml.Show()
- self.bttNew.Show()
- self.bttEdit.Show()
- self.bttCreateTemplate.Show()
- self.bttSaveTemplate.Show()
- self.bttUpdateGRASS.Show()
-
- def onCreateTemplate(self, evt):
- pub.sendMessage('TEMPLATE_EDITOR_STATUS.update', value=True)
- self.onEdit(evt=None)
- self.bttCreateTemplate.Disable()
- self.bttSaveTemplate.Enable()
-
- def onEdit(self, evt=None):
- '''
- @var : extendEdit if xml and jinja is loaded from file
- '''
- if self.extendEdit:
- pub.sendMessage('SET_JINJA_AND_XML.update', jinja=self.jinjaPath, xml=self.xmlPath)
- self.bttUpdateGRASS.Disable()
-
- if self.GetParent().configPanelLeft.rbGrass.GetValue():
- ok = self.GetParent().onEditMapMetadata()
- if not ok:
- return
- else:
- pub.sendMessage('INIT_EDITOR.create')
-
- self.bttCreateTemplate.Disable()
- self.bttEdit.Disable()
- self.bttsave.Enable()
- if not self.extendEdit:
- self.bttUpdateGRASS.Enable()
-
- try: # if multiediting mode ON
- if self.GetParent().numOfMap > 1:
- XMLhead, XMLtail = os.path.split(self.xmlPath)
- self.batch = mdutil.yesNo(self, 'Do you want to save metadata of : %s without editing ? ' % XMLtail, 'Multiple editing')
- if self.batch:
- self.onSaveXML()
- except:
- pass
-
- def onNewSession(self, evt):
- pub.sendMessage('INIT_EDITOR.create')
- pub.sendMessage('TEMPLATE_EDITOR_STATUS.update', value=False, template=False)
- # chck current editing mode(grass or external xml editor)
- if self.GetParent().configPanelLeft.rbGrass is False:
- self.bttLoad.Enable()
- self.bttLoadXml.Enable()
- self.statusBar.SetStatusText('')
- self.bttsave.Disable()
- self.bttUpdateGRASS.Disable()
- self.jinjaPath = None
- self.xmlPath = None
- self.bttsave.SetLabel('XML')
- self.showMultipleEdit()
-
- self.bttSaveTemplate.Disable()
-
- def onChangeXmlorTemplate(self, evt=None):
- '''in case if path of template and xml path are initialized-> enable buttons for next step
- '''
- if self.jinjaPath is not None and self.xmlPath is not None:
- pub.sendMessage('HIDE_LEFT_PANEL.update')
- self.bttEdit.Enable()
- self.bttCreateTemplate.Enable()
- self.bttLoad.Disable()
- self.bttLoadXml.Disable()
- self.extendEdit = True
-
- def onLoadXml(self, evt=None):
- dlg = wx.FileDialog(self,
- "Select xml metadata file",
- self.mdDestination,
- "",
- "*.xml",
- wx.OPEN)
-
- if dlg.ShowModal() == wx.ID_OK:
- self.xmlPath = dlg.GetPath()
- tx = self.statusBar.GetStatusText()
- self.statusBar.SetStatusText(tx + ' Selected XML: ' + self.xmlPath)
- self.onChangeXmlorTemplate()
- dlg.Destroy()
-
- def onSaveTemplate(self, evt=None):
- self.xmlPath=self.GetParent().xmlPath
-
- dlg = wx.FileDialog(self,
- "Select output file",
- self.mdDestination,
- "",
- "*.xml",
- wx.SAVE)
-
- if dlg.ShowModal() == wx.ID_OK:
- pub.sendMessage('EXPORT_TEMPLATE.create',
- outPath=dlg.GetDirectory(),
- outFileName=dlg.GetFilename())
-
- def OnLoadTemplate(self, evt):
- dlg = wx.FileDialog(self,
- "Select template of ISO profile",
- self.mdDestination,
- "",
- "*.xml",
- wx.OPEN)
-
- if dlg.ShowModal() == wx.ID_OK:
- self.jinjaPath = dlg.GetPath()
- tx = self.statusBar.GetStatusText()
- self.statusBar.SetStatusText(tx + ' Selected template: ' + self.jinjaPath)
- self.onChangeXmlorTemplate()
-
- dlg.Destroy()
-
- def onSaveXML(self, evt=None):
- self.xmlPath=self.GetParent().xmlPath
- self.XMLhead, self.XMLtail = os.path.split(self.xmlPath)
- if not self.batch: # if normal saving with user-task-dialog
-
- dlg = wx.FileDialog(self,
- message="Set output file",
- defaultDir=self.mdDestination,
- defaultFile=self.XMLtail,
- wildcard="*.xml",
- style=wx.SAVE | wx.FD_OVERWRITE_PROMPT)
-
- if dlg.ShowModal() == wx.ID_OK:
- pub.sendMessage('EXPORT_XML.create', outPath=dlg.GetDirectory(), outFileName=dlg.GetFilename())
- if self.bttsave.GetLabelText() == 'next':
- pub.sendMessage('EDIT_MAP_METADATA.create', multipleEditing=True)
-
- else:
- if self.bttsave.GetLabelText() == 'next':
- ask = mdutil.yesNo(self, 'File is not saved. Do you want to save it? ', 'Save dialog')
- if ask:
- self.onSaveXML()
- pub.sendMessage('EDIT_MAP_METADATA.create', multipleEditing=True)
-
- else:
- GMessage('File not save.')
- dlg.Destroy()
-
- else:
- pub.sendMessage('EXPORT_XML.create', outPath=None, outFileName=None)
- pub.sendMessage('EDIT_MAP_METADATA.create', multipleEditing=True)
-
- def _layout(self):
- self.mainsizer = wx.BoxSizer(wx.HORIZONTAL)
- self.SetSizer(self.mainsizer)
- self.mainsizer.Add(self.toolbar)
-
-#----------------------------------------------------------------------
-if __name__ == "__main__":
- app = wx.App(False)
- frame = MdMainFrame()
- app.MainLoop()
Deleted: grass-addons/grass7/gui/wxpython/wx.metadata/jinjainfo.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/jinjainfo.py 2014-08-13 15:54:00 UTC (rev 61594)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/jinjainfo.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -1,192 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8
-"""
- at package jinjainfo
- at module g.gui.metadata
- at brief Library for parsing informations from jinja template
-
-Classes:
- - jinjainfo::MdDescription
- - jinjainfo::JinjaTemplateParser
-
-(C) 2014 by 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.
-
- at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
-"""
-from core.gcmd import GError
-from mdutil import findBetween
-
-
-class MdDescription():
-
- '''Object which is initialzed by jinja template in '{# #}'
- '''
-
- def __init__(self, tag=None, object=None, name='', desc=None,
- example=None, type=None, multi=0, inboxmulti=None,
- group=None, inbox=None, multiline=None, validator=None,
- num=None, ref=None, selfInfoString=None):
- '''
- @param tag: OWSLib object which will be replaced by value of object after jinja template system render new file
- @param object: some object in OWSLib is neecesarry to initialize temporaly in gui generator. Others are initialize by configure file
- @param name: label and tooltip name
- @param desc: description/definition of metadata item
- @param example: example of md item (tooltip)
- @param type: data type is neccesary to validet widgets
- @param multi: 0=only one instance of editor::MdItem widget can be, 1= multiple insctances of widgets can be
- @param inboxmulti: 0=static box of items has not button for duplicating self 1=has button
- @param group: this param initialize page in notebook in mani editor
- @param inbox: Every items in block of code in jinja template must have same value of inbox.
- The value of inbox representing label of static box in gui.
- @param multiline: If true- textCtrl widget will be init with multiline control
- @param validator: Not use currently
- @param ref: additional information about reference of metadata item (ISO reference)
- @param selfInfoString: string value representing all these information. (parsed from jinja template)
- @var mdItem: very important parametr which holds instances of widgets(editor::MdItem)
- on every index of list is one instance of widget. In case, if is in static box MdItem with duplicating button:
- index of list is represented by list of these items
- @var statements: hold information about first statement in block
- @var statements1: hold info about secont stetement in block of var: statement
- '''
- self.tag = tag
- self.object = object
- self.name = name
- self.desc = desc
- self.example = example
- self.type = type
- self.multiplicity = multi # multiplicity of MD item
- self.group = group
- self.inbox = inbox
- self.ref = ref
- self.selfInfoString = selfInfoString
-
- self.inboxmulti = inboxmulti
- self.multiline = multiline # type of ctrl text
- self.validator = validator
- # --info from jinja -end
-
- self.statements = None
- self.statements1 = None
- self.mdItem = list()
-
- def addMdItem(self, newMdItem, oldMdItem=None):
- '''care about integrity of var: self.mdItem
- '''
- # if new mditem is from box- need to hold information
- # about it.(list on the same index in self.mdItem)
- if oldMdItem is not None:
- for n, item in enumerate(self.mdItem):
- for i in item:
- if i == oldMdItem:
- self.mdItem[n].append(newMdItem)
- else:
- self.mdItem.append(newMdItem)
-
- def removeMdItem(self, item):
- '''care about integrity of var: self.mdItem
- '''
- try:
- for k, oldListItem in enumerate(self.mdItem):
- for i in oldListItem:
- if i == item:
- self.mdItem[k].remove(item)
- except:
- self.mdItem.remove(item)
-
- def addStatements(self, stat):
- if self.statements is None:
- self.statements = stat
-
- def addStatements1(self, stat):
- if self.statements1 is None:
- self.statements1 = stat
-
-
-class JinjaTemplateParser():
-
- '''Parser of OWSLib tag and init. values of jinjainfo::MdDescription from jinja template.
- '''
-
- def __init__(self, template):
- '''
- @var mdDescription: list of jinjainfo::mdDescription
- @var mdOWSTag: list of tags in jinja templates
- @var mdOWSTagStr: string representing OWSLib tags from template(per line)
- @var mdOWSTagStrList: on each index of list is one line with parsed OWSLib tag
- '''
- self.mdDescription = []
- self.mdOWSTag = []
- self.template = template
-
- self.mdOWSTagStr = ''
- self.mdOWSTagStrList = []
-
- self._readJinjaInfo()
- self._readJinjaTags()
- self._formatMdOWSTagStrToPythonBlocks()
-
- def _readJinjaTags(self):
- '''Parser of OWSLib tag from jinja template to list
- '''
- try:
- with open(self.template, "r") as f:
- for line in f:
-
- # if found start of comments
- if str(line).find("{{") != -1:
- obj = findBetween(line, "{{", "}}")
- self.mdOWSTag.append(obj)
-
- if str(line).find("{%") != -1:
- obj = findBetween(line, "{%", "-%}")
- self.mdOWSTag.append(obj)
-
- except:
- GError('Cannot open jinja template')
- # print "I/O error({0}): {1}".format(e.errno, e.strerror)
-
- 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.decode("utf-8", 'ignore')
- eval(exe_str)
- except:
- GError('Cannot open jinja template')
- # print "I/O error({0}): {1}".format(e.errno, e.strerror)
-
- def _formatMdOWSTagStrToPythonBlocks(self):
- '''Formating of parsed tags to pythonic blocks
- '''
- self.mdOWSTagStr = ""
- tab = 0
- for item in self.mdOWSTag:
- if str(item).find(" endfor ") != -1 or \
- str(item).find(" endif ") != -1:
- tab -= 1
- continue
-
- tabstr = '\t' * tab
- str1 = tabstr + item[1:] + '\n'
- self.mdOWSTagStr += str1
- self.mdOWSTagStrList.append(tabstr + item[1:])
-
- if str(item).find(" for ") != -1 \
- or str(item).find(" if ") != -1:
- tab += 1
Deleted: grass-addons/grass7/gui/wxpython/wx.metadata/mdgrass.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/mdgrass.py 2014-08-13 15:54:00 UTC (rev 61594)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/mdgrass.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -1,523 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8
-"""
- at package mdgrass
- at module v.info.iso, r.info.iso, g.gui.metadata
- at brief Base class for import(r.info,v.info) and export(r/v.support)
- metadata with using OWSLib and jinja template.
-
-Classes:
- - mdgrass::MdDescription
-
-(C) 2014 by 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.
-
- at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
-"""
-from owslib.iso import *
-from jinja2 import Environment, FileSystemLoader
-
-from lxml import etree
-import os
-import sys
-import re
-import StringIO
-import subprocess as sub
-import uuid
-import mdutil # metadata lib
-import getpass # whoami for linux and ms-win
-
-from grass.pygrass.modules.shortcuts import general as g
-from grass.pygrass.gis import Mapset
-from grass.pygrass import raster
-from grass.pygrass.modules import Module
-from grass.script import parse_key_val
-from subprocess import PIPE
-from datetime import date, datetime
-from grass.script import parser
-from grass.script import core as grass
-
-
-class GrassMD():
-
- '''
- @var self.map: name of choosen map by user
- @var self.type: typ of map representation(cell, vector, r3)
- @var md_grass: dict with metadata from r.info v.info except "r.info flag=h"
-
- '''
-
- def __init__(self, map, type):
- self.map = map
- self.type = type
-
- self.isMapExist() # function to check if map exist
- self.md_grass = {}
- self.md_abstract = ''
- self.md_vinfo_h = '' # v.info flag=h" - parse
- self.gisenv_grass = grass.gisenv() # dict with gisenv information
- # postfix of output xml file (variables)
- self.schema_type = '_basic.xml' # currently
- self.dirpath = os.path.dirname(os.path.realpath(__file__))
- # metadata object from OWSLIB ( for define md values)
- self.md = MD_Metadata(md=None)
- self.template = None # path to file with xml templates
-
- if self.type == "cell":
- self.parseRast()
- elif self.type == "vector":
- self.parseVect()
- elif self.type == "r3??":
- # TODO
- self.parseRast3D()
-
- def isMapExist(self):
- '''Check if is the map in working mapset'''
- self.mapset = grass.find_file(self.map, self.type)['mapset']
- if not self.mapset:
- grass.fatal(_("Map <%s> doesn't exist") % self.map)
-
- def parseRast3D(self):
- pass
-
- def parseVect(self):
- '''Read metadata from v.info
- @var self.md_grass dictionary of metadata from v.info
- '''
-
- # parse md from v.info flags=-g -e -t
- vinfo = Module(
- 'v.info',
- self.map,
- flags='get',
- quiet=True,
- stdout_=PIPE)
-
- self.md_grass = parse_key_val(vinfo.outputs.stdout)
-
- # parse md from v.info flag h (history of map in grass)
- rinfo_h = Module(
- 'v.info',
- self.map,
- flags='h',
- quiet=True,
- stdout_=PIPE)
-
- md_h_grass = rinfo_h.outputs.stdout
- buf = StringIO.StringIO(md_h_grass)
- line = buf.readline().splitlines()
- while str(line) != '[]':
- if str(line[0]).strip() != "":
- self.md_vinfo_h += line[0] + '\n'
- line = buf.readline().splitlines()
- buf.close()
-
- # convert grass parsed date format to iso format
- # if date format is diverse from standard, use them
- self._createISODate('source_date')
-
- def _createISODate(self, key):
- '''Function for converting grass-generated date to iso format
- if the format of date is different to grass-generated format - use them and print warning
- '''
- try:
- date = datetime.strptime(self.md_grass[key], '%a %b %d %H:%M:%S %Y')
- self.md_grass['dateofcreation'] = date.strftime('%Y-%m-%d')
- except:
- grass.warning('date of creation: unknown date format')
- self.md_grass['dateofcreation'] = self.md_grass[key]
-
- def parseRast(self):
- '''Read metadata from r.info
- #self.md_grass dictionary of metadata from v.info
- #self.md_abstract string created by merge information from 'description' and 'source'
- '''
- rinfo = Module('r.info',
- self.map,
- flags='gre',
- quiet=True,
- stdout_=PIPE)
-
- self.md_grass = parse_key_val(rinfo.outputs.stdout)
-
- # convert date to iso format
- self._createISODate('date')
-
- # create abstract
- if self.md_grass['description'] != '""':
- self.md_abstract = self.md_grass['description'] + '; '
- if self.md_grass['source1'] != '""':
- self.md_abstract += self.md_grass['source1'] + '; '
- if self.md_grass['source2'] != '""':
- self.md_abstract += self.md_grass['source2'] + '; '
- self.md_abstract += 'Total cells: ' + self.md_grass['cells'] + '; '
- self.md_abstract += 'A range of values: min: ' + \
- self.md_grass['min'] + ' max: ' + self.md_grass['max']
- self.md_abstract.translate(None, """&<>"'""")
-
- def createGrassBasicISO(self, template=None):
- '''Create basic/essential profile based on ISO
- - unknown values are filling by n = '$NULL'
- '''
- try:
- self.md_grass['comments'] = self.md_grass['comments'].replace('\n', '; ')
- except:
- pass
-
- n = '$NULL'
- # jinja templates
- if template is None:
- self.template = os.path.join('templates', 'basicTemplate.xml')
- else:
- self.template = template
-
- # OWSLib md object
- self.md.identification = MD_DataIdentification()
- self.md.dataquality = DQ_DataQuality()
- self.md.distribution = MD_Distribution()
- self.md.identification.extent = EX_Extent()
- self.md.identification.extent.boundingBox = EX_GeographicBoundingBox()
-
- # Metadata on metadata
- val = CI_ResponsibleParty()
- val.organization = n
- val.email = n
- val.role = n
- self.md.contact.append(val)
-
- # Identification/Resource Title
- self.md.identification.title = mdutil.replaceXMLReservedChar(self.md_grass['title'])
- self.md.datestamp = mdutil.replaceXMLReservedChar(date.today().isoformat())
-
- # Identification/Resource Type
- self.md.identification.identtype = 'dataset'
-
- # Identification/Unique Resource Identifier
- self.md.identifier = mdutil.replaceXMLReservedChar(str(uuid.uuid4()))
- self.md.identification.uricode.append(n)
- self.md.identification.uricodespace.append(n)
-
- # Geographic/BB
- self.md.identification.extent.boundingBox.minx = mdutil.replaceXMLReservedChar(self.md_grass['south'])
- self.md.identification.extent.boundingBox.maxx = mdutil.replaceXMLReservedChar(self.md_grass['north'])
- self.md.identification.extent.boundingBox.miny = mdutil.replaceXMLReservedChar(self.md_grass['west'])
- self.md.identification.extent.boundingBox.maxy = mdutil.replaceXMLReservedChar(self.md_grass['east'])
-
- # Conformity/Title
- self.md.dataquality.conformancetitle.append(
- 'GRASS basic metadata profile based on ISO 19115, 19139')
-
- # Conformity/Date:
- self.md.dataquality.conformancedate.append(mdutil.replaceXMLReservedChar(date.today().isoformat()))
- self.md.dataquality.conformancedatetype.append('publication')
-
- # Temporal/Date of creation
- val = CI_Date()
- val.date = self.md_grass['dateofcreation']
- val.type = 'creation'
- self.md.identification.date.append(val)
-
- self.md.identification.uom.append('m') # TODO
-
- # different metadata sources for vector and raster
- if self.type == 'cell':
- # Identification/Resource Abstract
- self.md.identification.abstract = mdutil.replaceXMLReservedChar(self.md_abstract)
- # Geographic/resolution
- self.md.identification.distance.append(mdutil.replaceXMLReservedChar(self.md_grass['nsres'])) # TODO for discuss
-
- # Quality/Lineage
- try:
- self.md.dataquality.lineage = mdutil.replaceXMLReservedChar(self.md_grass['comments']).replace('\n', '\\n')
- except:
- grass.warning('Native metadata *flag=comments* not found, dataquality.lineage filled by $NULL')
- self.md.dataquality.lineage = n
-
- self.md.identification.denominators.append(n)
- # Organisation/Responsible Party:
- val = CI_ResponsibleParty()
- val.organization = n # self.md_grass['creator']
- val.role = n
- val.email = n
- self.md.identification.contact.append(val)
-
- if self.type == 'vector':
-
- # Identification/Resource Abstract
- # TODO not enough sources for crate abstarce
- self.md.identification.abstract = mdutil.replaceXMLReservedChar(self.md_grass['name'])
- self.md.dataquality.lineage = mdutil.replaceXMLReservedChar(self.md_vinfo_h).replace('\n', '\\n')
-
- self.md.identification.denominators.append(self.md_grass['scale'])
- # Organisation/Responsible Party:
- val = CI_ResponsibleParty()
- val.organization = n # mdutil.replaceXMLReservedChar(getpass.getuser())
- val.email = n
- val.role = n
- self.md.identification.contact.append(val)
-
- self.templatePathAbs = os.path.join(self.dirpath, self.template)
-
- def createGrassInspireISO(self, template=None):
- '''Create valid INSPIRE profile and fill it as much as possible by GRASS metadata. Missing values is $NULL
- -create basic md profile and add INSPIRE mandatory attributes
- '''
-
- self.schema_type = '_inspire.xml'
-
- # create basic profile
- self.createGrassBasicISO()
-
- if template is None:
- self.template = os.path.join('templates', 'inspireTemplate.xml')
- else:
- self.template = template
-
- n = '$NULL'
-
- if len(self.md.identification.distance) == 0:
- self.md.identification.distance.append(n) # TODO
- # Classification/Topic Category
- self.md.identification.topiccategory.append(n)
- self.md.identification.resourcelanguage.append(n)
- self.md.languagecode = n
- # Keyword/Keyword
- kw = {}
- kw['keywords'] = []
- kw['keywords'].append(n)
-
- kw['type'] = n
- kw['thesaurus'] = {}
- kw['thesaurus']['date'] = n
- kw['thesaurus']['datetype'] = n
- kw['thesaurus']['title'] = n
- self.md.identification.keywords.append(kw)
-
- # Conformity/Title
- # remove value from basic profile
- self.md.dataquality.conformancetitle.pop()
- self.md.dataquality.conformancetitle.append(
- 'Commission Regulation (EU) No 1089/2010 of 23 November 2010 implementing Directive 2007/2/EC of the European Parliament and of the Council as regards interoperability of spatial data sets and services')
- # Identification/Resource Locator
- val = CI_OnlineResource()
- val.url = n
- self.md.distribution.online.append(val)
-
- # Conformity/Date
- self.md.dataquality.conformancedate.append(n)
- self.md.dataquality.conformancedatetype.append(n)
-
- # Conformity/Degree
- self.md.dataquality.conformancedegree.append('true')
-
- # Constraints/Limitations on public access
- self.md.identification.accessconstraints.append(n)
- self.md.identification.otherconstraints.append(n)
-
- # Constraints/Conditions for access and use-general
- self.md.identification.uselimitation.append(n)
-
- # Temporal/Temporal Extent
- self.md.identification.temporalextent_start = n
- self.md.identification.temporalextent_end = n
-
- self.templatePathAbs = os.path.join(self.dirpath, self.template)
- # print self.templatePathAbs
-
- def readXML(self, xml_file):
- '''create instance of metadata(owslib) from xml file'''
- self.md = MD_Metadata(etree.parse(xml_file))
-
- def saveXML(self, path=None, xml_out_name=None, wxparent=None, overwrite=False):
- ''' Save init. record of OWSLib objects to ISO XML file'''
-
- # if output file name is None, use map name and add postfix
- if xml_out_name is None:
- xml_out_name = self.type + '_' + str(self.map).partition('@')[0] # + self.schema_type
- if not xml_out_name.lower().endswith('.xml'):
- xml_out_name += '.xml'
-
- if not path:
- path = os.path.join(mdutil.pathToMapset(), 'metadata')
- if not os.path.exists(path):
- print os.makedirs(path)
- path = os.path.join(path, xml_out_name)
-
- # generate xml using jinja tempaltes
- env = Environment(loader=FileSystemLoader(self.dirpath))
- env.globals.update(zip=zip)
- template = env.get_template(self.template)
- iso_xml = template.render(md=self.md)
-
- # write xml to flat file
- if wxparent != None:
- if os.path.isfile(path):
- if mdutil.yesNo(wxparent, 'Metadata file is exist. Do you want to overwrite file: %s?' % path, 'Overwrite dialog'):
- try:
- xml_file = open(path, "w")
- xml_file.write(iso_xml)
- xml_file.close()
- Module('g.message', message='metadata exported: \n\
- %s' % (str(path)))
- except IOError as e:
- print "I/O error({0}): {1}".format(e.errno, e.strerror)
- grass.fatal('error: cannot write xml to file')
- return path
- else:
- try:
- xml_file = open(path, "w")
- xml_file.write(iso_xml)
- xml_file.close()
- Module('g.message', message='metadata exported: \n\
- %s' % (str(path)))
- except IOError as e:
- print "I/O error({0}): {1}".format(e.errno, e.strerror)
- grass.fatal('error: cannot write xml to file')
- # sys.exit()
- return path
- else:
- if os.path.isfile(path):
- Module('g.message', message='Metadata file is exist: %s' % path)
- if overwrite:
- try:
- xml_file = open(path, "w")
- xml_file.write(iso_xml)
- xml_file.close()
- Module('g.message', message='Metadata file has been overwritten')
- except IOError as e:
- print "I/O error({0}): {1}".format(e.errno, e.strerror)
- grass.fatal('error: cannot write xml to file')
- # sys.exit()
- return path
- else:
- Module('g.message', message='For overwriting use flag -o')
- return False
-
- def validate_inspire(self):
- return mdutil.isnpireValidator(self.md)
-
- def validate_basic(self):
- return mdutil.grassProfileValidator(self.md)
-
- def updateGrassMd(self, md):
- '''
- Update some parameters in r/v.support. This part need revision#TODO
- '''
- if self.type == "vector":
-
- if len(md.contact) > 0:
- _org = ''
- for co in md.contact:
- if co.organization != '':
- _org += co.organization + ', '
- if co.email != '':
- _org += co.email + ', '
- if co.role != '':
- _org += co.role + '; '
-
- Module('v.support',
- map=self.map,
- organization=_org,
- flags='r')
-
- if md.identification.date is not None:
- if len(md.identification.date) > 0:
- for d in md.identification.date:
- if d.type == 'creation':
- _date = d.date
-
- Module('v.support',
- map=self.map,
- date=_date,
- flags='r')
-
- if md.identification.contact is not None:
- if len(md.identification.contact) > 0:
- _person = md.identification.contact.organization.pop()
-
- Module('v.support',
- map=self.map,
- person=_person,
- flags='r')
-
- if md.identification.title is not (None or ''):
- _name = md.identification.title
- Module('v.support',
- map=self.map,
- map_name=_name,
- flags='r')
-
- if len(md.identification.denominators) > 0:
- _scale = md.identification.denominators.pop()
- try:
- _scale = int(_scale)
- Module('v.support',
- map=self.map,
- scale=_scale,
- flags='r')
- except:
- pass
-
- if md.identification.keywords is not None or len(md.identification.keywords) > 0:
- _comments = ''
- for k in md.identification.keywords:
- for kw in k["keywords"]:
- if kw != '':
- _comments += kw + ', '
- if k["thesaurus"]["title"] != '':
- _comments += k["thesaurus"]["title"] + ', '
- if k["thesaurus"]["date"] != '':
- _comments += k["thesaurus"]["date"] + ', '
- if k['thesaurus']['datetype'] != '':
- _comments += k['thesaurus']['datetype'] + ';'
-
- Module('v.support',
- map=self.map,
- comment=_comments,
- flags='r')
-
-#------------------------------------------------------------------------ RASTER
- if self.type == "cell":
-
- if md.identification.title is not (None or ''):
- _title = md.identification.title
- Module('r.support',
- map=self.map,
- title=_title,
- overwrite=True)
-
- if md.dataquality.lineage is not (None or ''):
- _history = md.dataquality.lineage
- Module('r.support',
- map=self.map, # append
- history=_history)
-
- _units = ''
- if len(md.identification.distance) > 0:
- _units += md.identification.distance.pop()
- if len(md.identification.uom) > 0:
- _units += md.identification.uom.pop()
- if _units != '':
- Module('r.support',
- map=self.map,
- units=_units,
- overwrite=True)
-
- if md.identification.keywords is not None or len(md.identification.keywords) > 0:
- _comments = self.md_grass['description']
- for k in md.identification.keywords:
- for kw in k["keywords"]:
- if kw != '':
- _comments += kw + ', '
- if k["thesaurus"]["title"] != '':
- _comments += k["thesaurus"]["title"] + ', '
- if k["thesaurus"]["date"] != '':
- _comments += k["thesaurus"]["date"] + ', '
- if k['thesaurus']['datetype'] != '':
- _comments += k['thesaurus']['datetype'] + ';'
-
- Module('r.support',
- map=self.map,
- description=_comments,
- overwrite=True)
Copied: grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/jinjainfo.py (from rev 61594, grass-addons/grass7/gui/wxpython/wx.metadata/jinjainfo.py)
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/jinjainfo.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/jinjainfo.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -0,0 +1,192 @@
+#!/usr/bin/env python
+# -*- coding: utf-8
+"""
+ at package jinjainfo
+ at module g.gui.metadata
+ at brief Library for parsing informations from jinja template
+
+Classes:
+ - jinjainfo::MdDescription
+ - jinjainfo::JinjaTemplateParser
+
+(C) 2014 by 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.
+
+ at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
+"""
+from core.gcmd import GError
+from mdutil import findBetween
+
+
+class MdDescription():
+
+ '''Object which is initialzed by jinja template in '{# #}'
+ '''
+
+ def __init__(self, tag=None, object=None, name='', desc=None,
+ example=None, type=None, multi=0, inboxmulti=None,
+ group=None, inbox=None, multiline=None, validator=None,
+ num=None, ref=None, selfInfoString=None):
+ '''
+ @param tag: OWSLib object which will be replaced by value of object after jinja template system render new file
+ @param object: some object in OWSLib is neecesarry to initialize temporaly in gui generator. Others are initialize by configure file
+ @param name: label and tooltip name
+ @param desc: description/definition of metadata item
+ @param example: example of md item (tooltip)
+ @param type: data type is neccesary to validet widgets
+ @param multi: 0=only one instance of editor::MdItem widget can be, 1= multiple insctances of widgets can be
+ @param inboxmulti: 0=static box of items has not button for duplicating self 1=has button
+ @param group: this param initialize page in notebook in mani editor
+ @param inbox: Every items in block of code in jinja template must have same value of inbox.
+ The value of inbox representing label of static box in gui.
+ @param multiline: If true- textCtrl widget will be init with multiline control
+ @param validator: Not use currently
+ @param ref: additional information about reference of metadata item (ISO reference)
+ @param selfInfoString: string value representing all these information. (parsed from jinja template)
+ @var mdItem: very important parametr which holds instances of widgets(editor::MdItem)
+ on every index of list is one instance of widget. In case, if is in static box MdItem with duplicating button:
+ index of list is represented by list of these items
+ @var statements: hold information about first statement in block
+ @var statements1: hold info about secont stetement in block of var: statement
+ '''
+ self.tag = tag
+ self.object = object
+ self.name = name
+ self.desc = desc
+ self.example = example
+ self.type = type
+ self.multiplicity = multi # multiplicity of MD item
+ self.group = group
+ self.inbox = inbox
+ self.ref = ref
+ self.selfInfoString = selfInfoString
+
+ self.inboxmulti = inboxmulti
+ self.multiline = multiline # type of ctrl text
+ self.validator = validator
+ # --info from jinja -end
+
+ self.statements = None
+ self.statements1 = None
+ self.mdItem = list()
+
+ def addMdItem(self, newMdItem, oldMdItem=None):
+ '''care about integrity of var: self.mdItem
+ '''
+ # if new mditem is from box- need to hold information
+ # about it.(list on the same index in self.mdItem)
+ if oldMdItem is not None:
+ for n, item in enumerate(self.mdItem):
+ for i in item:
+ if i == oldMdItem:
+ self.mdItem[n].append(newMdItem)
+ else:
+ self.mdItem.append(newMdItem)
+
+ def removeMdItem(self, item):
+ '''care about integrity of var: self.mdItem
+ '''
+ try:
+ for k, oldListItem in enumerate(self.mdItem):
+ for i in oldListItem:
+ if i == item:
+ self.mdItem[k].remove(item)
+ except:
+ self.mdItem.remove(item)
+
+ def addStatements(self, stat):
+ if self.statements is None:
+ self.statements = stat
+
+ def addStatements1(self, stat):
+ if self.statements1 is None:
+ self.statements1 = stat
+
+
+class JinjaTemplateParser():
+
+ '''Parser of OWSLib tag and init. values of jinjainfo::MdDescription from jinja template.
+ '''
+
+ def __init__(self, template):
+ '''
+ @var mdDescription: list of jinjainfo::mdDescription
+ @var mdOWSTag: list of tags in jinja templates
+ @var mdOWSTagStr: string representing OWSLib tags from template(per line)
+ @var mdOWSTagStrList: on each index of list is one line with parsed OWSLib tag
+ '''
+ self.mdDescription = []
+ self.mdOWSTag = []
+ self.template = template
+
+ self.mdOWSTagStr = ''
+ self.mdOWSTagStrList = []
+
+ self._readJinjaInfo()
+ self._readJinjaTags()
+ self._formatMdOWSTagStrToPythonBlocks()
+
+ def _readJinjaTags(self):
+ '''Parser of OWSLib tag from jinja template to list
+ '''
+ try:
+ with open(self.template, "r") as f:
+ for line in f:
+
+ # if found start of comments
+ if str(line).find("{{") != -1:
+ obj = findBetween(line, "{{", "}}")
+ self.mdOWSTag.append(obj)
+
+ if str(line).find("{%") != -1:
+ obj = findBetween(line, "{%", "-%}")
+ self.mdOWSTag.append(obj)
+
+ except:
+ GError('Cannot open jinja template')
+ # print "I/O error({0}): {1}".format(e.errno, e.strerror)
+
+ 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.decode("utf-8", 'ignore')
+ eval(exe_str)
+ except:
+ GError('Cannot open jinja template')
+ # print "I/O error({0}): {1}".format(e.errno, e.strerror)
+
+ def _formatMdOWSTagStrToPythonBlocks(self):
+ '''Formating of parsed tags to pythonic blocks
+ '''
+ self.mdOWSTagStr = ""
+ tab = 0
+ for item in self.mdOWSTag:
+ if str(item).find(" endfor ") != -1 or \
+ str(item).find(" endif ") != -1:
+ tab -= 1
+ continue
+
+ tabstr = '\t' * tab
+ str1 = tabstr + item[1:] + '\n'
+ self.mdOWSTagStr += str1
+ self.mdOWSTagStrList.append(tabstr + item[1:])
+
+ if str(item).find(" for ") != -1 \
+ or str(item).find(" if ") != -1:
+ tab += 1
Copied: grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/mdgrass.py (from rev 61594, grass-addons/grass7/gui/wxpython/wx.metadata/mdgrass.py)
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/mdgrass.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/mdgrass.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -0,0 +1,523 @@
+#!/usr/bin/env python
+# -*- coding: utf-8
+"""
+ at package mdgrass
+ at module v.info.iso, r.info.iso, g.gui.metadata
+ at brief Base class for import(r.info,v.info) and export(r/v.support)
+ metadata with using OWSLib and jinja template.
+
+Classes:
+ - mdgrass::MdDescription
+
+(C) 2014 by 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.
+
+ at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
+"""
+from owslib.iso import *
+from jinja2 import Environment, FileSystemLoader
+
+from lxml import etree
+import os
+import sys
+import re
+import StringIO
+import subprocess as sub
+import uuid
+import mdutil # metadata lib
+import getpass # whoami for linux and ms-win
+
+from grass.pygrass.modules.shortcuts import general as g
+from grass.pygrass.gis import Mapset
+from grass.pygrass import raster
+from grass.pygrass.modules import Module
+from grass.script import parse_key_val
+from subprocess import PIPE
+from datetime import date, datetime
+from grass.script import parser
+from grass.script import core as grass
+
+
+class GrassMD():
+
+ '''
+ @var self.map: name of choosen map by user
+ @var self.type: typ of map representation(cell, vector, r3)
+ @var md_grass: dict with metadata from r.info v.info except "r.info flag=h"
+
+ '''
+
+ def __init__(self, map, type):
+ self.map = map
+ self.type = type
+
+ self.isMapExist() # function to check if map exist
+ self.md_grass = {}
+ self.md_abstract = ''
+ self.md_vinfo_h = '' # v.info flag=h" - parse
+ self.gisenv_grass = grass.gisenv() # dict with gisenv information
+ # postfix of output xml file (variables)
+ self.schema_type = '_basic.xml' # currently
+ self.dirpath = os.path.dirname(os.path.realpath(__file__))
+ # metadata object from OWSLIB ( for define md values)
+ self.md = MD_Metadata(md=None)
+ self.template = None # path to file with xml templates
+
+ if self.type == "cell":
+ self.parseRast()
+ elif self.type == "vector":
+ self.parseVect()
+ elif self.type == "r3??":
+ # TODO
+ self.parseRast3D()
+
+ def isMapExist(self):
+ '''Check if is the map in working mapset'''
+ self.mapset = grass.find_file(self.map, self.type)['mapset']
+ if not self.mapset:
+ grass.fatal(_("Map <%s> doesn't exist") % self.map)
+
+ def parseRast3D(self):
+ pass
+
+ def parseVect(self):
+ '''Read metadata from v.info
+ @var self.md_grass dictionary of metadata from v.info
+ '''
+
+ # parse md from v.info flags=-g -e -t
+ vinfo = Module(
+ 'v.info',
+ self.map,
+ flags='get',
+ quiet=True,
+ stdout_=PIPE)
+
+ self.md_grass = parse_key_val(vinfo.outputs.stdout)
+
+ # parse md from v.info flag h (history of map in grass)
+ rinfo_h = Module(
+ 'v.info',
+ self.map,
+ flags='h',
+ quiet=True,
+ stdout_=PIPE)
+
+ md_h_grass = rinfo_h.outputs.stdout
+ buf = StringIO.StringIO(md_h_grass)
+ line = buf.readline().splitlines()
+ while str(line) != '[]':
+ if str(line[0]).strip() != "":
+ self.md_vinfo_h += line[0] + '\n'
+ line = buf.readline().splitlines()
+ buf.close()
+
+ # convert grass parsed date format to iso format
+ # if date format is diverse from standard, use them
+ self._createISODate('source_date')
+
+ def _createISODate(self, key):
+ '''Function for converting grass-generated date to iso format
+ if the format of date is different to grass-generated format - use them and print warning
+ '''
+ try:
+ date = datetime.strptime(self.md_grass[key], '%a %b %d %H:%M:%S %Y')
+ self.md_grass['dateofcreation'] = date.strftime('%Y-%m-%d')
+ except:
+ grass.warning('date of creation: unknown date format')
+ self.md_grass['dateofcreation'] = self.md_grass[key]
+
+ def parseRast(self):
+ '''Read metadata from r.info
+ #self.md_grass dictionary of metadata from v.info
+ #self.md_abstract string created by merge information from 'description' and 'source'
+ '''
+ rinfo = Module('r.info',
+ self.map,
+ flags='gre',
+ quiet=True,
+ stdout_=PIPE)
+
+ self.md_grass = parse_key_val(rinfo.outputs.stdout)
+
+ # convert date to iso format
+ self._createISODate('date')
+
+ # create abstract
+ if self.md_grass['description'] != '""':
+ self.md_abstract = self.md_grass['description'] + '; '
+ if self.md_grass['source1'] != '""':
+ self.md_abstract += self.md_grass['source1'] + '; '
+ if self.md_grass['source2'] != '""':
+ self.md_abstract += self.md_grass['source2'] + '; '
+ self.md_abstract += 'Total cells: ' + self.md_grass['cells'] + '; '
+ self.md_abstract += 'A range of values: min: ' + \
+ self.md_grass['min'] + ' max: ' + self.md_grass['max']
+ self.md_abstract.translate(None, """&<>"'""")
+
+ def createGrassBasicISO(self, template=None):
+ '''Create basic/essential profile based on ISO
+ - unknown values are filling by n = '$NULL'
+ '''
+ try:
+ self.md_grass['comments'] = self.md_grass['comments'].replace('\n', '; ')
+ except:
+ pass
+
+ n = '$NULL'
+ # jinja templates
+ if template is None:
+ self.template = os.path.join('templates', 'basicTemplate.xml')
+ else:
+ self.template = template
+
+ # OWSLib md object
+ self.md.identification = MD_DataIdentification()
+ self.md.dataquality = DQ_DataQuality()
+ self.md.distribution = MD_Distribution()
+ self.md.identification.extent = EX_Extent()
+ self.md.identification.extent.boundingBox = EX_GeographicBoundingBox()
+
+ # Metadata on metadata
+ val = CI_ResponsibleParty()
+ val.organization = n
+ val.email = n
+ val.role = n
+ self.md.contact.append(val)
+
+ # Identification/Resource Title
+ self.md.identification.title = mdutil.replaceXMLReservedChar(self.md_grass['title'])
+ self.md.datestamp = mdutil.replaceXMLReservedChar(date.today().isoformat())
+
+ # Identification/Resource Type
+ self.md.identification.identtype = 'dataset'
+
+ # Identification/Unique Resource Identifier
+ self.md.identifier = mdutil.replaceXMLReservedChar(str(uuid.uuid4()))
+ self.md.identification.uricode.append(n)
+ self.md.identification.uricodespace.append(n)
+
+ # Geographic/BB
+ self.md.identification.extent.boundingBox.minx = mdutil.replaceXMLReservedChar(self.md_grass['south'])
+ self.md.identification.extent.boundingBox.maxx = mdutil.replaceXMLReservedChar(self.md_grass['north'])
+ self.md.identification.extent.boundingBox.miny = mdutil.replaceXMLReservedChar(self.md_grass['west'])
+ self.md.identification.extent.boundingBox.maxy = mdutil.replaceXMLReservedChar(self.md_grass['east'])
+
+ # Conformity/Title
+ self.md.dataquality.conformancetitle.append(
+ 'GRASS basic metadata profile based on ISO 19115, 19139')
+
+ # Conformity/Date:
+ self.md.dataquality.conformancedate.append(mdutil.replaceXMLReservedChar(date.today().isoformat()))
+ self.md.dataquality.conformancedatetype.append('publication')
+
+ # Temporal/Date of creation
+ val = CI_Date()
+ val.date = self.md_grass['dateofcreation']
+ val.type = 'creation'
+ self.md.identification.date.append(val)
+
+ self.md.identification.uom.append('m') # TODO
+
+ # different metadata sources for vector and raster
+ if self.type == 'cell':
+ # Identification/Resource Abstract
+ self.md.identification.abstract = mdutil.replaceXMLReservedChar(self.md_abstract)
+ # Geographic/resolution
+ self.md.identification.distance.append(mdutil.replaceXMLReservedChar(self.md_grass['nsres'])) # TODO for discuss
+
+ # Quality/Lineage
+ try:
+ self.md.dataquality.lineage = mdutil.replaceXMLReservedChar(self.md_grass['comments']).replace('\n', '\\n')
+ except:
+ grass.warning('Native metadata *flag=comments* not found, dataquality.lineage filled by $NULL')
+ self.md.dataquality.lineage = n
+
+ self.md.identification.denominators.append(n)
+ # Organisation/Responsible Party:
+ val = CI_ResponsibleParty()
+ val.organization = n # self.md_grass['creator']
+ val.role = n
+ val.email = n
+ self.md.identification.contact.append(val)
+
+ if self.type == 'vector':
+
+ # Identification/Resource Abstract
+ # TODO not enough sources for crate abstarce
+ self.md.identification.abstract = mdutil.replaceXMLReservedChar(self.md_grass['name'])
+ self.md.dataquality.lineage = mdutil.replaceXMLReservedChar(self.md_vinfo_h).replace('\n', '\\n')
+
+ self.md.identification.denominators.append(self.md_grass['scale'])
+ # Organisation/Responsible Party:
+ val = CI_ResponsibleParty()
+ val.organization = n # mdutil.replaceXMLReservedChar(getpass.getuser())
+ val.email = n
+ val.role = n
+ self.md.identification.contact.append(val)
+
+ self.templatePathAbs = os.path.join(self.dirpath, self.template)
+
+ def createGrassInspireISO(self, template=None):
+ '''Create valid INSPIRE profile and fill it as much as possible by GRASS metadata. Missing values is $NULL
+ -create basic md profile and add INSPIRE mandatory attributes
+ '''
+
+ self.schema_type = '_inspire.xml'
+
+ # create basic profile
+ self.createGrassBasicISO()
+
+ if template is None:
+ self.template = os.path.join('templates', 'inspireTemplate.xml')
+ else:
+ self.template = template
+
+ n = '$NULL'
+
+ if len(self.md.identification.distance) == 0:
+ self.md.identification.distance.append(n) # TODO
+ # Classification/Topic Category
+ self.md.identification.topiccategory.append(n)
+ self.md.identification.resourcelanguage.append(n)
+ self.md.languagecode = n
+ # Keyword/Keyword
+ kw = {}
+ kw['keywords'] = []
+ kw['keywords'].append(n)
+
+ kw['type'] = n
+ kw['thesaurus'] = {}
+ kw['thesaurus']['date'] = n
+ kw['thesaurus']['datetype'] = n
+ kw['thesaurus']['title'] = n
+ self.md.identification.keywords.append(kw)
+
+ # Conformity/Title
+ # remove value from basic profile
+ self.md.dataquality.conformancetitle.pop()
+ self.md.dataquality.conformancetitle.append(
+ 'Commission Regulation (EU) No 1089/2010 of 23 November 2010 implementing Directive 2007/2/EC of the European Parliament and of the Council as regards interoperability of spatial data sets and services')
+ # Identification/Resource Locator
+ val = CI_OnlineResource()
+ val.url = n
+ self.md.distribution.online.append(val)
+
+ # Conformity/Date
+ self.md.dataquality.conformancedate.append(n)
+ self.md.dataquality.conformancedatetype.append(n)
+
+ # Conformity/Degree
+ self.md.dataquality.conformancedegree.append('true')
+
+ # Constraints/Limitations on public access
+ self.md.identification.accessconstraints.append(n)
+ self.md.identification.otherconstraints.append(n)
+
+ # Constraints/Conditions for access and use-general
+ self.md.identification.uselimitation.append(n)
+
+ # Temporal/Temporal Extent
+ self.md.identification.temporalextent_start = n
+ self.md.identification.temporalextent_end = n
+
+ self.templatePathAbs = os.path.join(self.dirpath, self.template)
+ # print self.templatePathAbs
+
+ def readXML(self, xml_file):
+ '''create instance of metadata(owslib) from xml file'''
+ self.md = MD_Metadata(etree.parse(xml_file))
+
+ def saveXML(self, path=None, xml_out_name=None, wxparent=None, overwrite=False):
+ ''' Save init. record of OWSLib objects to ISO XML file'''
+
+ # if output file name is None, use map name and add postfix
+ if xml_out_name is None:
+ xml_out_name = self.type + '_' + str(self.map).partition('@')[0] # + self.schema_type
+ if not xml_out_name.lower().endswith('.xml'):
+ xml_out_name += '.xml'
+
+ if not path:
+ path = os.path.join(mdutil.pathToMapset(), 'metadata')
+ if not os.path.exists(path):
+ print os.makedirs(path)
+ path = os.path.join(path, xml_out_name)
+
+ # generate xml using jinja tempaltes
+ env = Environment(loader=FileSystemLoader(self.dirpath))
+ env.globals.update(zip=zip)
+ template = env.get_template(self.template)
+ iso_xml = template.render(md=self.md)
+
+ # write xml to flat file
+ if wxparent != None:
+ if os.path.isfile(path):
+ if mdutil.yesNo(wxparent, 'Metadata file is exist. Do you want to overwrite file: %s?' % path, 'Overwrite dialog'):
+ try:
+ xml_file = open(path, "w")
+ xml_file.write(iso_xml)
+ xml_file.close()
+ Module('g.message', message='metadata exported: \n\
+ %s' % (str(path)))
+ except IOError as e:
+ print "I/O error({0}): {1}".format(e.errno, e.strerror)
+ grass.fatal('error: cannot write xml to file')
+ return path
+ else:
+ try:
+ xml_file = open(path, "w")
+ xml_file.write(iso_xml)
+ xml_file.close()
+ Module('g.message', message='metadata exported: \n\
+ %s' % (str(path)))
+ except IOError as e:
+ print "I/O error({0}): {1}".format(e.errno, e.strerror)
+ grass.fatal('error: cannot write xml to file')
+ # sys.exit()
+ return path
+ else:
+ if os.path.isfile(path):
+ Module('g.message', message='Metadata file is exist: %s' % path)
+ if overwrite:
+ try:
+ xml_file = open(path, "w")
+ xml_file.write(iso_xml)
+ xml_file.close()
+ Module('g.message', message='Metadata file has been overwritten')
+ except IOError as e:
+ print "I/O error({0}): {1}".format(e.errno, e.strerror)
+ grass.fatal('error: cannot write xml to file')
+ # sys.exit()
+ return path
+ else:
+ Module('g.message', message='For overwriting use flag -o')
+ return False
+
+ def validate_inspire(self):
+ return mdutil.isnpireValidator(self.md)
+
+ def validate_basic(self):
+ return mdutil.grassProfileValidator(self.md)
+
+ def updateGrassMd(self, md):
+ '''
+ Update some parameters in r/v.support. This part need revision#TODO
+ '''
+ if self.type == "vector":
+
+ if len(md.contact) > 0:
+ _org = ''
+ for co in md.contact:
+ if co.organization != '':
+ _org += co.organization + ', '
+ if co.email != '':
+ _org += co.email + ', '
+ if co.role != '':
+ _org += co.role + '; '
+
+ Module('v.support',
+ map=self.map,
+ organization=_org,
+ flags='r')
+
+ if md.identification.date is not None:
+ if len(md.identification.date) > 0:
+ for d in md.identification.date:
+ if d.type == 'creation':
+ _date = d.date
+
+ Module('v.support',
+ map=self.map,
+ date=_date,
+ flags='r')
+
+ if md.identification.contact is not None:
+ if len(md.identification.contact) > 0:
+ _person = md.identification.contact.organization.pop()
+
+ Module('v.support',
+ map=self.map,
+ person=_person,
+ flags='r')
+
+ if md.identification.title is not (None or ''):
+ _name = md.identification.title
+ Module('v.support',
+ map=self.map,
+ map_name=_name,
+ flags='r')
+
+ if len(md.identification.denominators) > 0:
+ _scale = md.identification.denominators.pop()
+ try:
+ _scale = int(_scale)
+ Module('v.support',
+ map=self.map,
+ scale=_scale,
+ flags='r')
+ except:
+ pass
+
+ if md.identification.keywords is not None or len(md.identification.keywords) > 0:
+ _comments = ''
+ for k in md.identification.keywords:
+ for kw in k["keywords"]:
+ if kw != '':
+ _comments += kw + ', '
+ if k["thesaurus"]["title"] != '':
+ _comments += k["thesaurus"]["title"] + ', '
+ if k["thesaurus"]["date"] != '':
+ _comments += k["thesaurus"]["date"] + ', '
+ if k['thesaurus']['datetype'] != '':
+ _comments += k['thesaurus']['datetype'] + ';'
+
+ Module('v.support',
+ map=self.map,
+ comment=_comments,
+ flags='r')
+
+#------------------------------------------------------------------------ RASTER
+ if self.type == "cell":
+
+ if md.identification.title is not (None or ''):
+ _title = md.identification.title
+ Module('r.support',
+ map=self.map,
+ title=_title,
+ overwrite=True)
+
+ if md.dataquality.lineage is not (None or ''):
+ _history = md.dataquality.lineage
+ Module('r.support',
+ map=self.map, # append
+ history=_history)
+
+ _units = ''
+ if len(md.identification.distance) > 0:
+ _units += md.identification.distance.pop()
+ if len(md.identification.uom) > 0:
+ _units += md.identification.uom.pop()
+ if _units != '':
+ Module('r.support',
+ map=self.map,
+ units=_units,
+ overwrite=True)
+
+ if md.identification.keywords is not None or len(md.identification.keywords) > 0:
+ _comments = self.md_grass['description']
+ for k in md.identification.keywords:
+ for kw in k["keywords"]:
+ if kw != '':
+ _comments += kw + ', '
+ if k["thesaurus"]["title"] != '':
+ _comments += k["thesaurus"]["title"] + ', '
+ if k["thesaurus"]["date"] != '':
+ _comments += k["thesaurus"]["date"] + ', '
+ if k['thesaurus']['datetype'] != '':
+ _comments += k['thesaurus']['datetype'] + ';'
+
+ Module('r.support',
+ map=self.map,
+ description=_comments,
+ overwrite=True)
Copied: grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/mdutil.py (from rev 61594, grass-addons/grass7/gui/wxpython/wx.metadata/mdutil.py)
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/mdutil.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/mdlib/mdutil.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -0,0 +1,387 @@
+#!/usr/bin/env python
+# -*- coding: utf-8
+"""
+ at package mdgrass
+ at module v.info.iso, r.info.iso, g.gui.metadata
+ at brief Global methods for metadata management
+
+Methods:
+-mdutil::removeNonAscii
+-mdutil::yesNo
+-mdutil::findBetween
+-mdutil::replaceXMLReservedChar
+-mdutil::pathToMapset
+-mdutil::grassProfileValidator
+-mdutil::isnpireValidator
+
+(C) 2014 by 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.
+
+ at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
+"""
+
+import string
+import os
+from grass.script import core as grass
+import wx
+
+
+def removeNonAscii(s):
+ '''Removed non ascii char
+ '''
+ s = filter(lambda x: x in string.printable, s)
+ return s
+
+
+def yesNo(parent, question, caption='Yes or no?'):
+
+ dlg = wx.MessageDialog(parent, question, caption, wx.YES_NO | wx.ICON_QUESTION)
+ result = dlg.ShowModal() == wx.ID_YES
+ dlg.Destroy()
+ return result
+
+
+def findBetween(s, first, last):
+ try:
+ start = s.index(first) + len(first)
+ end = s.index(last, start)
+ return s[start:end]
+ except:
+ return ""
+
+
+def replaceXMLReservedChar(inp):
+ if inp:
+ import re
+
+ inp = re.sub('<', '<', inp)
+ inp = re.sub('>', '>', inp)
+ inp = re.sub('&', '&', inp)
+ inp = re.sub('%', '%', inp)
+ return inp
+
+
+def pathToMapset():
+ gisenvDict = grass.gisenv()
+ return os.path.join(gisenvDict['GISDBASE'], gisenvDict['LOCATION_NAME'], gisenvDict['MAPSET'])
+
+
+def grassProfileValidator(md):
+ '''function for validation GRASS BASIC XML-OWSLib file-object'''
+
+ result = {}
+ result["status"] = "succeded"
+ result["errors"] = []
+ result["num_of_errors"] = "0"
+ errors = 0
+
+ if md.identification is None:
+ result["errors"].append("gmd:CI_ResponsibleParty: Organization missing")
+ result["errors"].append("gmd:CI_ResponsibleParty: E-mail missing")
+ result["errors"].append("gmd:CI_ResponsibleParty: Role missing")
+ result["errors"].append("gmd:md_DataIdentification: Title is missing")
+ result["errors"].append("gmd:md_DataIdentification: Abstract is missing")
+ result["errors"].append("gmd:md_ScopeCode: Resource Type is missing")
+ result["errors"].append("gmd:RS_Identifier: Unique Resource Identifier is missing")
+ result["errors"].append("gmd:EX_Extent: extent element is missing")
+ result["errors"].append("gmd:EX_GeographicBoundingBox: bbox is missing")
+ result["errors"].append("Both gmd:EX_TemporalExtent and gmd:CI_Date are missing")
+ result["errors"].append("gmd:useLimitation is missing")
+ errors += 20
+ else:
+ if len(md.identification.contact) < 1 or md.identification.contact is None:
+ result["errors"].append("gmd:CI_ResponsibleParty: Organization missing")
+ result["errors"].append("gmd:CI_ResponsibleParty: E-mail missing")
+ result["errors"].append("gmd:CI_ResponsibleParty: Role missing")
+ errors += 3
+ else:
+ if md.identification.contact[0].organization is (None or ''):
+ result["errors"].append("gmd:CI_ResponsibleParty: Organization missing")
+ errors += 1
+
+ if md.identification.contact[0].email is (None or ''):
+ result["errors"].append("gmd:CI_ResponsibleParty: E-mail missing")
+ errors += 1
+
+ if md.identification.contact[0].role is (None or ''):
+ result["errors"].append("gmd:CI_ResponsibleParty: Role missing")
+ errors += 1
+
+ if md.identification.title is (None or ''):
+ result["errors"].append("gmd:md_DataIdentification: Title is missing")
+ errors += 1
+ if md.identification.abstract is (None or ''):
+ result["errors"].append("gmd:md_DataIdentification: Abstract is missing")
+ errors += 1
+ if md.identification.identtype is '':
+ result["errors"].append("gmd:md_ScopeCode: Resource Type is missing")
+ errors += 1
+
+ if md.identification.extent is None:
+ result["errors"].append("gmd:EX_Extent: extent element is missing")
+ errors += 4
+ else:
+ if md.identification.extent.boundingBox is None:
+ result["errors"].append("gmd:EX_GeographicBoundingBox: bbox is missing")
+ errors += 4
+ else:
+ if md.identification.extent.boundingBox.minx is (None or ''):
+ result["errors"].append("gmd:westBoundLongitude: minx is missing")
+ errors += 1
+ if md.identification.extent.boundingBox.maxx is (None or ''):
+ result["errors"].append("gmd:eastBoundLongitude: maxx is missing")
+ errors += 1
+ if md.identification.extent.boundingBox.miny is (None or ''):
+ result["errors"].append("gmd:southBoundLatitude: miny is missing")
+ errors += 1
+ if md.identification.extent.boundingBox.maxy is (None or ''):
+ result["errors"].append("gmd:northBoundLatitude: maxy is missing")
+ errors += 1
+
+ if len(md.identification.date) < 1 or (md.identification.temporalextent_start is (
+ None or '') or md.identification.temporalextent_end is (None or '')):
+ result["errors"].append("Both gmd:EX_TemporalExtent and gmd:CI_Date are missing")
+ errors += 1
+
+ if md.datestamp is (None or ''):
+ result["errors"].append("gmd:dateStamp: Date is missing")
+ errors += 1
+
+ if md.identifier is (None or ''):
+ result["errors"].append("gmd:identifier: Identifier is missing")
+ errors += 1
+
+ if md.contact is None:
+ result["errors"].append("gmd:contact: Organization name is missing")
+ result["errors"].append("gmd:contact: e-mail is missing")
+ result["errors"].append("gmd:role: role is missing")
+ errors += 3
+ else:
+ if md.contact[0].organization is (None or ''):
+ result["errors"].append("gmd:contact: Organization name is missing")
+ errors += 1
+
+ if md.contact[0].email is (None or ''):
+ result["errors"].append("gmd:contact: e-mail is missing")
+ errors += 1
+
+ if md.contact[0].role is (None or ''):
+ result["errors"].append("gmd:role: role is missing")
+ errors += 1
+
+ if errors > 0:
+ result["status"] = "failed"
+ result["num_of_errors"] = str(errors)
+ return result
+
+
+def isnpireValidator(md):
+ '''function for validation INSPIRE XML-OWSLib file-object'''
+
+ result = {}
+ result["status"] = "succeded"
+ result["errors"] = []
+ result["num_of_errors"] = "0"
+ errors = 0
+
+ if md.identification is None:
+ result["errors"].append("gmd:CI_ResponsibleParty: Organization missing")
+ result["errors"].append("gmd:CI_ResponsibleParty: E-mail missing")
+ result["errors"].append("gmd:CI_ResponsibleParty: Role missing")
+ result["errors"].append("gmd:md_DataIdentification: Title is missing")
+ result["errors"].append("gmd:md_DataIdentification: Abstract is missing")
+ result["errors"].append("gmd:md_ScopeCode: Resource Type is missing")
+ result["errors"].append("gmd:language: Resource Language is missing")
+ result["errors"].append("gmd:RS_Identifier: Unique Resource Identifier is missing")
+ result["errors"].append("gmd:topicCategory: TopicCategory is missing")
+ result["errors"].append("gmd:md_Keywords: Keywords are missing")
+ result["errors"].append("gmd:thesaurusName: Thesaurus Title is missing")
+ result["errors"].append("gmd:thesaurusName: Thesaurus Date is missing")
+ result["errors"].append("gmd:thesaurusName: Thesaurus Date Type is missing")
+ result["errors"].append("gmd:EX_Extent: extent element is missing")
+ result["errors"].append("gmd:EX_GeographicBoundingBox: bbox is missing")
+ result["errors"].append("Both gmd:EX_TemporalExtent and gmd:CI_Date are missing")
+ result["errors"].append("gmd:useLimitation is missing")
+ result["errors"].append("gmd:accessConstraints is missing")
+ result["errors"].append("gmd:otherConstraints is missing")
+ errors += 20
+ else:
+ if md.identification.contact is None or len(md.identification.contact) < 1:
+ result["errors"].append("gmd:CI_ResponsibleParty: Organization missing")
+ result["errors"].append("gmd:CI_ResponsibleParty: E-mail missing")
+ result["errors"].append("gmd:CI_ResponsibleParty: Role missing")
+ errors += 3
+ else:
+
+ if md.identification.contact[0].organization is (None or ''):
+ result["errors"].append("gmd:CI_ResponsibleParty: Organization missing")
+ errors += 1
+
+ if md.identification.contact[0].email is (None or ''):
+ result["errors"].append("gmd:CI_ResponsibleParty: E-mail missing")
+ errors += 1
+
+ if md.identification.contact[0].role is (None or ''):
+ result["errors"].append("gmd:CI_ResponsibleParty: Role missing")
+ errors += 1
+
+ if md.identification.title is (None or ''):
+ result["errors"].append("gmd:md_DataIdentification: Title is missing")
+ errors += 1
+ if md.identification.abstract is (None or ''):
+ result["errors"].append("gmd:md_DataIdentification: Abstract is missing")
+ errors += 1
+ if md.identification.identtype is (None or ''):
+ result["errors"].append("gmd:md_ScopeCode: Resource Type is missing")
+ errors += 1
+
+ if md.identification.resourcelanguage is None:
+ errors += 1
+ result["errors"].append("gmd:language: Resource Language is missing")
+ else:
+ if len(md.identification.resourcelanguage) < 1 or md.identification.resourcelanguage[0] == '':
+ result["errors"].append("gmd:language: Resource Language is missing")
+ errors += 1
+
+ if md.identification.uricode is None:
+ result["errors"].append("gmd:RS_Identifier: Unique Resource Identifier is missing")
+ errors += 1
+ else:
+ if len(md.identification.uricode) < 1 or md.identification.uricode[0] == '':
+ result["errors"].append("gmd:RS_Identifier: Unique Resource Identifier is missing")
+ errors += 1
+
+ if md.identification.topiccategory is None:
+ result["errors"].append("gmd:topicCategory: TopicCategory is missing")
+ errors += 1
+ else:
+ if len(md.identification.topiccategory) < 1 or md.identification.topiccategory[0] == '':
+ result["errors"].append("gmd:topicCategory: TopicCategory is missing")
+ errors += 1
+
+ if md.identification.keywords is None or len(md.identification.keywords) < 1:
+ result["errors"].append("gmd:MD_Keywords: Keywords are missing")
+ result["errors"].append("gmd:thesaurusName: Thesaurus Title is missing")
+ result["errors"].append("gmd:thesaurusName: Thesaurus Date is missing")
+ result["errors"].append("gmd:thesaurusName: Thesaurus Date Type is missing")
+ errors += 4
+ else:
+ if md.identification.keywords[0]['keywords'] is None or len(md.identification.keywords[0]['keywords']) < 1 \
+ or str(md.identification.keywords[0]['keywords']) == "[u'']":
+ result["errors"].append("gmd:MD_Keywords: Keywords are missing")
+ errors += 1
+ if md.identification.keywords[0]['thesaurus'] is None:
+ result["errors"].append("gmd:thesaurusName: Thesaurus Title is missing")
+ result["errors"].append("gmd:thesaurusName: Thesaurus Date is missing")
+ result["errors"].append("gmd:thesaurusName: Thesaurus Date Type is missing")
+ errors += 3
+ else:
+ if md.identification.keywords[0]['thesaurus']['title'] is None \
+ or len(md.identification.keywords[0]['thesaurus']['title']) < 1:
+ result["errors"].append("gmd:thesaurusName: Thesaurus Title is missing")
+ errors += 1
+ if md.identification.keywords[0]['thesaurus']['date'] is None \
+ or len(md.identification.keywords[0]['thesaurus']['date']) < 1:
+ result["errors"].append("gmd:thesaurusName: Thesaurus Date is missing")
+ errors += 1
+ if md.identification.keywords[0]['thesaurus']['datetype'] is None \
+ or len(md.identification.keywords[0]['thesaurus']['datetype']) < 1:
+ result["errors"].append("gmd:thesaurusName: Thesaurus Date Type is missing")
+ errors += 1
+
+ if md.identification.extent is None:
+ result["errors"].append("gmd:EX_Extent: extent element is missing")
+ errors += 1
+ else:
+ if md.identification.extent.boundingBox is None:
+ result["errors"].append(
+ "gmd:EX_GeographicBoundingBox: bbox is missing")
+ errors += 1
+ else:
+ if md.identification.extent.boundingBox.minx is (None or ''):
+ result["errors"].append("gmd:westBoundLongitude: minx is missing")
+ errors += 1
+ if md.identification.extent.boundingBox.maxx is (None or ''):
+ result["errors"].append("gmd:eastBoundLongitude: maxx is missing")
+ errors += 1
+ if md.identification.extent.boundingBox.miny is (None or ''):
+ result["errors"].append("gmd:southBoundLatitude: miny is missing")
+ errors += 1
+ if md.identification.extent.boundingBox.maxy is (None or ''):
+ result["errors"].append("gmd:northBoundLatitude: maxy is missing")
+ errors += 1
+
+ if len(md.identification.date) < 1 or (md.identification.temporalextent_start is (
+ None or '') or md.identification.temporalextent_end is (None or '')):
+ result["errors"].append("Both gmd:EX_TemporalExtent and gmd:CI_Date are missing")
+ errors += 1
+
+ if len(md.identification.uselimitation) < 1 or md.identification.uselimitation[0] == '':
+ result["errors"].append("gmd:useLimitation is missing")
+ errors += 1
+ if len(md.identification.accessconstraints) < 1 or md.identification.accessconstraints[0] == '':
+ result["errors"].append("gmd:accessConstraints is missing")
+ errors += 1
+ if len(md.identification.otherconstraints) < 1 or md.identification.otherconstraints[0] == '':
+ result["errors"].append("gmd:otherConstraints is missing")
+ errors += 1
+
+ if md.languagecode is (None or ''):
+ result["errors"].append("gmd:LanguageCode: Language code missing")
+ errors += 1
+ if md.datestamp is (None or ''):
+ result["errors"].append("gmd:dateStamp: Date is missing")
+ errors += 1
+ if md.identifier is (None or ''):
+ result["errors"].append("gmd:identifier: Identifier is missing")
+ errors += 1
+ if md.dataquality is (None or ''):
+ result["errors"].append("gmd:LI_Lineage is missing")
+ result["errors"].append("gmd:DQ_ConformanceResult: date is missing")
+ result["errors"].append("gmd:DQ_ConformanceResult: date type is missing")
+ # result["errors"].append("gmd:DQ_ConformanceResult: degree is missing")
+ result["errors"].append("gmd:DQ_ConformanceResult: title is missing")
+ errors += 4
+ else:
+
+ if md.dataquality.lineage is (None or ''):
+ result["errors"].append("gmd:LI_Lineage is missing")
+ errors += 1
+ if len(md.dataquality.conformancedate) < 1 or md.dataquality.conformancedate[0] == '':
+ result["errors"].append("gmd:DQ_ConformanceResult: date is missing")
+ errors += 1
+ if len(md.dataquality.conformancedatetype) < 1 or md.dataquality.conformancedatetype[0] == '':
+ result["errors"].append("gmd:DQ_ConformanceResult: date type is missing")
+ errors += 1
+ # if len(md.dataquality.conformancedegree) < 1:
+ # result["errors"].append("gmd:DQ_ConformanceResult: degree is missing")
+ # errors += 1
+ if len(md.dataquality.conformancetitle) < 1 or md.dataquality.conformancetitle[0] == '':
+ result["errors"].append("gmd:DQ_ConformanceResult: title is missing")
+ errors += 1
+
+ if md.contact is None or len(md.contact) < 1:
+ result["errors"].append("gmd:contact: Organization name is missing")
+ result["errors"].append("gmd:contact: e-mail is missing")
+ result["errors"].append("gmd:role: role is missing")
+ errors += 3
+ else:
+
+ if md.contact[0].organization is (None or ''):
+ result["errors"].append("gmd:contact: Organization name is missing")
+ errors += 1
+
+ if md.contact[0].email is (None or ''):
+ result["errors"].append("gmd:contact: e-mail is missing")
+ errors += 1
+
+ if md.contact[0].role is (None or ''):
+ result["errors"].append("gmd:role: role is missing")
+ errors += 1
+
+ if errors > 0:
+ result["status"] = "failed"
+ result["num_of_errors"] = str(errors)
+
+ return result
Deleted: grass-addons/grass7/gui/wxpython/wx.metadata/mdutil.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/mdutil.py 2014-08-13 15:54:00 UTC (rev 61594)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/mdutil.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -1,387 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8
-"""
- at package mdgrass
- at module v.info.iso, r.info.iso, g.gui.metadata
- at brief Global methods for metadata management
-
-Methods:
--mdutil::removeNonAscii
--mdutil::yesNo
--mdutil::findBetween
--mdutil::replaceXMLReservedChar
--mdutil::pathToMapset
--mdutil::grassProfileValidator
--mdutil::isnpireValidator
-
-(C) 2014 by 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.
-
- at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
-"""
-
-import string
-import os
-from grass.script import core as grass
-import wx
-
-
-def removeNonAscii(s):
- '''Removed non ascii char
- '''
- s = filter(lambda x: x in string.printable, s)
- return s
-
-
-def yesNo(parent, question, caption='Yes or no?'):
-
- dlg = wx.MessageDialog(parent, question, caption, wx.YES_NO | wx.ICON_QUESTION)
- result = dlg.ShowModal() == wx.ID_YES
- dlg.Destroy()
- return result
-
-
-def findBetween(s, first, last):
- try:
- start = s.index(first) + len(first)
- end = s.index(last, start)
- return s[start:end]
- except:
- return ""
-
-
-def replaceXMLReservedChar(inp):
- if inp:
- import re
-
- inp = re.sub('<', '<', inp)
- inp = re.sub('>', '>', inp)
- inp = re.sub('&', '&', inp)
- inp = re.sub('%', '%', inp)
- return inp
-
-
-def pathToMapset():
- gisenvDict = grass.gisenv()
- return os.path.join(gisenvDict['GISDBASE'], gisenvDict['LOCATION_NAME'], gisenvDict['MAPSET'])
-
-
-def grassProfileValidator(md):
- '''function for validation GRASS BASIC XML-OWSLib file-object'''
-
- result = {}
- result["status"] = "succeded"
- result["errors"] = []
- result["num_of_errors"] = "0"
- errors = 0
-
- if md.identification is None:
- result["errors"].append("gmd:CI_ResponsibleParty: Organization missing")
- result["errors"].append("gmd:CI_ResponsibleParty: E-mail missing")
- result["errors"].append("gmd:CI_ResponsibleParty: Role missing")
- result["errors"].append("gmd:md_DataIdentification: Title is missing")
- result["errors"].append("gmd:md_DataIdentification: Abstract is missing")
- result["errors"].append("gmd:md_ScopeCode: Resource Type is missing")
- result["errors"].append("gmd:RS_Identifier: Unique Resource Identifier is missing")
- result["errors"].append("gmd:EX_Extent: extent element is missing")
- result["errors"].append("gmd:EX_GeographicBoundingBox: bbox is missing")
- result["errors"].append("Both gmd:EX_TemporalExtent and gmd:CI_Date are missing")
- result["errors"].append("gmd:useLimitation is missing")
- errors += 20
- else:
- if len(md.identification.contact) < 1 or md.identification.contact is None:
- result["errors"].append("gmd:CI_ResponsibleParty: Organization missing")
- result["errors"].append("gmd:CI_ResponsibleParty: E-mail missing")
- result["errors"].append("gmd:CI_ResponsibleParty: Role missing")
- errors += 3
- else:
- if md.identification.contact[0].organization is (None or ''):
- result["errors"].append("gmd:CI_ResponsibleParty: Organization missing")
- errors += 1
-
- if md.identification.contact[0].email is (None or ''):
- result["errors"].append("gmd:CI_ResponsibleParty: E-mail missing")
- errors += 1
-
- if md.identification.contact[0].role is (None or ''):
- result["errors"].append("gmd:CI_ResponsibleParty: Role missing")
- errors += 1
-
- if md.identification.title is (None or ''):
- result["errors"].append("gmd:md_DataIdentification: Title is missing")
- errors += 1
- if md.identification.abstract is (None or ''):
- result["errors"].append("gmd:md_DataIdentification: Abstract is missing")
- errors += 1
- if md.identification.identtype is '':
- result["errors"].append("gmd:md_ScopeCode: Resource Type is missing")
- errors += 1
-
- if md.identification.extent is None:
- result["errors"].append("gmd:EX_Extent: extent element is missing")
- errors += 4
- else:
- if md.identification.extent.boundingBox is None:
- result["errors"].append("gmd:EX_GeographicBoundingBox: bbox is missing")
- errors += 4
- else:
- if md.identification.extent.boundingBox.minx is (None or ''):
- result["errors"].append("gmd:westBoundLongitude: minx is missing")
- errors += 1
- if md.identification.extent.boundingBox.maxx is (None or ''):
- result["errors"].append("gmd:eastBoundLongitude: maxx is missing")
- errors += 1
- if md.identification.extent.boundingBox.miny is (None or ''):
- result["errors"].append("gmd:southBoundLatitude: miny is missing")
- errors += 1
- if md.identification.extent.boundingBox.maxy is (None or ''):
- result["errors"].append("gmd:northBoundLatitude: maxy is missing")
- errors += 1
-
- if len(md.identification.date) < 1 or (md.identification.temporalextent_start is (
- None or '') or md.identification.temporalextent_end is (None or '')):
- result["errors"].append("Both gmd:EX_TemporalExtent and gmd:CI_Date are missing")
- errors += 1
-
- if md.datestamp is (None or ''):
- result["errors"].append("gmd:dateStamp: Date is missing")
- errors += 1
-
- if md.identifier is (None or ''):
- result["errors"].append("gmd:identifier: Identifier is missing")
- errors += 1
-
- if md.contact is None:
- result["errors"].append("gmd:contact: Organization name is missing")
- result["errors"].append("gmd:contact: e-mail is missing")
- result["errors"].append("gmd:role: role is missing")
- errors += 3
- else:
- if md.contact[0].organization is (None or ''):
- result["errors"].append("gmd:contact: Organization name is missing")
- errors += 1
-
- if md.contact[0].email is (None or ''):
- result["errors"].append("gmd:contact: e-mail is missing")
- errors += 1
-
- if md.contact[0].role is (None or ''):
- result["errors"].append("gmd:role: role is missing")
- errors += 1
-
- if errors > 0:
- result["status"] = "failed"
- result["num_of_errors"] = str(errors)
- return result
-
-
-def isnpireValidator(md):
- '''function for validation INSPIRE XML-OWSLib file-object'''
-
- result = {}
- result["status"] = "succeded"
- result["errors"] = []
- result["num_of_errors"] = "0"
- errors = 0
-
- if md.identification is None:
- result["errors"].append("gmd:CI_ResponsibleParty: Organization missing")
- result["errors"].append("gmd:CI_ResponsibleParty: E-mail missing")
- result["errors"].append("gmd:CI_ResponsibleParty: Role missing")
- result["errors"].append("gmd:md_DataIdentification: Title is missing")
- result["errors"].append("gmd:md_DataIdentification: Abstract is missing")
- result["errors"].append("gmd:md_ScopeCode: Resource Type is missing")
- result["errors"].append("gmd:language: Resource Language is missing")
- result["errors"].append("gmd:RS_Identifier: Unique Resource Identifier is missing")
- result["errors"].append("gmd:topicCategory: TopicCategory is missing")
- result["errors"].append("gmd:md_Keywords: Keywords are missing")
- result["errors"].append("gmd:thesaurusName: Thesaurus Title is missing")
- result["errors"].append("gmd:thesaurusName: Thesaurus Date is missing")
- result["errors"].append("gmd:thesaurusName: Thesaurus Date Type is missing")
- result["errors"].append("gmd:EX_Extent: extent element is missing")
- result["errors"].append("gmd:EX_GeographicBoundingBox: bbox is missing")
- result["errors"].append("Both gmd:EX_TemporalExtent and gmd:CI_Date are missing")
- result["errors"].append("gmd:useLimitation is missing")
- result["errors"].append("gmd:accessConstraints is missing")
- result["errors"].append("gmd:otherConstraints is missing")
- errors += 20
- else:
- if md.identification.contact is None or len(md.identification.contact) < 1:
- result["errors"].append("gmd:CI_ResponsibleParty: Organization missing")
- result["errors"].append("gmd:CI_ResponsibleParty: E-mail missing")
- result["errors"].append("gmd:CI_ResponsibleParty: Role missing")
- errors += 3
- else:
-
- if md.identification.contact[0].organization is (None or ''):
- result["errors"].append("gmd:CI_ResponsibleParty: Organization missing")
- errors += 1
-
- if md.identification.contact[0].email is (None or ''):
- result["errors"].append("gmd:CI_ResponsibleParty: E-mail missing")
- errors += 1
-
- if md.identification.contact[0].role is (None or ''):
- result["errors"].append("gmd:CI_ResponsibleParty: Role missing")
- errors += 1
-
- if md.identification.title is (None or ''):
- result["errors"].append("gmd:md_DataIdentification: Title is missing")
- errors += 1
- if md.identification.abstract is (None or ''):
- result["errors"].append("gmd:md_DataIdentification: Abstract is missing")
- errors += 1
- if md.identification.identtype is (None or ''):
- result["errors"].append("gmd:md_ScopeCode: Resource Type is missing")
- errors += 1
-
- if md.identification.resourcelanguage is None:
- errors += 1
- result["errors"].append("gmd:language: Resource Language is missing")
- else:
- if len(md.identification.resourcelanguage) < 1 or md.identification.resourcelanguage[0] == '':
- result["errors"].append("gmd:language: Resource Language is missing")
- errors += 1
-
- if md.identification.uricode is None:
- result["errors"].append("gmd:RS_Identifier: Unique Resource Identifier is missing")
- errors += 1
- else:
- if len(md.identification.uricode) < 1 or md.identification.uricode[0] == '':
- result["errors"].append("gmd:RS_Identifier: Unique Resource Identifier is missing")
- errors += 1
-
- if md.identification.topiccategory is None:
- result["errors"].append("gmd:topicCategory: TopicCategory is missing")
- errors += 1
- else:
- if len(md.identification.topiccategory) < 1 or md.identification.topiccategory[0] == '':
- result["errors"].append("gmd:topicCategory: TopicCategory is missing")
- errors += 1
-
- if md.identification.keywords is None or len(md.identification.keywords) < 1:
- result["errors"].append("gmd:MD_Keywords: Keywords are missing")
- result["errors"].append("gmd:thesaurusName: Thesaurus Title is missing")
- result["errors"].append("gmd:thesaurusName: Thesaurus Date is missing")
- result["errors"].append("gmd:thesaurusName: Thesaurus Date Type is missing")
- errors += 4
- else:
- if md.identification.keywords[0]['keywords'] is None or len(md.identification.keywords[0]['keywords']) < 1 \
- or str(md.identification.keywords[0]['keywords']) == "[u'']":
- result["errors"].append("gmd:MD_Keywords: Keywords are missing")
- errors += 1
- if md.identification.keywords[0]['thesaurus'] is None:
- result["errors"].append("gmd:thesaurusName: Thesaurus Title is missing")
- result["errors"].append("gmd:thesaurusName: Thesaurus Date is missing")
- result["errors"].append("gmd:thesaurusName: Thesaurus Date Type is missing")
- errors += 3
- else:
- if md.identification.keywords[0]['thesaurus']['title'] is None \
- or len(md.identification.keywords[0]['thesaurus']['title']) < 1:
- result["errors"].append("gmd:thesaurusName: Thesaurus Title is missing")
- errors += 1
- if md.identification.keywords[0]['thesaurus']['date'] is None \
- or len(md.identification.keywords[0]['thesaurus']['date']) < 1:
- result["errors"].append("gmd:thesaurusName: Thesaurus Date is missing")
- errors += 1
- if md.identification.keywords[0]['thesaurus']['datetype'] is None \
- or len(md.identification.keywords[0]['thesaurus']['datetype']) < 1:
- result["errors"].append("gmd:thesaurusName: Thesaurus Date Type is missing")
- errors += 1
-
- if md.identification.extent is None:
- result["errors"].append("gmd:EX_Extent: extent element is missing")
- errors += 1
- else:
- if md.identification.extent.boundingBox is None:
- result["errors"].append(
- "gmd:EX_GeographicBoundingBox: bbox is missing")
- errors += 1
- else:
- if md.identification.extent.boundingBox.minx is (None or ''):
- result["errors"].append("gmd:westBoundLongitude: minx is missing")
- errors += 1
- if md.identification.extent.boundingBox.maxx is (None or ''):
- result["errors"].append("gmd:eastBoundLongitude: maxx is missing")
- errors += 1
- if md.identification.extent.boundingBox.miny is (None or ''):
- result["errors"].append("gmd:southBoundLatitude: miny is missing")
- errors += 1
- if md.identification.extent.boundingBox.maxy is (None or ''):
- result["errors"].append("gmd:northBoundLatitude: maxy is missing")
- errors += 1
-
- if len(md.identification.date) < 1 or (md.identification.temporalextent_start is (
- None or '') or md.identification.temporalextent_end is (None or '')):
- result["errors"].append("Both gmd:EX_TemporalExtent and gmd:CI_Date are missing")
- errors += 1
-
- if len(md.identification.uselimitation) < 1 or md.identification.uselimitation[0] == '':
- result["errors"].append("gmd:useLimitation is missing")
- errors += 1
- if len(md.identification.accessconstraints) < 1 or md.identification.accessconstraints[0] == '':
- result["errors"].append("gmd:accessConstraints is missing")
- errors += 1
- if len(md.identification.otherconstraints) < 1 or md.identification.otherconstraints[0] == '':
- result["errors"].append("gmd:otherConstraints is missing")
- errors += 1
-
- if md.languagecode is (None or ''):
- result["errors"].append("gmd:LanguageCode: Language code missing")
- errors += 1
- if md.datestamp is (None or ''):
- result["errors"].append("gmd:dateStamp: Date is missing")
- errors += 1
- if md.identifier is (None or ''):
- result["errors"].append("gmd:identifier: Identifier is missing")
- errors += 1
- if md.dataquality is (None or ''):
- result["errors"].append("gmd:LI_Lineage is missing")
- result["errors"].append("gmd:DQ_ConformanceResult: date is missing")
- result["errors"].append("gmd:DQ_ConformanceResult: date type is missing")
- # result["errors"].append("gmd:DQ_ConformanceResult: degree is missing")
- result["errors"].append("gmd:DQ_ConformanceResult: title is missing")
- errors += 4
- else:
-
- if md.dataquality.lineage is (None or ''):
- result["errors"].append("gmd:LI_Lineage is missing")
- errors += 1
- if len(md.dataquality.conformancedate) < 1 or md.dataquality.conformancedate[0] == '':
- result["errors"].append("gmd:DQ_ConformanceResult: date is missing")
- errors += 1
- if len(md.dataquality.conformancedatetype) < 1 or md.dataquality.conformancedatetype[0] == '':
- result["errors"].append("gmd:DQ_ConformanceResult: date type is missing")
- errors += 1
- # if len(md.dataquality.conformancedegree) < 1:
- # result["errors"].append("gmd:DQ_ConformanceResult: degree is missing")
- # errors += 1
- if len(md.dataquality.conformancetitle) < 1 or md.dataquality.conformancetitle[0] == '':
- result["errors"].append("gmd:DQ_ConformanceResult: title is missing")
- errors += 1
-
- if md.contact is None or len(md.contact) < 1:
- result["errors"].append("gmd:contact: Organization name is missing")
- result["errors"].append("gmd:contact: e-mail is missing")
- result["errors"].append("gmd:role: role is missing")
- errors += 3
- else:
-
- if md.contact[0].organization is (None or ''):
- result["errors"].append("gmd:contact: Organization name is missing")
- errors += 1
-
- if md.contact[0].email is (None or ''):
- result["errors"].append("gmd:contact: e-mail is missing")
- errors += 1
-
- if md.contact[0].role is (None or ''):
- result["errors"].append("gmd:role: role is missing")
- errors += 1
-
- if errors > 0:
- result["status"] = "failed"
- result["num_of_errors"] = str(errors)
-
- return result
Copied: grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso/r.info.iso.html (from rev 61594, grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso.html)
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso/r.info.iso.html (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso/r.info.iso.html 2014-08-13 20:15:41 UTC (rev 61595)
@@ -0,0 +1,5 @@
+<h2>DESCRIPTION</h2>
+Metadata creator according to EN ISO 19115 and EN ISO 19119
+<h2>AUTHOR</h2>
+
+Matej Krejci, Czech Technical University in Prague, Czech Republic
Copied: grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso/r.info.iso.py (from rev 61594, grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso.py)
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso/r.info.iso.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso/r.info.iso.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+# -*- coding: utf-8
+"""
+ at module r.info.iso
+ at brief Module for creating metadata based on ISO from raster maps
+
+(C) 2014 by 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.
+
+ at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
+"""
+#%option G_OPT_R_MAP
+#% key: map
+#% label: Name of input raster map
+#% required: yes
+#%end
+
+#%flag
+#% key: o
+#% label: Allow to overwrite exist metadata
+#%end
+
+#%option
+#% key: profil
+#% label: Metadata profil based on ISO
+#% description: INSPIRE profile is not filled properly (unknown values are filled '$NULL')
+#% options: basic, inspire
+#% answer: basic
+#%end
+
+#%option G_OPT_R_MAP
+#% key: mdout
+#% label: Name of output metadata file
+#% required: no
+#%end
+
+#%option G_OPT_M_DIR
+#% key: destination
+#% label: Path to destination folder
+#% required: no
+#%end
+
+from grass.script import parser
+from mdgrass import *
+
+
+def main():
+ if not options['destination']:
+ destination = None
+ else:
+ destination = options['destination']
+
+ if not options['mdout']:
+ mdout = None
+ else:
+ mdout = options['mdout']
+
+ md = GrassMD(options['map'], 'cell')
+ if options['profil'] == 'inspire':
+ md.createGrassInspireISO()
+ xml_file = md.saveXML(path=destination,
+ xml_out_name=mdout,
+ overwrite=flags['o'])
+ if xml_file is not False:
+ md.readXML(xml_file)
+ print md.validate_inspire()
+
+ else:
+ md.createGrassBasicISO()
+ xml_file = md.saveXML(path=destination,
+ xml_out_name=mdout,
+ overwrite=flags['o'])
+ if xml_file is not False:
+ md.readXML(xml_file)
+ print md.validate_basic()
+
+if __name__ == "__main__":
+ options, flags = parser()
+ main()
Deleted: grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso.html
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso.html 2014-08-13 15:54:00 UTC (rev 61594)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso.html 2014-08-13 20:15:41 UTC (rev 61595)
@@ -1,5 +0,0 @@
-<h2>DESCRIPTION</h2>
-Metadata creator according to EN ISO 19115 and EN ISO 19119
-<h2>AUTHOR</h2>
-
-Matej Krejci, Czech Technical University in Prague, Czech Republic
Deleted: grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso.py 2014-08-13 15:54:00 UTC (rev 61594)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/r.info.iso.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -1,80 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8
-"""
- at module r.info.iso
- at brief Module for creating metadata based on ISO from raster maps
-
-(C) 2014 by 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.
-
- at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
-"""
-#%option G_OPT_R_MAP
-#% key: map
-#% label: Name of input raster map
-#% required: yes
-#%end
-
-#%flag
-#% key: o
-#% label: Allow to overwrite exist metadata
-#%end
-
-#%option
-#% key: profil
-#% label: Metadata profil based on ISO
-#% description: INSPIRE profile is not filled properly (unknown values are filled '$NULL')
-#% options: basic, inspire
-#% answer: basic
-#%end
-
-#%option G_OPT_R_MAP
-#% key: mdout
-#% label: Name of output metadata file
-#% required: no
-#%end
-
-#%option G_OPT_M_DIR
-#% key: destination
-#% label: Path to destination folder
-#% required: no
-#%end
-
-from grass.script import parser
-from mdgrass import *
-
-
-def main():
- if not options['destination']:
- destination = None
- else:
- destination = options['destination']
-
- if not options['mdout']:
- mdout = None
- else:
- mdout = options['mdout']
-
- md = GrassMD(options['map'], 'cell')
- if options['profil'] == 'inspire':
- md.createGrassInspireISO()
- xml_file = md.saveXML(path=destination,
- xml_out_name=mdout,
- overwrite=flags['o'])
- if xml_file is not False:
- md.readXML(xml_file)
- print md.validate_inspire()
-
- else:
- md.createGrassBasicISO()
- xml_file = md.saveXML(path=destination,
- xml_out_name=mdout,
- overwrite=flags['o'])
- if xml_file is not False:
- md.readXML(xml_file)
- print md.validate_basic()
-
-if __name__ == "__main__":
- options, flags = parser()
- main()
Copied: grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso/v.info.iso.html (from rev 61594, grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso.html)
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso/v.info.iso.html (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso/v.info.iso.html 2014-08-13 20:15:41 UTC (rev 61595)
@@ -0,0 +1,5 @@
+<h2>DESCRIPTION</h2>
+Metadata creator according to EN ISO 19115 and EN ISO 19119
+<h2>AUTHOR</h2>
+
+Matej Krejci, Czech Technical University in Prague, Czech Republic
Copied: grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso/v.info.iso.py (from rev 61594, grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso.py)
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso/v.info.iso.py (rev 0)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso/v.info.iso.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+# -*- coding: utf-8
+"""
+ at module v.info.iso
+ at brief Module for creating metadata based on ISO from vector maps
+
+(C) 2014 by 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.
+
+ at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
+"""
+#%option G_OPT_V_MAP
+#% key: map
+#% label: Name of input vector map
+#% required: yes
+#%end
+
+#%flag
+#% key: o
+#% label: Allow to overwrite exist metadata
+#%end
+
+#%option
+#% key: profil
+#% label: Metadata profil based on ISO
+#% description: INSPIRE profile is not filled properly (unknown values are filled '$NULL')
+#% options: basic, inspire
+#% answer: basic
+#%end
+
+#%option G_OPT_V_MAP
+#% key: mdout
+#% label: Name of output metadata file
+#% required: no
+#%end
+
+#%option G_OPT_M_DIR
+#% key: destination
+#% label: Path to destination folder
+#% required: no
+#%end
+
+from grass.script import parser
+from mdgrass import *
+
+
+def main():
+ if not options['destination']:
+ destination = None
+ else:
+ destination = options['destination']
+
+ if not options['mdout']:
+ mdout = None
+ else:
+ mdout = options['mdout']
+
+ md = GrassMD(options['map'], 'vector')
+ if options['profil'] == 'inspire':
+ md.createGrassInspireISO()
+ xml_file = md.saveXML(path=destination,
+ xml_out_name=mdout,
+ overwrite=flags['o'])
+ if xml_file is not False:
+ md.readXML(xml_file)
+ print md.validate_inspire()
+
+ else:
+ md.createGrassBasicISO()
+ xml_file = md.saveXML(path=destination,
+ xml_out_name=mdout,
+ overwrite=flags['o'])
+ if xml_file is not False:
+ md.readXML(xml_file)
+ print md.validate_basic()
+
+if __name__ == "__main__":
+ options, flags = parser()
+ main()
Deleted: grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso.html
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso.html 2014-08-13 15:54:00 UTC (rev 61594)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso.html 2014-08-13 20:15:41 UTC (rev 61595)
@@ -1,5 +0,0 @@
-<h2>DESCRIPTION</h2>
-Metadata creator according to EN ISO 19115 and EN ISO 19119
-<h2>AUTHOR</h2>
-
-Matej Krejci, Czech Technical University in Prague, Czech Republic
Deleted: grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso.py
===================================================================
--- grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso.py 2014-08-13 15:54:00 UTC (rev 61594)
+++ grass-addons/grass7/gui/wxpython/wx.metadata/v.info.iso.py 2014-08-13 20:15:41 UTC (rev 61595)
@@ -1,80 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8
-"""
- at module v.info.iso
- at brief Module for creating metadata based on ISO from vector maps
-
-(C) 2014 by 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.
-
- at author Matej Krejci <matejkrejci gmail.com> (GSoC 2014)
-"""
-#%option G_OPT_V_MAP
-#% key: map
-#% label: Name of input vector map
-#% required: yes
-#%end
-
-#%flag
-#% key: o
-#% label: Allow to overwrite exist metadata
-#%end
-
-#%option
-#% key: profil
-#% label: Metadata profil based on ISO
-#% description: INSPIRE profile is not filled properly (unknown values are filled '$NULL')
-#% options: basic, inspire
-#% answer: basic
-#%end
-
-#%option G_OPT_V_MAP
-#% key: mdout
-#% label: Name of output metadata file
-#% required: no
-#%end
-
-#%option G_OPT_M_DIR
-#% key: destination
-#% label: Path to destination folder
-#% required: no
-#%end
-
-from grass.script import parser
-from mdgrass import *
-
-
-def main():
- if not options['destination']:
- destination = None
- else:
- destination = options['destination']
-
- if not options['mdout']:
- mdout = None
- else:
- mdout = options['mdout']
-
- md = GrassMD(options['map'], 'vector')
- if options['profil'] == 'inspire':
- md.createGrassInspireISO()
- xml_file = md.saveXML(path=destination,
- xml_out_name=mdout,
- overwrite=flags['o'])
- if xml_file is not False:
- md.readXML(xml_file)
- print md.validate_inspire()
-
- else:
- md.createGrassBasicISO()
- xml_file = md.saveXML(path=destination,
- xml_out_name=mdout,
- overwrite=flags['o'])
- if xml_file is not False:
- md.readXML(xml_file)
- print md.validate_basic()
-
-if __name__ == "__main__":
- options, flags = parser()
- main()
More information about the grass-commit
mailing list