Change-Id: If95cb839ad81ca2a842ff7f6926847ac3928d8f2 Former-commit-id: 77e1a4d8f5237e5fae930c1e00589c752f8b3738
385 lines
14 KiB
Python
385 lines
14 KiB
Python
##
|
|
# This software was developed and / or modified by Raytheon Company,
|
|
# pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
|
#
|
|
# U.S. EXPORT CONTROLLED TECHNICAL DATA
|
|
# This software product contains export-restricted data whose
|
|
# export/transfer/disclosure is restricted by U.S. law. Dissemination
|
|
# to non-U.S. persons whether in the United States or abroad requires
|
|
# an export license or other authorization.
|
|
#
|
|
# Contractor Name: Raytheon Company
|
|
# Contractor Address: 6825 Pine Street, Suite 340
|
|
# Mail Stop B8
|
|
# Omaha, NE 68106
|
|
# 402.291.0100
|
|
#
|
|
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
|
# further licensing information.
|
|
##
|
|
#
|
|
# Name:
|
|
# ProductDialog.py
|
|
# GFS1-NHD:A8056.0000-SCRIPT;13
|
|
#
|
|
# Status:
|
|
# $TO_BE_DEFINED
|
|
#
|
|
# History:
|
|
# Revision 12 (DELIVERED)
|
|
# Created: 01-JUN-2006 08:37:50 TROJAN
|
|
# spr 7157 - errors when adding new product
|
|
#
|
|
# Revision 11 (REVIEW)
|
|
# Created: 01-JUN-2006 08:34:30 TROJAN
|
|
# spr 7156 - errors when adding new product
|
|
#
|
|
# Revision 10 (DELIVERED)
|
|
# Created: 23-MAR-2006 15:14:14 TROJAN
|
|
# spr 7109 - modified method to determine work PIL
|
|
#
|
|
# Revision 9 (DELIVERED)
|
|
# Created: 22-MAR-2006 13:05:17 TROJAN
|
|
# spr 7110. Revised TAF handling for consistency
|
|
#
|
|
# Revision 8 (DELIVERED)
|
|
# Created: 29-JAN-2006 12:25:33 TROJAN
|
|
# spr 7083
|
|
#
|
|
# Revision 7 (DELIVERED)
|
|
# Created: 06-JUL-2005 20:50:38 TROJAN
|
|
# spr 6910
|
|
#
|
|
# Revision 6 (DELIVERED)
|
|
# Created: 01-JUN-2005 17:41:18 OBERFIEL
|
|
# Bug fixes since RHE3 initial snapshot
|
|
#
|
|
# Revision 5 (DELIVERED)
|
|
# Created: 07-MAY-2005 11:37:00 OBERFIEL
|
|
# Added Item Header Block
|
|
#
|
|
# Revision 4 (DELIVERED)
|
|
# Created: 18-APR-2005 17:32:17 OBERFIEL
|
|
# Changes to support gamin
|
|
#
|
|
# Revision 3 (DELIVERED)
|
|
# Created: 28-FEB-2005 19:42:40 TROJAN
|
|
# spr 6284
|
|
#
|
|
# Revision 2 (APPROVED)
|
|
# Created: 28-FEB-2005 19:04:55 TROJAN
|
|
# spr 6685
|
|
#
|
|
# Revision 1 (BUILD_RELEASE)
|
|
# Created: 30-SEP-2004 18:17:38 TROJAN
|
|
# rewrite of avnsetup
|
|
#
|
|
# Change Document History:
|
|
# 1:
|
|
# Change Document: GFS1-NHD_SPR_7407
|
|
# Action Date: 29-SEP-2008 15:38:12
|
|
# Relationship Type: In Response to
|
|
# Status: UNDER WORK
|
|
# Title: AvnFPS: Allow WFOs to update HDF5 climate files
|
|
#
|
|
#
|
|
# ProductDialog.py
|
|
# Aviation setup editor
|
|
# Author: George Trojan, SAIC/MDL, September 2004
|
|
# last update: 06/01/06
|
|
|
|
import logging, os
|
|
import ConfigParser
|
|
from Tkinter import *
|
|
import Pmw
|
|
from Balloon import Balloon
|
|
import Avn, AvnDialog, AvnParser, Busy
|
|
|
|
_Help = {
|
|
'title': 'Route Setup Help',
|
|
'content': """
|
|
This dialog is used to define TAF/TWEB product (list of forecasts).
|
|
|
|
Thee products should be defined AFTER relevant site/route configuration
|
|
files have been created.
|
|
|
|
To add a new product, enter product label in the "Products" entry
|
|
field and press <Enter>. Then enter all TAF ids or TWEB routes in
|
|
the "Idents" entry field, press <Enter> after typing one item.
|
|
Press "Save" button to save configuration file.
|
|
|
|
To remove a product, press "Delede" below "Products" list.
|
|
|
|
To remove an ident from the product definition, use "Delete"
|
|
button in the "Idents" column. You must then save the product.
|
|
This will NOT delete TAF/TWEB configuration files, this can only be
|
|
done from the command line.
|
|
|
|
The "Verify" button can be used to check for existence and proper
|
|
syntax of all relevant files.
|
|
"""
|
|
}
|
|
|
|
_Logger = logging.getLogger(__name__)
|
|
|
|
##############################################################################
|
|
class _Editor(AvnDialog.Dialog):
|
|
Key = ''
|
|
def __init__(self, parent, **kw):
|
|
AvnDialog.Dialog.__init__(self, parent, **kw)
|
|
|
|
# from AvnDialog
|
|
self.createMessageBar(self.interior(), True)
|
|
|
|
frame = Frame(self.interior())
|
|
self.products = Pmw.ComboBox(frame,
|
|
label_text='Products',
|
|
labelpos='n',
|
|
dropdown=0,
|
|
scrolledlist_vscrollmode='static',
|
|
listbox_width=16,
|
|
entryfield_entry_width=16,
|
|
listbox_exportselection=0,
|
|
selectioncommand=self.listIdents,
|
|
)
|
|
self.products.grid(row=0, column=0, sticky='news')
|
|
btn = Button(frame, text='Delete', command=self.__deleteProduct)
|
|
btn.grid(row=1, column=0, sticky='news')
|
|
frame.grid_rowconfigure(0, weight=1)
|
|
frame.grid_rowconfigure(1, weight=0)
|
|
frame.pack(side='left', expand='yes', fill='both')
|
|
frame = Frame(self.interior())
|
|
self.idents = Pmw.ComboBox(frame,
|
|
label_text='Idents',
|
|
labelpos='n',
|
|
dropdown=0,
|
|
scrolledlist_vscrollmode='static',
|
|
listbox_width=4,
|
|
entryfield_entry_width=4,
|
|
listbox_exportselection=0,
|
|
)
|
|
self.idents.grid(row=0, column=0, sticky='news')
|
|
btn = Button(frame, text='Delete', command=self.__deleteIdent)
|
|
btn.grid(row=1, column=0, sticky='news')
|
|
Balloon().bind(btn, 'Delete selected id from list')
|
|
frame.grid_rowconfigure(0, weight=1)
|
|
frame.grid_rowconfigure(1, weight=0)
|
|
frame.pack(side='left', expand='yes', fill='both', padx=5)
|
|
bbox = Pmw.ButtonBox(self.interior(),
|
|
orient='vertical',
|
|
hull_borderwidth=2,
|
|
hull_relief='groove',
|
|
pady=1,
|
|
)
|
|
btn = bbox.add('Save', command=self.__save)
|
|
Balloon().bind(btn, 'Saves route info to a file')
|
|
btn = bbox.add('Verify', command=self.verify)
|
|
Balloon().bind(btn, 'Verifies existence of all relevant files')
|
|
btn = bbox.add('Default', command=self.__setDefault)
|
|
Balloon().bind(btn, 'Makes selected product default one')
|
|
btn = bbox.add('Close', command=self.close)
|
|
Balloon().bind(btn, 'Closes this dialog')
|
|
btn = bbox.add('Help', command=Avn.curry(self.showHelp, _Help))
|
|
Balloon().bind(btn, 'Shows help')
|
|
bbox.alignbuttons()
|
|
bbox.pack(side='top', expand='no')
|
|
self.pil = Pmw.EntryField(self.interior(),
|
|
labelpos='n',
|
|
label_text='Work PIL',
|
|
entry_width=9,
|
|
validate={'validator': 'alphabetic', 'minstrict': 0, \
|
|
'min': 8, 'max': 9}
|
|
)
|
|
self.pil.pack(side='top', expand='no')
|
|
|
|
self.initialiseoptions(_Editor)
|
|
self.setGeometry()
|
|
|
|
def __deleteIdent(self):
|
|
self.messagebar().resetmessages('systemerror')
|
|
try:
|
|
self.idents.delete('active')
|
|
except IndexError:
|
|
self.messagebar().message('usererror', 'Select ident to delete')
|
|
return
|
|
|
|
def __deleteProduct(self):
|
|
self.messagebar().resetmessages('systemerror')
|
|
try:
|
|
item = self.products.getcurselection()[0]
|
|
path = os.path.join('etc', self.Key, item+'.cfg')
|
|
if not Busy.askokcancel('This will remove file %s' % \
|
|
path + '\nAre you sure?', self.interior()):
|
|
return
|
|
os.unlink(path)
|
|
self.products.delete('active')
|
|
msg = 'Deleted %s' % os.path.basename(path)
|
|
_Logger.info(msg)
|
|
self.messagebar().message('userevent', msg)
|
|
except IndexError:
|
|
self.messagebar().message('usererror', 'Select product to delete')
|
|
except Exception:
|
|
msg = 'Cannot delete %s' % os.path.basename(path)
|
|
_Logger.exception(msg)
|
|
self.messagebar().message('systemerror', msg)
|
|
|
|
def __setDefault(self):
|
|
self.messagebar().resetmessages('systemerror')
|
|
try:
|
|
item = self.products.getcurselection()[0]
|
|
file(os.path.join('etc', self.Key, 'DEFAULT'), 'w').write(item+'\n')
|
|
products = list(self.products.get(0, 'end'))
|
|
products.remove(item)
|
|
products.sort()
|
|
products.insert(0, item)
|
|
self.products.setlist(products)
|
|
except IndexError:
|
|
self.messagebar().message('usererror',
|
|
'Select product to mark as default')
|
|
except IOError:
|
|
msg = 'Cannot write DEFAULT file'
|
|
_Logger.exception(msg)
|
|
self.messagebar().message('systemerror', msg)
|
|
|
|
def __save(self):
|
|
self.messagebar().resetmessages('systemerror')
|
|
try:
|
|
product = self.products.getcurselection()[0]
|
|
idents = [i.upper() for i in self.idents.get(0, 'end')]
|
|
if self.pil.valid():
|
|
pil = self.pil.get().strip().upper()
|
|
else:
|
|
Busy.showerror('Invalid Work PIL', self.interior())
|
|
return
|
|
path = os.path.join('etc', self.Key, product+'.cfg')
|
|
cp = ConfigParser.ConfigParser()
|
|
cp.add_section('sites')
|
|
cp.set('sites', 'idents', ','.join(idents))
|
|
cp.set('sites', 'workpil', pil)
|
|
try:
|
|
if not os.path.exists(os.path.dirname(path)):
|
|
os.mkdir(os.path.dirname(path))
|
|
fp = file(path, 'w')
|
|
fp.write('# %s\n\n' % path)
|
|
cp.write(fp)
|
|
finally:
|
|
fp.close()
|
|
msg = 'Updated %s' % path
|
|
self.messagebar().message('systemevent', msg)
|
|
except IndexError:
|
|
self.messagebar().message('usererror', 'Select product to save')
|
|
except Exception:
|
|
msg = 'Failed to update %s' % path
|
|
_Logger.exception(msg)
|
|
|
|
##############################################################################
|
|
class TafEditor(_Editor):
|
|
Key = 'tafs'
|
|
def __init__(self, parent, **kw):
|
|
_Editor.__init__(self, parent, **kw)
|
|
self.title(Avn.Name + ' TAF Product Configuration')
|
|
|
|
def verify(self):
|
|
self.messagebar().resetmessages('systemerror')
|
|
try:
|
|
product = self.products.getcurselection()[0]
|
|
cfg = AvnParser.getTafProductCfg(product)
|
|
if not cfg:
|
|
raise Avn.AvnError('Cannot parse product definition file')
|
|
idents = cfg.get('sites', [])
|
|
for i in idents:
|
|
if not AvnParser.getTafSiteCfg(i):
|
|
raise Avn.AvnError('Cannot parse %s info file' % i)
|
|
for h in [0, 6, 12, 18]:
|
|
try:
|
|
AvnParser.getTafTemplate(i, h)
|
|
except IOError:
|
|
raise Avn.AvnError('Cannot read %s %02dZ template' % \
|
|
(i, h))
|
|
self.messagebar().message('userevent', 'Verify succeeded')
|
|
except IndexError:
|
|
self.messagebar().message('usererror', 'Select product to verify')
|
|
except Avn.AvnError, e:
|
|
self.messagebar().message('usererror', str(e))
|
|
|
|
def listIdents(self, product):
|
|
self.messagebar().resetmessages('systemerror')
|
|
cfg = AvnParser.getTafProductCfg(product)
|
|
if cfg:
|
|
idents = cfg.get('sites', [])
|
|
pil = cfg.get('workpil')
|
|
self.idents.setlist(idents)
|
|
if pil is None:
|
|
pil = Avn.TAFWorkPIL
|
|
self.pil.setvalue(pil)
|
|
else:
|
|
self.idents.clear()
|
|
self.pil.clear()
|
|
msg = 'Cannot read product %s' % product
|
|
self.messagebar().message('usererror', msg)
|
|
|
|
def listProducts(self):
|
|
self.messagebar().resetmessages('systemerror')
|
|
products = AvnParser.getTafProducts()
|
|
if products:
|
|
self.products.setlist(products)
|
|
self.products.selectitem(0)
|
|
self.products.invoke()
|
|
else:
|
|
self.products.clear()
|
|
self.messagebar().message('usererror', 'Empty product list')
|
|
|
|
##############################################################################
|
|
class TwbEditor(_Editor):
|
|
Key = 'twbs'
|
|
def __init__(self, parent, **kw):
|
|
_Editor.__init__(self, parent, **kw)
|
|
self.title(Avn.Name + ' TWEB Product Configuration')
|
|
|
|
def verify(self):
|
|
self.messagebar().resetmessages('systemerror')
|
|
try:
|
|
product = self.products.getcurselection()[0]
|
|
cfg = AvnParser.getTwbProductCfg(product)
|
|
if not cfg:
|
|
raise Avn.AvnError('Cannot parse product definition')
|
|
idents = cfg.get('sites', [])
|
|
for i in idents:
|
|
if not AvnParser.getTwbSiteCfg(i):
|
|
raise Avn.AvnError('Cannot parse %s info file' % i)
|
|
try:
|
|
AvnParser.getTwbTemplate(i)
|
|
except IOError:
|
|
raise Avn.AvnError('Cannot read %s template' % i)
|
|
self.messagebar().message('userevent', 'Verify succeeded')
|
|
except IndexError:
|
|
self.messagebar().message('usererror', 'Select product to verify')
|
|
except Avn.AvnError, e:
|
|
self.messagebar().message('usererror', str(e))
|
|
|
|
def listIdents(self, product):
|
|
self.messagebar().resetmessages('systemerror')
|
|
cfg = AvnParser.getTwbProductCfg(product)
|
|
if cfg:
|
|
idents = cfg.get('sites', [])
|
|
pil = cfg.get('workpil')
|
|
self.idents.setlist(idents)
|
|
if pil is None:
|
|
pil = Avn.TWBWorkPIL
|
|
self.pil.setvalue(pil)
|
|
else:
|
|
self.idents.clear()
|
|
self.pil.clear()
|
|
msg = 'Cannot read product %s' % product
|
|
self.messagebar().message('usererror', msg)
|
|
|
|
def listProducts(self):
|
|
self.messagebar().resetmessages('systemerror')
|
|
products = AvnParser.getTwbProducts()
|
|
if products:
|
|
self.products.setlist(products)
|
|
self.products.selectitem(0)
|
|
self.products.invoke()
|
|
else:
|
|
self.products.clear()
|
|
self.messagebar().message('usererror', 'Empty product list')
|