#!/usr/bin/env python
#############################################################################
##
## This file is part of Taurus, a Tango User Interface Library
##
## http://www.tango-controls.org/static/taurus/latest/doc/html/index.html
##
## Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
##
## Taurus is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## Taurus is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public License
## along with Taurus. If not, see <http://www.gnu.org/licenses/>.
##
###########################################################################
"""
TaurusGUI configuration file used to convert Taurus into VACCA
This file should be NOT modified.
.. toctree::
:maxdepth: 4
h2. Usage
=========
This configuration file determines the default, permanent, pre-defined
contents of the GUI. While the user may add/remove more elements at run
time and those customizations will also be stored, this file defines what a
user will find when launching the GUI for the first time.
Don't modify this file, use default.py to do a simple setup of your
facility and paths and a CONFIG.py file (based on default.py format) to
construct a VACCA gui for each subsystem.
h3. Contents
------------
This file mainly defines two kinds of objects:
* Panel descriptors: the panels to be shown.
To define a panel, instantiate a PanelDescription object (see documentation
for the gblgui_utils module)
* Panels will be TREE, JDRAW_FILE, DEVICE, ...
* QSignals (managed by Taurus Shared Data Manager):
* SelectedInstrument: goes from taurusgui and tree into panel/synoptic
* SelectionMultiple: goes from panic/finder/... to synoptic to display multiple elements
* JDrawIn/JDrawOut: used only if JDRAW_HOOK defined, to transform data between synoptic and selection
* lastWindowClosed: signal will close all opened widgets and dialogs on application exit
h3. Extending Taurus GUI
------------------------
We will differentiate between:
- Tools (applications launched in a separate process)
- Panels (widgets embeddable in the application)
- Applets (widgets or applications launched from the right-side bar)
- Widgets (widgets not instantiated, but added to the catalog when adding a new panel).
The config variables to include new Tools/Panels/Apps/Widgets are:
Use EXTRA_WIDGETS to add new widgets to the catalog and the right-side toolbar.
They will be added to EXTRA_CATALOG_WIDGETS, that contains default extra widgets.
Use EXTRA_PANELS to force new Panels always at startup.
They will be instantiated and running in background.
Use EXTRA_APPS to add launchers to the toolbar.
Creates new AppletDescription objects to add elements to the right-side toolbar.
Use EXTRA_TOOLS to add launchers to the "External Apps" toolbar.
Creates new ExternalApp objects to add elements to the top menu and toolbar.
Use TOOLBARS to add new Toolbars:
TOOLBARS = [('Sectors','SR.sector.get_sectors_toolbar')]
Creates new ToolBarDescription objects.
h2. Config Variables
====================
Described below. All of them can be overriden in TangoDB(VACCA free properties) or
using environment variables (adding the VACCA_ preffix).
"""
#==============================================================================
# Import section. You probably want to keep this line. Don't edit this block
# unless you know what you are doing
import time,os,sys,traceback,imp,inspect
from PyQt4.QtCore import SIGNAL
import fandango as fn,taurus
import vacca,vacca.utils
from .doc import get_autodoc,get_vars_docs
from fandango import partial,FakeLogger as FL
from taurus.qt import Qt
from taurus.qt.qtgui.taurusgui.utils import \
PanelDescription, ExternalApp, ToolBarDescription, AppletDescription
from vacca.panel import VaccaAction,VaccaSplash
from vacca.utils import *
# (end of import section)
#==============================================================================
VACCA_CONFIG = os.getenv('VACCA_CONFIG')
PROPS = get_config_properties(VACCA_CONFIG)
VACCA_DIR = WDIR = PROPS.get('VACCA_DIR',VACCA_DIR)
print('-'*80)
print('In vacca.config(%s,%s)'%(globals().get('CONFIG_DONE',None),VACCA_DIR))
try:
if VACCA_DIR:
print('Changing directory to VACCA_DIR:%s' %(VACCA_DIR))
os.chdir(os.environ['VACCA_DIR'])
sys.path.append(os.environ['VACCA_DIR'])
try:
app = Qt.QApplication.instance()
assert app,'QApplication not running!'
splash = VaccaSplash()
except:
print("QApplication Instance do not exist!")
app = None
try:
import default
except:
try:
default = get_config_file(imp.find_module('vacca')[1]+'/default.py')
except:
traceback.print_exc()
#===============================================================================
# Loading of Config Files
#===============================================================================
#: Config file where perspectives will be saved
SETTINGS = '/home/$USER/.config/$ORGANIZATION/$GUI_NAME'
#: Default options are set in default.py file and later customized in a config file.
#: This CONFIG can be a .py file passed as argument or a TANGO_HOST.py file in
#: vacca folder.
CONFIG = get_config_file()
#: ALL Variables that can be defined in CONFIG FILE
OPTION_LISTS = [
('General Info', ['GUI_NAME','URL_HELP','URL_LOGBOOK','VACCA_LOGO','ORGANIZATION','ORGANIZATION_LOGO',]),
('Installation', ['WDIR','SETTINGS']),
('Sub systems', ['DOMAIN','TARGET','COMPOSER',]),
('Device Tree', ['USE_DEVICE_TREE','CUSTOM_TREE','EXTRA_DEVICES',]),
('Synoptics', ['JDRAW_FILE','JDRAW_TREE','JDRAW_HOOK','GRID',]),
('Device Panel', ['USE_DEVICE_PANEL','DEVICE','PANEL_COMMAND','AttributeFilters','CommandFilters','IconMap',]),
('Plot', ['GAUGES']),
('Widgets', ['EXTRA_WIDGETS','EXTRA_PANELS','TOOLBARS','MENUS','EXTRA_APPS','EXTRA_CATALOG_WIDGETS']),]
OPTIONS = [o for c,l in OPTION_LISTS for o in l]
for c,l in OPTION_LISTS:
__doc__ += get_vars_docs(__name__,title=c+' Options',module_vars=l,subtitle=False)
if CONFIG:
print('\n%s Config Options:\n'%VACCA_CONFIG)
for op in OPTIONS:
limit = 800
if 'VACCA_'+op in os.environ:
print('%s.%s overriden by OS'%(VACCA_CONFIG,op))
setattr(CONFIG,op,os.getenv('VACCA_'+op))
elif op in PROPS:
print('%s.%s overriden by TangoDB'%(VACCA_CONFIG,op))
setattr(CONFIG,op,PROPS[op])
if hasattr(CONFIG,op):
v = getattr(CONFIG,op)
print('\t%s: \t%s = %s'%(CONFIG.__name__,op,str(v).replace('\n',',')[:limit]))
setattr(default,op,v)
if not getattr(CONFIG,'DEVICE',None) and getattr(CONFIG,'COMPOSER',None):
default.DEVICE = default.COMPOSER
#Adding all variables to Namespace where taurusgui can found them
try:
for k,v in vars(default).items():
if not any((k.startswith('_'),inspect.ismodule(v))): #inspect.isfunction(v)
vars()[k] = v
except:
traceback.print_exc()
#===============================================================================
# General info.
#===============================================================================
#: GUI_NAME will be used on application title and settings filenames
GUI_NAME = '%s-%s-%s'%(GUI_NAME,VACCA_CONFIG.split('/')[-1].split('.')[0],DB_HOST)
#: Name to be shown in right-side bar
ORGANIZATION = ORGANIZATION
#: Logo to be shown in right-side bar
ORGANIZATION_LOGO = ORGANIZATION_LOGO
print('\nConfig loaded, Perspectives will be saved/loaded from %s'%(
SETTINGS.replace('$USER',get_env_variable('USER')
).replace('$ORGANIZATION',ORGANIZATION
).replace('$GUI_NAME',GUI_NAME)))
SINGLE_INSTANCE = False
#: CUSTOM_LOGO. It can be an absolute path,or relative to the app dir or a
#: resource path. If commented out, ":/taurus.png" will be used
CUSTOM_LOGO = VACCA_LOGO
#: You can provide an URI for a manual in html format
#: (comment out or make MANUAL_URI=None to skip creating a Manual panel)
MANUAL_URI = URL_HELP #'http://packages.python.org/taurus'
print('\n'+'#'*80+'\n')
print('In vacca.config(%s): loading classes\n'%VACCA_CONFIG)
#===============================================================================
# Define panels to be shown.
# To define a panel, instantiate a PanelDescription object (see documentation
# for the gblgui_utils module)
#===============================================================================
print('\t>>> Loading Trend panel ... %s'%','.join(GAUGES))
#: If defined, the default trend will be shown in logarithmic scale
GAUGES=GAUGES
if GAUGES:
trend = PanelDescription('Gauges',
classname = 'vacca.plot.PressureTrend',
model = GAUGES)
trends = PanelDescription('Trends',
classname = 'vacca.plot.VaccaTrend',
model = '')
#: USE_DEVICE_TREE: True or False, To Show by default the Device_Tree
USE_DEVICE_TREE = USE_DEVICE_TREE
if USE_DEVICE_TREE or JDRAW_FILE or EXTRA_DEVICES:
print('\t>>> Loading Tree panel(%s) ...'%(len(EXTRA_DEVICES)))
from tree import *
try:
# The lastWindowClosed() signal will close all opened widgets and dialogs on application exit
assert Qt.QApplication.instance(),'QApplication not running!'
panelclass = VaccaAction(default=PANEL_COMMAND)
Qt.QObject.connect(Qt.QApplication.instance(), Qt.SIGNAL(
"lastWindowClosed()"), panelclass.kill )
VaccaTree.setDefaultPanelClass(panelclass)
except:
print("Cannot instance Device Tree")
logger = fn.Logger()
printf = logger.info
[docs] def filterMatching(a,dct=AttributeFilters,p=printf):
match = False
if a.lower().endswith('/state'): return True
elif a.lower().endswith('/status'): return False
for k,l in dct.items():
if fn.searchCl(k,a.rsplit('/',1)[0]):
for t in l: #T is every declared Tab for panel (TabName,[attrlist]); or just attrname when not using tabs
p((k,t))
f = t[-1] if all(map(fn.isSequence,(t,t[-1]))) else [t]
if any(fn.matchCl(v,a.rsplit('/',1)[-1]) for v in f):
match =True
return match
VaccaTree.setDefaultAttrFilter(filterMatching)
if IconMap: VaccaTree.setIconMap(IconMap)
if fn.isString(EXTRA_DEVICES):
EXTRA_DEVICES = fn.join((s.split(',') if ',' in s else fn.get_matching_devices(s)) for s in EXTRA_DEVICES.split())
EXTRA_DEVICES = sorted(set(map(str.lower,filter(bool,[DEVICE]+list(EXTRA_DEVICES)))))
tree = PanelDescription('Tree',
classname = 'vacca.VaccaTree',#'vacca.VaccaTree',#'TaurusDevTree',
model = CUSTOM_TREE or ','.join(EXTRA_DEVICES),
sharedDataRead={'LoadItems':'addModels',
##DISABLED BECAUSE TRIGGERED RECURSIVE SELECTION, TO BE AVOIDED IN TREE
#'SelectedInstrument':'findInTree',
}, #It will load devices from synoptic
sharedDataWrite={'SelectedInstrument':'deviceSelected(QString)'}
)
if EXTRA_DEVICES and not DEVICE: DEVICE = EXTRA_DEVICES[0]
#: USE_DEVICE_PANEL: True or False, To Show by default the DevicePanel
USE_DEVICE_PANEL = USE_DEVICE_PANEL
if USE_DEVICE_PANEL:
print('\t>>> Loading Device panel (%s)...' % DEVICE)
from vacca.panel import VaccaPanel
panel = VaccaPanel.getPanelDescription('Device',model=DEVICE or None)
from vacca.panel import VaccaPanel
if AttributeFilters: VaccaPanel.setAttributeFilters(AttributeFilters)
if IconMap: VaccaPanel.setIconMap(IconMap)
if CommandFilters: VaccaPanel.setCommandFilters(CommandFilters)
#: JDRAW_FILE: The JDRAW file to create the Synoptic,
#: it can be .jdw or .svg but the second option will require the svgsynoptic module from maxlab.
JDRAW_FILE = JDRAW_FILE
if JDRAW_FILE:
print('\t>>> Loading Synoptic panel new ... %s, %s, %s'%(JDRAW_FILE,
JDRAW_HOOK, JDRAW_TREE))
from vacca.synoptics import VaccaSynoptic
try:
synoptic = VaccaSynoptic.getPanelDescription('Synoptic',JDRAW_FILE,JDRAW_HOOK,JDRAW_TREE)
except:
traceback.print_exc()
sys.exit()
#: GRID: True/False to show by default ehe GRID Panel.
GRID = GRID
if GRID:
print('\t>>> Loading Grid panels ...')
GRID['frames'] = False
GRID['labels'] = False
GRID['units'] = False
from vacca.grid import VaccaGrid, VaccaVerticalGrid
try:
assert Qt.QApplication.instance(),'QApplication not running!'
grid = VaccaGrid.getGridPanelDescription(GRID)
except:
print('\t>>> Unable to create Grid')
##VGRID disabled, the Vertical layout should be added as option to common GRID
#try:
#assert Qt.QApplication.instance(),'QApplication not running!'
#vgrid = VaccaVerticalGrid.getVerticalGridPanelDescription(GRID)
#except:
#print 'Unable to create VerticalGrid'
#: COMPOSER: True/False to show by default the COMPOSER Panel.
COMPOSER = COMPOSER
if COMPOSER:
def VacuumProfile():
print('\t>>> Loading VacuumProfile()')
from . import plot
p = plot.VaccaProfilePlot()
p.setModel(COMPOSER)
return p
try:
print('\t>>> Loading Profile panel ...')
profile = PanelDescription('Profile',
classname = 'vacca.plot.VaccaProfilePlot',
model = COMPOSER,
)
except:
print('\t>>> Unable to create ProfilePlot')
import vacca.properties
properties = vacca.properties.VaccaPropTable.getPanelDescription('Properties',model=DEVICE or '')
#: EXTRA_PANELS: dictionary of Extra Panels to be shown by default.
#: Each element may be a PanelDescription object or a tuple with its arguments.
#:
#: The dictionary will be defined like:
#: * key: Panel name
#: * value: list of arguments to PanelDescription
#: * value[0]: panel name
#: * value[1]: class name
#: * value[2]: default model
#: * value[3]: shared data read signal
#: * value[4]: shared data write signal
#:
#: As example, to add PANIC as extra panel use:
#: EXTRA_PANELS['PANIC'] = ('PANIC','panic.gui.AlarmGUI','',{},{'HighlightInstruments':'devicesSelected'})
EXTRA_PANELS = EXTRA_PANELS
if EXTRA_PANELS:
print('\t>>> Loading Extra panels ... %s'%str(EXTRA_PANELS))
if not hasattr(EXTRA_PANELS,'items'):
EXTRA_PANELS = dict(('extra%d'%(i+1),p) for i,p in enumerate(EXTRA_PANELS))
def get_panel(i):
pargs = EXTRA_PANELS[i]
if not fn.isSequence(pargs): return pargs
elif len(pargs)==3: return PanelDescription(pargs[0],classname=pargs[1],model=pargs[2])
else: return PanelDescription(pargs[0],classname=pargs[1],model=pargs[2],sharedDataRead=pargs[3],sharedDataWrite=pargs[4])
for k,p in EXTRA_PANELS.items():
try:
vars()[k] = get_panel(k)
except:
traceback.print_exc()
#===============================================================================
#: EXTRA_WIDGETS: The Dictionary of EXTRA_WIDGETS Panels
#:
#: Adding other widgets to the catalog of the "new panel" dialog.
#: pass a tuple of (classname,screenshot)
#:
#: - classname may contain the module name.
#: - screenshot can either be a file name relative to the application dir or
#: a resource URL or None
#:
#: examples:
#:
#: ('vacca.properties.VaccaPropTable',wdir('vacca/image/widgets/Properties.png')),
#: ('vacca.panel.VaccaPanel',wdir('vacca/image/widgets/Panel.png')),
EXTRA_WIDGETS = EXTRA_WIDGETS
#: EXTRA_CATALOG_WIDGETS: The Dictionary of EXTRA_CATALOG_WIDGETS Panels to Show by
#: default.
#:Is the Sum of EXTRA_WIDGETS and the custom Widgets defined in config.py
EXTRA_CATALOG_WIDGETS = []
EXTRA_CATALOG_WIDGETS = EXTRA_WIDGETS+[
#('vacca.VacuumProfile',WDIR+'image/ProfilePlot.jpg'),
#('vacca.plot.PressureTrend',WDIR+'image/PressureTrend.jpg'),
#('vacca.VacuumGrid',WDIR+'image/BLGrid.jpg'),
#('vacca.VerticalGrid',WDIR+'image/VerticalGrid.jpg'),
('vacca.properties.VaccaPropTable',vpath('image/widgets/Properties.png')),
('fandango.qt.QEvaluator',':/snapshot/large/snapshot/TaurusShell.png'),
]
#===============================================================================
#: TOOLBARS
#:
#: Define custom toolbars to be shown. To define a toolbar, instantiate a
#: ToolbarDescription object (see documentation for the gblgui_utils module)
#===============================================================================
#dummytoolbar = ToolBarDescription('Empty Toolbar',
#classname = 'QToolBar',
#modulename = 'PyQt4.Qt')
#panictoolbar = ToolBarDescription('Panic Toolbar',
# classname = 'PanicToolbar',
# modulename = 'tangopanic')
toolbars = []
for name,obj in (TOOLBARS or []):
toolbars.append(ToolBarDescription(name,
classname = obj.split('.')[-1],
modulename = obj.rsplit('.',1)[0],
#sharedDataWrite={'selectedPerspective':'blabla'}
))
toolbar = toolbars[-1]
try:
for menu,actions in MENUS:
vacca.utils.add_menu(menu,actions)
except:
traceback.print_exc()
#===============================================================================
# Define custom applets to be shown in the applets bar (the wide bar that
# contains the logos). To define an applet, instantiate an AppletDescription
# object (see documentation for the gblgui_utils module)
#===============================================================================
# ALREADY LOADED FROM vacca.default.EXTRA_APPS
#xmambo = AppletDescription('Mambo',classname = 'vacca.panel.VaccaAction',
# model=["Archiving",wdir('vacca/image/widgets/ProfilePlot.png'),'mambo'],)
#===============================================================================
# Define which External Applications are to be inserted.
# To define an external application, instantiate an ExternalApp object
# See TaurusMainWindow.addExternalAppLauncher for valid values of ExternalApp
#===============================================================================
# ALREADY LOADED FROM vacca.default.EXTRA_TOOLS
#xvacca = ExternalApp(cmdargs=['konqueror',URL_HELP], text="Alba VACuum Controls Application", icon=WDIR+'image/icons/cow-tux.png')
#DEFAULT_APPS =
EXTRA_TOOLS = EXTRA_TOOLS
for name,cmdargs,icon in EXTRA_TOOLS:
locals()['x'+name] = ExternalApp(cmdargs=cmdargs,text=name,icon=icon or None)
#xjive = ExternalApp(cmdargs=['jive'], text="Jive")#, icon=WDIR+'image/icons/cow-tux.png')
#xastor = ExternalApp(cmdargs=['astor'], text="Astor")#, icon=WDIR+'image/icons/cow-tux.png')
#===============================================================================
# POOL RELATED OPTIONS
#===============================================================================
# Set INSTRUMENTS_FROM_POOL to True for enabling auto-creation of
# instrument panels based on the Pool Instrument info
#MACROSERVER_NAME =
#DOOR_NAME =
#MACROEDITORS_PATH =
INSTRUMENTS_FROM_POOL = False
#===============================================================================
# THIS SYNOPTIC OPTION IS POOL-related; IT'S NOT THE MAIN APPLICATION SYNOPTIC!!!
# If you want an instrument selection synoptic, set the SYNOPTIC variable
# to the file name of a jdraw file. If a relative path is given, the directory
# containing this configuration file will be used as root
# (comment out or make SYNOPTIC=None to skip creating a synoptic panel)
#===============================================================================
SYNOPTIC = [] #'images/example01.jdw','images/syn2.jdw']
#===============================================================================
#:
from PyQt4 import Qt
#Forcing nesting of dock widgets
if app:
try:
main = vacca.utils.get_main_window(app)
main.setDockNestingEnabled(True)
except:
traceback.print_exc()
EXTRA_APPS = EXTRA_APPS
""" The Vacca Panels to show in the JogsBar. Use EXTRA_APPS to add launchers to the toolbar.
It will create new AppletDescription objects to add elements to the right-side toolbar.
Examples:
* EXTRA_APPS['Properties'] = {'class' : vacca.VaccaPropTable}
* EXTRA_APPS['DevicePanel'] = {'class' : vacca.VaccaPanel}
* EXTRA_APPS['Panic']= {'class' : vacca.VaccaPanic }
* EXTRA_APPS['ExtraDock']= {'class' : Qt.QMainWindow }
"""
adder = vacca.addCustomPanel2Gui(EXTRA_APPS)
print('\n\t>>> Config Finished ...')
globals()['CONFIG_DONE'] = True
print('-'*80 + '\n\n\n')
except:
print(traceback.format_exc())