[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