diff --git a/lib/taurus/qt/qtgui/taurusgui/config_loader/__init__.py b/lib/taurus/qt/qtgui/taurusgui/config_loader/__init__.py
new file mode 100644
index 000000000..2d954c2f8
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_loader/__init__.py
@@ -0,0 +1,27 @@
+#############################################################################
+##
+# This file is part of Taurus
+##
+# http://taurus-scada.org
+##
+# 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 .
+##
+###########################################################################
+
+"""
+"""
+
+from .util import getLoaders
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_loader/__main__.py b/lib/taurus/qt/qtgui/taurusgui/config_loader/__main__.py
new file mode 100644
index 000000000..c3d609195
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_loader/__main__.py
@@ -0,0 +1,18 @@
+import sys
+from pprint import pprint
+
+from .util import getLoaders
+
+
+def main(conf):
+ cfg = {}
+ loaders = getLoaders(conf)
+ for loader in loaders:
+ cfg.update(loader.load())
+
+ cfg = loaders[0].to_dict(cfg)
+
+ pprint(cfg)
+
+
+main(sys.argv[1])
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_loader/abstract.py b/lib/taurus/qt/qtgui/taurusgui/config_loader/abstract.py
new file mode 100644
index 000000000..ba0fa18a3
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_loader/abstract.py
@@ -0,0 +1,94 @@
+#############################################################################
+##
+# This file is part of Taurus
+##
+# http://taurus-scada.org
+##
+# 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 .
+##
+###########################################################################
+
+""""""
+import abc
+
+from taurus.qt.qtgui.taurusgui.utils import (
+ AppletDescription,
+ ExternalApp,
+ PanelDescription,
+ ToolBarDescription,
+)
+
+# Python 2/3 compatibility
+if not hasattr(abc, "ABC"):
+ setattr(abc, "ABC", abc.ABCMeta("ABC", (object,), {}))
+
+
+__all__ = ["AbstractConfigLoader"]
+
+
+class AbstractConfigLoader(abc.ABC):
+ """
+ Abstract class for config loaders.
+ It defines interface which has to be implemneted by subclass in
+ order for it to be ConfigLoader
+ """
+
+ CONFIG_VALUES = [
+ "GUI_NAME",
+ "ORGANIZATION",
+ "CUSTOM_LOGO",
+ "ORGANIZATION_LOGO",
+ "SINGLE_INSTANCE",
+ "MANUAL_URI",
+ "INIFILE",
+ "EXTRA_CATALOG_WIDGETS",
+ ]
+
+ DESCRIPTIONS = [
+ (AppletDescription, "AppletDescriptions"),
+ (ExternalApp, "ExternalApps"),
+ (PanelDescription, "PanelDescriptions"),
+ (ToolBarDescription, "ToolBarDescriptions"),
+ ]
+
+ def __init__(self, confname):
+ self._confname = confname
+
+ @abc.abstractmethod
+ def supports(self, confname):
+ """
+ Return True or False for support of specific configuration passed
+ """
+ return None
+
+ @abc.abstractmethod
+ def load(self):
+ """
+ This method is meant to load actual data from file on disk.
+ Return dictionary with configuration.
+ """
+ return {}
+
+ def to_dict(self, conf):
+ """
+ Generate pure Python dictionary from conf
+ """
+
+ for _, section in self.DESCRIPTIONS:
+ objs = [o.to_dict() for o in conf.get(section, [])]
+ conf[section] = objs
+
+ return conf
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_loader/examples/config.json b/lib/taurus/qt/qtgui/taurusgui/config_loader/examples/config.json
new file mode 100644
index 000000000..95489ba1e
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_loader/examples/config.json
@@ -0,0 +1,69 @@
+{
+ "GUI_NAME": "EXAMPLE 01",
+ "ORGANIZATION": "Taurus",
+ "MANUAL_URI": "http://www.taurus-scada.org",
+ "SYNOPTIC": ["images/example01.jdw", "images/syn2.jdw"],
+ "INSTRUMENTS_FROM_POOL": false,
+ "PanelDescriptions": [
+ {
+ "name": "NeXus Browser",
+ "classname": "taurus.qt.qtgui.extra_nexus.TaurusNeXusBrowser"
+ },
+ {
+ "name": "BigInstrument",
+ "classname": "taurus.qt.qtgui.panel.TaurusAttrForm",
+ "model": "sys/tg_test/1"
+ },
+ {
+ "name": "NeXus Browser",
+ "classname": "taurus.qt.qtgui.extra_nexus.TaurusNeXusBrowser"
+ },
+ {
+ "name": "instrument1",
+ "classname": "taurus.qt.qtgui.panel.TaurusForm",
+ "model": [
+ "sys/tg_test/1/double_scalar",
+ "sys/tg_test/1/short_scalar_ro",
+ "sys/tg_test/1/float_spectrum_ro",
+ "sys/tg_test/1/double_spectrum"
+ ]
+ },
+ {
+ "name": "instrument2",
+ "classname": "taurus.qt.qtgui.panel.TaurusForm",
+ "model": [
+ "sys/tg_test/1/wave",
+ "sys/tg_test/1/boolean_scalar"
+ ]
+ },
+ {
+ "name": "Selected Instrument",
+ "classname": "taurus.external.qt.Qt.QLineEdit",
+ "sharedDataRead": {
+ "SelectedInstrument": "setText"
+ },
+ "sharedDataWrite": {
+ "SelectedInstrument": "textEdited"
+ }
+ }
+ ],
+ "ToolBarDescriptions": [
+ {
+ "name": "Empty Toolbar",
+ "classname": "taurus.external.qt.Qt.QToolBar"
+ }
+ ],
+ "ExternalApps": [
+ {
+ "name": "xterm",
+ "cmdargs": ["xterm", "spock"],
+ "text": "Spock",
+ "icon": "utilities-terminal"
+ }
+ ],
+ "EXTRA_CATALOG_WIDGETS": [
+ ["taurus.external.qt.Qt.QLineEdit", "logos:taurus.png"],
+ ["taurus.external.qt.Qt.QSpinBox", "images/syn2.jpg"],
+ ["taurus.external.qt.Qt.QLabel", null]
+ ]
+}
\ No newline at end of file
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_loader/examples/config.py b/lib/taurus/qt/qtgui/taurusgui/config_loader/examples/config.py
new file mode 100644
index 000000000..e00aecc26
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_loader/examples/config.py
@@ -0,0 +1,70 @@
+
+
+from taurus.qt.qtgui.taurusgui.utils import PanelDescription, ExternalApp, ToolBarDescription, AppletDescription
+
+GUI_NAME = 'EXAMPLE 01'
+ORGANIZATION = 'Taurus'
+
+MANUAL_URI = 'http://www.taurus-scada.org'
+
+SYNOPTIC = ['images/example01.jdw', 'images/syn2.jdw']
+
+
+INSTRUMENTS_FROM_POOL = False
+
+
+nxbrowser = PanelDescription(
+ 'NeXus Browser',
+ classname='taurus.qt.qtgui.extra_nexus.TaurusNeXusBrowser'
+)
+
+i0 = PanelDescription(
+ 'BigInstrument',
+ classname='taurus.qt.qtgui.panel.TaurusAttrForm',
+ model='sys/tg_test/1'
+)
+
+i1 = PanelDescription(
+ 'instrument1',
+ classname='taurus.qt.qtgui.panel.TaurusForm',
+ model=['sys/tg_test/1/double_scalar',
+ 'sys/tg_test/1/short_scalar_ro',
+ 'sys/tg_test/1/float_spectrum_ro',
+ 'sys/tg_test/1/double_spectrum']
+)
+
+i2 = PanelDescription(
+ 'instrument2',
+ classname='taurus.qt.qtgui.panel.TaurusForm',
+ model=['sys/tg_test/1/wave',
+ 'sys/tg_test/1/boolean_scalar']
+)
+
+trend = PanelDescription(
+ 'Trend',
+ classname='taurus.qt.qtgui.plot.TaurusTrend',
+ model=['sys/tg_test/1/double_scalar']
+)
+
+connectionDemo = PanelDescription(
+ 'Selected Instrument',
+ classname='taurus.external.qt.Qt.QLineEdit', # A pure Qt widget!
+ sharedDataRead={'SelectedInstrument': 'setText'},
+ sharedDataWrite={'SelectedInstrument': 'textEdited'}
+)
+
+dummytoolbar = ToolBarDescription(
+ 'Empty Toolbar',
+ classname='taurus.external.qt.Qt.QToolBar'
+)
+
+xterm = ExternalApp(
+ cmdargs=['xterm', 'spock'], text="Spock", icon='utilities-terminal')
+hdfview = ExternalApp(["hdfview"])
+pymca = ExternalApp(['pymca'])
+
+EXTRA_CATALOG_WIDGETS = [
+ ('taurus.external.qt.Qt.QLineEdit', 'logos:taurus.png'), # a resource
+ ('taurus.external.qt.Qt.QSpinBox', 'images/syn2.jpg'), # relative
+ # ('taurus.external.Qt.QTextEdit','/tmp/foo.png'), # absolute
+ ('taurus.external.qt.Qt.QLabel', None)] # none
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_loader/jsonconf.py b/lib/taurus/qt/qtgui/taurusgui/config_loader/jsonconf.py
new file mode 100644
index 000000000..5c1afb4a5
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_loader/jsonconf.py
@@ -0,0 +1,93 @@
+#############################################################################
+##
+# This file is part of Taurus
+##
+# http://taurus-scada.org
+##
+# 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 .
+##
+###########################################################################
+
+""""""
+
+import json
+import os
+
+from taurus.qt.qtgui.taurusgui.config_loader.abstract import (
+ AbstractConfigLoader,
+)
+from taurus.qt.qtgui.taurusgui.config_loader.util import ConfigLoaderError
+
+__all__ = ["JsonConfigLoader"]
+
+
+class JsonConfigLoader(AbstractConfigLoader):
+ """
+ Loads configuration for TaurusGui from JSON file
+ """
+
+ def __init__(self, confname):
+ super(JsonConfigLoader, self).__init__(confname)
+ self._data = {}
+
+ def _get_objects(self, klass, section):
+ """
+ Helper function to get list of Python objects from dictionary
+ """
+ objs = []
+ for o in self._data.get(section, []):
+ if isinstance(o, dict):
+ objs.append(klass(**o))
+ return objs
+
+ @staticmethod
+ def supports(confname):
+ if os.path.isfile(confname):
+ ext = os.path.splitext(confname)[-1]
+ if ext == ".json":
+ return True
+ return False
+
+ def _get_data(self):
+ try:
+ with open(self._confname, "r") as fp:
+ self._data = json.load(fp)
+ except IOError as e:
+ raise ConfigLoaderError(
+ "Problem with accessing config file: " + str(e)
+ )
+ except ValueError as e:
+ raise ConfigLoaderError(
+ "Problem with config file decoding: " + str(e)
+ )
+
+ def load(self):
+ self._get_data()
+
+ tmp = {}
+
+ for v in self.CONFIG_VALUES:
+ if v in self._data:
+ tmp[v] = self._data[v]
+
+ for klass, section in self.DESCRIPTIONS:
+ tmp[section] = self._get_objects(klass, section)
+
+ tmp["CONF_DIR"] = os.path.abspath(
+ os.path.dirname(self._confname)
+ )
+
+ return tmp
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_loader/pyconf.py b/lib/taurus/qt/qtgui/taurusgui/config_loader/pyconf.py
new file mode 100644
index 000000000..c739f64bc
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_loader/pyconf.py
@@ -0,0 +1,145 @@
+#############################################################################
+##
+# This file is part of Taurus
+##
+# http://taurus-scada.org
+##
+# 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 .
+##
+###########################################################################
+
+""""""
+
+import inspect
+import os
+import pkgutil
+import sys
+import types
+
+from taurus.qt.qtgui.taurusgui.config_loader.abstract import (
+ AbstractConfigLoader,
+)
+from taurus.qt.qtgui.taurusgui.config_loader.util import ConfigLoaderError
+
+__all__ = ["PyConfigLoader"]
+
+
+class PyConfigLoader(AbstractConfigLoader):
+ """
+ Loads configuration for TaurusGui from Python module or package
+ """
+
+ def __init__(self, confname):
+ super(PyConfigLoader, self).__init__(confname)
+ self._mod = types.ModuleType(
+ "__dummy_conf_module_%s__" % confname
+ ) # dummy module
+
+ def _get_objects(self, klass):
+ objs = [
+ obj
+ for name, obj in inspect.getmembers(self._mod)
+ if isinstance(obj, klass)
+ ]
+ return objs
+
+ def _importConfiguration(self):
+ """returns the module corresponding to `confname` or to
+ `tgconf_`. Note: the `conf` subdirectory of the directory in
+ which taurusgui.py file is installed is temporally prepended to sys.path
+ """
+ confsubdir = os.path.join(
+ os.path.abspath(os.path.dirname(__file__)), "conf"
+ ) # the path to a conf subdirectory of the place where taurusgui.py is
+ oldpath = sys.path
+ try:
+ # add the conf subdirectory dir to the pythonpath
+ sys.path = [confsubdir] + sys.path
+ mod = __import__(self._confname)
+ except ImportError:
+ altconfname = "tgconf_%s" % self._confname
+ try:
+ mod = __import__(altconfname)
+ except ImportError:
+ msg = "cannot import %s or %s" % (self._confname, altconfname)
+ raise ConfigLoaderError(msg)
+ finally:
+ sys.path = oldpath # restore the previous sys.path
+ return mod
+
+ @staticmethod
+ def supports(confname):
+ if os.path.exists(confname):
+ if os.path.isfile(confname): # happy path, we got file
+ ext = os.path.splitext(confname)[-1]
+ if ext == ".py":
+ return True
+ return False
+
+ elif os.path.isdir(confname):
+ # if it's directory, assume it's importable Python package
+ return True
+ return False
+ else:
+ # not exisitng path, check if it is in top-level modules
+ if confname in list(pkgutil.iter_modules()):
+ return True
+ return False
+
+ def _get_data(self):
+ """Reads a configuration file
+
+ :param confname: (str or None) the name of module located in the
+ PYTHONPATH or in the conf subdirectory of the directory
+ in which taurusgui.py file is installed.
+ This method will try to import .
+ If that fails, it will try to import
+ `tgconf_`.
+ Alternatively, `confname` can be the path to the
+ configuration module (not necessarily in the
+ PYTHONPATH).
+ `confname` can also be None, in which case a dummy
+ empty module will be used.
+ """
+
+ # import the python config file
+ if os.path.exists(self._confname): # if confname is a dir or file name
+ import imp
+
+ path, name = os.path.split(self._confname)
+ name, _ = os.path.splitext(name)
+ try:
+ f, filename, data = imp.find_module(name, [path])
+ self._mod = imp.load_module(name, f, filename, data)
+ except ImportError:
+ self._mod = self._importConfiguration()
+ else: # if confname is not a dir name, we assume it is a module name in the python path
+ self._mod = self._importConfiguration()
+
+ def load(self):
+ self._get_data()
+
+ tmp = {}
+ tmp["CONF_DIR"] = os.path.abspath(os.path.dirname(self._mod.__file__))
+
+ for v in self.CONFIG_VALUES:
+ if hasattr(self._mod, v):
+ tmp[v] = getattr(self._mod, v)
+
+ for klass, section in self.DESCRIPTIONS:
+ tmp[section] = self._get_objects(klass)
+
+ return tmp
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_loader/util.py b/lib/taurus/qt/qtgui/taurusgui/config_loader/util.py
new file mode 100644
index 000000000..b47ea7bc7
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_loader/util.py
@@ -0,0 +1,78 @@
+#############################################################################
+##
+# This file is part of Taurus
+##
+# http://taurus-scada.org
+##
+# 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 .
+##
+###########################################################################
+
+"""
+This module provides factory 'getLoader' for proper ConfigLoader object
+detected from 'confname' string. Each config loader has to implement interface
+defined by AbstractConfigLoader class in
+taurus.qt.qtgui.taurusgui.config_loader.abstract
+"""
+
+
+import pkg_resources
+
+from taurus import warning
+
+__all__ = ["getLoaders", "ConfigLoaderError"]
+
+
+class ConfigLoaderError(Exception):
+ """
+ Base exception raised by ConfigLoader
+ """
+
+ def __init__(self, message):
+ message = "Exception raised while loading configuration: " + message
+ super(ConfigLoaderError, self).__init__(message)
+
+
+def getLoaders(confname):
+ """
+ Discover proper config loader based on passed string.
+ It can be either path to file or directory or Python
+ abolute path to module with configuration.
+
+ :param confname: name of configuration
+ :return: A AbstractConfigLoader subclass object
+ """
+
+ EP_GROUP_LOADERS = "taurus.gui.loaders"
+
+ loaders = []
+ for ep in pkg_resources.iter_entry_points(EP_GROUP_LOADERS):
+ try:
+ loader = ep.load()
+ if loader.supports(confname):
+ loaders.append(loader(confname))
+ except Exception as e:
+ warning(
+ "Could not load config loader plugin '%s. Reason: '%s",
+ ep.name,
+ e,
+ )
+ if not loaders:
+ raise NotImplementedError(
+ "No supported config loader for '%s'" % confname
+ )
+ else:
+ return loaders
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_loader/xmlconf.py b/lib/taurus/qt/qtgui/taurusgui/config_loader/xmlconf.py
new file mode 100644
index 000000000..e0bd96d88
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_loader/xmlconf.py
@@ -0,0 +1,127 @@
+#############################################################################
+##
+# This file is part of Taurus
+##
+# http://taurus-scada.org
+##
+# 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 .
+##
+###########################################################################
+
+""""""
+
+import os
+
+from lxml import etree
+from taurus.qt.qtgui.taurusgui.config_loader.abstract import (
+ AbstractConfigLoader,
+)
+from taurus.qt.qtgui.taurusgui.config_loader.util import ConfigLoaderError
+from taurus.qt.qtgui.taurusgui.utils import (
+ AppletDescription,
+ ExternalApp,
+ PanelDescription,
+ ToolBarDescription,
+)
+
+__all__ = ["XmlConfigLoader"]
+
+
+class XmlConfigLoader(AbstractConfigLoader):
+ """
+ Loads configuration for TaurusGui from XML file
+ """
+
+ def __init__(self, confname):
+ super(XmlConfigLoader, self).__init__(confname)
+ self._root = etree.fromstring("")
+
+ def _get(self, nodename, default=None):
+ """
+ Helper method for getting data from XML
+ """
+ name = self._root.find(nodename)
+ if name is None or name.text is None:
+ return default
+ else:
+ return name.text
+
+ def _get_objects(self, klass, section):
+ """
+ Helper method to get list of objects of given Python class
+ """
+ objs = []
+ obj = self._root.find(section) # 's' is for plural form
+ if obj is not None:
+ for child in obj:
+ if child.tag == klass.__name__:
+ child_str = etree.tostring(child, encoding="unicode")
+ o = klass.fromXml(child_str)
+ if o is not None:
+ objs.append(o)
+ return objs
+
+ @staticmethod
+ def supports(confname):
+ if os.path.isfile(confname):
+ ext = os.path.splitext(confname)[-1]
+ if ext == ".xml":
+ return True
+ return False
+
+ def _get_data(self):
+ """
+ Get the xml root node from the xml configuration file
+ """
+ try:
+ with open(self._confname, "r") as xmlFile:
+ self._root = etree.fromstring(xmlFile.read())
+ except IOError as e:
+ raise ConfigLoaderError(
+ "Problem with accessing config file: " + str(e)
+ )
+ except Exception as e:
+ msg = 'Error reading the XML file: "%s"' % self._confname
+ raise ConfigLoaderError(msg)
+
+ def load(self):
+ self._get_data()
+
+ tmp = {}
+
+ for v in self.CONFIG_VALUES:
+ name = self._root.find(v)
+ if name is not None and name.text is not None:
+ tmp[v] = name.text
+
+ for klass, section in self.DESCRIPTIONS:
+ tmp[section] = self._get_objects(klass, section)
+
+ tmp["CONF_DIR"] = os.path.abspath(os.path.dirname(self._confname))
+
+ return tmp
+
+ @property
+ def synoptics(self):
+ synoptic = []
+ node = self._root.find("SYNOPTIC")
+ if (node is not None) and (node.text is not None):
+ for child in node:
+ s = child.get("str")
+ # we do not append empty strings
+ if s:
+ synoptic.append(s)
+ return synoptic
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_properties/__init__.py b/lib/taurus/qt/qtgui/taurusgui/config_properties/__init__.py
new file mode 100644
index 000000000..b9f831f6d
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_properties/__init__.py
@@ -0,0 +1,27 @@
+#############################################################################
+##
+# This file is part of Taurus
+##
+# http://taurus-scada.org
+##
+# 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 .
+##
+###########################################################################
+
+"""
+"""
+
+from .util import getConfigPropertiesLoaders
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_properties/bck_compat.py b/lib/taurus/qt/qtgui/taurusgui/config_properties/bck_compat.py
new file mode 100644
index 000000000..5474b815f
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_properties/bck_compat.py
@@ -0,0 +1,42 @@
+#############################################################################
+##
+# This file is part of Taurus
+##
+# http://taurus-scada.org
+##
+# 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 .
+##
+###########################################################################
+
+
+"""
+Module for backwards-compatible configuration loading
+"""
+
+
+def loadXmlConf(gui):
+ xml_conf = gui.getConfigValue("XML_CONF")
+ if xml_conf is None:
+ return
+
+ try:
+ from taurus.qt.qtgui.taurusgui.config_loader.xmlconf import XmlConfigLoader
+
+ xcl = XmlConfigLoader(xml_conf)
+ cfg = xcl.load()
+ gui.__config.update(cfg)
+ except Exception as e:
+ gui.warning("Could not load configuration from XML_CONF=%s" % xml_conf)
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_properties/deprecated.py b/lib/taurus/qt/qtgui/taurusgui/config_properties/deprecated.py
new file mode 100644
index 000000000..3b52ed767
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_properties/deprecated.py
@@ -0,0 +1,80 @@
+#############################################################################
+##
+# This file is part of Taurus
+##
+# http://taurus-scada.org
+##
+# 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 .
+##
+###########################################################################
+
+"""
+Provide loading of deprecated TaurusGUI config properties
+"""
+
+from taurus.external.qt import Qt
+
+
+def loadMonitor(gui):
+ monitor_model = gui.getConfigValue("MONITOR", "")
+ if not monitor_model:
+ return
+
+ try:
+ gui.splashScreen().showMessage("Creating applet monitor")
+ except AttributeError:
+ pass
+
+ from taurus.qt.qtgui.qwt5.monitor import TaurusMonitorTiny
+
+ w = TaurusMonitorTiny()
+ w.setModel(monitor_model)
+ # add the widget to the applets toolbar
+ gui.jorgsBar.addWidget(w)
+ # register the toolbar as delegate
+ gui.registerConfigDelegate(w, "monitor")
+
+
+def loadConsole(gui):
+ """
+ Deprecated CONSOLE command (if you need a IPython Console, just add a
+ Panel with a `silx.gui.console.IPythonWidget`
+ """
+ # TODO: remove this method when making deprecation efective
+ if not gui.getConfigValue("CONSOLE", []):
+ return
+
+ msg = (
+ "createConsole() and the 'CONSOLE' configuration key are "
+ + "deprecated since 4.0.4. Add a panel with a "
+ + "silx.gui.console.IPythonWidget widdget instead"
+ )
+ gui.deprecated(msg)
+ try:
+ from silx.gui.console import IPythonWidget
+ except ImportError:
+ gui.warning(
+ "Cannot import taurus.qt.qtgui.console. "
+ + "The Console Panel will not be available"
+ )
+ return
+ console = IPythonWidget()
+ gui.createPanel(
+ console,
+ "Console",
+ permanent=True,
+ icon=Qt.QIcon.fromTheme("utilities-terminal"),
+ )
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_properties/jdraw.py b/lib/taurus/qt/qtgui/taurusgui/config_properties/jdraw.py
new file mode 100644
index 000000000..c0ab807e0
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_properties/jdraw.py
@@ -0,0 +1,62 @@
+import os
+import sys
+
+from future.utils import string_types
+import taurus
+from taurus.external.qt import Qt
+
+
+def loadSynoptic(gui):
+ # Synoptics
+ synoptic = gui.getConfigValue("SYNOPTIC")
+ if isinstance(synoptic, string_types): # old config file style
+ gui.warning(
+ 'Deprecated usage of synoptic keyword (now it expects a list of paths). Please update your configuration file to: "synoptic=[\'%s\']".' % synoptic)
+ synoptic = [synoptic]
+ for s in synoptic:
+ _createMainSynoptic(gui, s)
+
+
+def _createMainSynoptic(gui, synopticname):
+ '''
+ Creates a synoptic panel and registers it as "SelectedInstrument"
+ reader and writer (allowing selecting instruments from synoptic
+ '''
+ try:
+ jdwFileName = os.path.join(gui._confDirectory, synopticname)
+ from taurus.qt.qtgui.graphic import TaurusJDrawSynopticsView
+ synoptic = TaurusJDrawSynopticsView()
+ synoptic.setModel(jdwFileName)
+ gui.__synoptics.append(synoptic)
+ except Exception as e:
+ # print repr(e)
+ msg = 'Error loading synoptic file "%s".\nSynoptic won\'t be available' % jdwFileName
+ gui.error(msg)
+ gui.traceback(level=taurus.Info)
+ result = Qt.QMessageBox.critical(gui, 'Initialization error', '%s\n\n%s' % (
+ msg, repr(e)), Qt.QMessageBox.Abort | Qt.QMessageBox.Ignore)
+ if result == Qt.QMessageBox.Abort:
+ sys.exit()
+
+ Qt.qApp.SDM.connectWriter(
+ "SelectedInstrument", synoptic, "graphicItemSelected")
+ Qt.qApp.SDM.connectReader(
+ "SelectedInstrument", synoptic.selectGraphicItem)
+
+ # find an unique (and short) name
+ name = os.path.splitext(os.path.basename(synopticname))[0]
+ if len(name) > 10:
+ name = 'Syn'
+ i = 2
+ prefix = name
+ while name in gui.__panels:
+ name = '%s_%i' % (prefix, i)
+ i += 1
+
+ synopticpanel = gui.createPanel(synoptic, name, permanent=True,
+ icon=Qt.QIcon.fromTheme(
+ 'image-x-generic'))
+
+ if gui.QUICK_ACCESS_TOOLBAR_ENABLED:
+ toggleSynopticAction = synopticpanel.toggleViewAction()
+ gui.quickAccessToolBar.addAction(toggleSynopticAction)
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_properties/sardana.py b/lib/taurus/qt/qtgui/taurusgui/config_properties/sardana.py
new file mode 100644
index 000000000..3e55b21cc
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_properties/sardana.py
@@ -0,0 +1,191 @@
+#############################################################################
+##
+# This file is part of Taurus
+##
+# http://taurus-scada.org
+##
+# 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 .
+##
+###########################################################################
+
+"""
+Module for loading Sardana-specific config properties
+"""
+
+from operator import attrgetter
+
+from taurus import Device
+
+
+def loadMacroServerName(gui):
+ macro_server_name = gui.getConfigValue("MACROSERVER_NAME", "")
+ if macro_server_name:
+ gui.macroserverNameChanged.emit(macro_server_name)
+ return macro_server_name
+
+
+def loadMacroBroker(gui):
+ """configure macro infrastructure"""
+ ms = gui.getConfigValue("MACROSERVER_NAME", "")
+ mp = gui.getConfigValue("MACRO_PANELS", True)
+ # macro infrastructure will only be created if MACROSERVER_NAME is set
+ if ms and mp is True:
+ from sardana.taurus.qt.qtgui.macrolistener import MacroBroker
+
+ gui.__macroBroker = MacroBroker(gui)
+
+
+def loadDoorName(gui):
+ door_name = gui.getConfigValue("DOOR_NAME", True)
+ if door_name:
+ gui.doorNameChanged.emit(door_name)
+
+ @staticmethod
+ def _loadMacroEditorsPath(gui):
+ macro_editors_path = gui.getConfigValue(
+ "MACRO_EDITORS_PATH", True
+ )
+ if macro_editors_path:
+ from sardana.taurus.qt.qtgui.extra_macroexecutor.macroparameterseditor.macroparameterseditor import (
+ ParamEditorManager,
+ )
+
+ ParamEditorManager().parsePaths(macro_editors_path)
+ ParamEditorManager().browsePaths()
+
+def loadInstrumentsFromPool(self, gui):
+ """
+ Get panel descriptions from pool if required
+ """
+ # todo: needs heavy refactor
+ ms = gui.getConfigValue("MACROSERVER_NAME", "")
+ if not ms:
+ return
+
+ instruments_from_pool = gui.getConfigValue(
+ "INSTRUMENTS_FROM_POOL", False
+ )
+ if instruments_from_pool:
+ try:
+ gui.splashScreen().showMessage(
+ "Gathering Instrument info from Pool"
+ )
+ except AttributeError:
+ pass
+
+ pool_instruments = _getInstrumentsFromPool(gui, ms)
+ if pool_instruments:
+ _createInstrumentPanels(gui, pool_instruments)
+
+
+def _getInstrumentsFromPool(gui, macroservername):
+ """
+ Get Instruments information form Pool. Return models for
+ each instrument.
+
+ :param TaurusGui gui: instance of TaurusGui
+ :param str macroservername: name of MacroServer
+
+ :return: Dicionary with Pool instruments where values are lists
+ of models
+ :rtype: dict()>)
+ """
+ # todo: needs heavy refactor
+ instrument_dict = {}
+ try:
+ ms = Device(macroservername)
+ instruments = ms.getElementsOfType("Instrument")
+ if instruments is None:
+ raise Exception()
+ except Exception as e:
+ msg = 'Could not fetch Instrument list from "%s": %s' % (
+ macroservername,
+ str(e),
+ )
+ raise type(e)(msg)
+
+ for i in instruments.values():
+ instrument_dict[i.full_name] = []
+
+ pool_elements = []
+ for kls in ("Moveable", "ExpChannel", "IORegister"):
+ pool_elements += sorted(
+ ms.getElementsWithInterface(kls).values(),
+ key=attrgetter("name"),
+ )
+
+ for elem in pool_elements:
+ instrument = elem.instrument
+ if instrument:
+ # -----------------------------------------------------------
+ # Support sardana v<2.4 (which used tango names instead of
+ # taurus full names
+ e_name = elem.full_name
+ if not e_name.startswith("tango://"):
+ e_name = "tango://%s" % e_name
+ # -----------------------------------------------------------
+ instrument_dict[instrument].append(e_name)
+ # filter out empty panels
+ ret = [i for i in instrument_dict if len(instrument_dict[i]) > 0]
+ return ret
+
+
+def _createInstrumentPanels(gui, poolinstruments):
+ """
+ Create GUI panels from Sardana Pool instruments. Each panel is a
+ TaurusForm grouping together all those elements that belong to
+ the same instrument according to the Pool info
+
+ :param TaurusGui gui: isntance of TaurusGui
+ :param dict()) poolinstruments: dictionary where keys
+ are panel names and
+ values are lists of
+ models
+ :return: None
+ """
+
+ for name, model in poolinstruments.items():
+ try:
+ try:
+ gui.splashScreen().showMessage(
+ "Creating instrument panel %s" % name
+ )
+ except AttributeError:
+ pass
+ from taurus.qt.qtgui.panel.taurusform import TaurusForm
+
+ w = TaurusForm()
+
+ # -------------------------------------------------------------
+ # Backwards-compat. Remove when removing CW map support
+ if gui._customWidgetMap:
+ w.setCustomWidgetMap(gui._customWidgetMap)
+ # -------------------------------------------------------------
+ w.setModel(model)
+
+ # the pool instruments may change when the pool config changes,
+ # so we do not store their config
+ gui.createPanel(
+ w,
+ name,
+ floating=False,
+ registerconfig=False,
+ instrumentkey=gui.IMPLICIT_ASSOCIATION,
+ permanent=True,
+ )
+ except Exception as e:
+ msg = "Cannot create instrument panel %s: %s" % (name, str(e))
+ raise type(e)(msg)
diff --git a/lib/taurus/qt/qtgui/taurusgui/config_properties/util.py b/lib/taurus/qt/qtgui/taurusgui/config_properties/util.py
new file mode 100644
index 000000000..662f9d395
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/config_properties/util.py
@@ -0,0 +1,49 @@
+#############################################################################
+##
+# This file is part of Taurus
+##
+# http://taurus-scada.org
+##
+# 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 .
+##
+###########################################################################
+
+
+import pkg_resources
+
+from taurus import warning
+
+__all__ = ["getConfigPropertiesLoaders"]
+
+
+def getConfigPropertiesLoaders():
+ """
+ Get list of all registered callables
+ that can load additional config properties
+ """
+ EP_GROUP_PROPS = "taurus.gui.properties"
+
+ loaders = []
+ for ep in pkg_resources.iter_entry_points(EP_GROUP_PROPS):
+ try:
+ loaders.append(ep.load())
+ except Exception as e:
+ warning(
+ "Could not load config property plugin '%s. Reason: '%s",
+ ep.name,
+ e,
+ )
+ return loaders
diff --git a/lib/taurus/qt/qtgui/taurusgui/taurusgui.py b/lib/taurus/qt/qtgui/taurusgui/taurusgui.py
index b51b2296f..cc51c4597 100644
--- a/lib/taurus/qt/qtgui/taurusgui/taurusgui.py
+++ b/lib/taurus/qt/qtgui/taurusgui/taurusgui.py
@@ -33,9 +33,7 @@
import copy
import click
import weakref
-import inspect
-from future.utils import string_types
from lxml import etree
import taurus
@@ -46,12 +44,12 @@
from taurus.qt.qtgui.util import TaurusWidgetFactory
from taurus.qt.qtgui.base import TaurusBaseWidget, TaurusBaseComponent
from taurus.qt.qtgui.container import TaurusMainWindow
-from taurus.qt.qtgui.taurusgui.utils import (ExternalApp, PanelDescription,
- ToolBarDescription,
- AppletDescription)
+from taurus.qt.qtgui.taurusgui.utils import ExternalApp, PanelDescription
from taurus.qt.qtgui.util.ui import UILoadable
from taurus.qt.qtgui.taurusgui.utils import ExternalAppAction
from taurus.core.util.log import deprecation_decorator
+from taurus.qt.qtgui.taurusgui.config_loader import getLoaders
+from taurus.qt.qtgui.taurusgui.confif_properties import getConfigPropertiesLoaders
__all__ = ["DockWidgetPanel", "TaurusGui"]
@@ -302,6 +300,24 @@ def __init__(self, parent=None, confname=None, configRecursionDepth=None,
if configRecursionDepth is not None:
self.defaultConfigRecursionDepth = configRecursionDepth
+ # default gui configuration
+ self.__conf = {
+ "GUI_NAME": confname,
+ "ORGANIZATION": str(Qt.qApp.organizationName()) or 'Taurus',
+ "CUSTOM_LOGO": 'logos:taurus.png',
+ "ORGANIZATION_LOGO": getattr(tauruscustomsettings, "ORGANIZATION_LOGO", "logos:taurus.png"),
+ "SINGLE_INSTANCE": True,
+ "EXTRA_CATALOG_WIDGETS": [],
+ "MANUAL_URI": taurus.Release.url,
+ "SYNOPTIC": [],
+ "CONF_DIR": os.path.expanduser("~"), # maybe '~/.config' ?
+ "INIFILE": os.path.join(os.path.expanduser("~", "default.ini")),
+ "PanelDescriptions": [],
+ "ToolbarDescriptions": [],
+ "AppletDescriptions": [],
+ "ExternalApps": [],
+ }
+
self.__panels = {}
self.__external_app = {}
self.__external_app_actions = {}
@@ -864,189 +880,19 @@ def createCustomPanel(self, paneldesc=None):
msg = 'Panel %s created. Drag items to it or use the context menu to customize it' % w.name
self.newShortMessage.emit(msg)
- def createMainSynoptic(self, synopticname):
- '''
- Creates a synoptic panel and registers it as "SelectedInstrument"
- reader and writer (allowing selecting instruments from synoptic
- '''
- try:
- jdwFileName = os.path.join(self._confDirectory, synopticname)
- from taurus.qt.qtgui.graphic import TaurusJDrawSynopticsView
- synoptic = TaurusJDrawSynopticsView()
- synoptic.setModel(jdwFileName)
- self.__synoptics.append(synoptic)
- except Exception as e:
- # print repr(e)
- msg = 'Error loading synoptic file "%s".\nSynoptic won\'t be available' % jdwFileName
- self.error(msg)
- self.traceback(level=taurus.Info)
- result = Qt.QMessageBox.critical(self, 'Initialization error', '%s\n\n%s' % (
- msg, repr(e)), Qt.QMessageBox.Abort | Qt.QMessageBox.Ignore)
- if result == Qt.QMessageBox.Abort:
- sys.exit()
-
- Qt.qApp.SDM.connectWriter(
- "SelectedInstrument", synoptic, "graphicItemSelected")
- Qt.qApp.SDM.connectReader(
- "SelectedInstrument", synoptic.selectGraphicItem)
-
- # find an unique (and short) name
- name = os.path.splitext(os.path.basename(synopticname))[0]
- if len(name) > 10:
- name = 'Syn'
- i = 2
- prefix = name
- while name in self.__panels:
- name = '%s_%i' % (prefix, i)
- i += 1
-
- synopticpanel = self.createPanel(synoptic, name, permanent=True,
- icon=Qt.QIcon.fromTheme(
- 'image-x-generic'))
-
- if self.QUICK_ACCESS_TOOLBAR_ENABLED:
- toggleSynopticAction = synopticpanel.toggleViewAction()
- self.quickAccessToolBar.addAction(toggleSynopticAction)
-
- def createConsole(self, kernels):
- msg = ('createConsole() and the "CONSOLE" configuration key are ' +
- 'deprecated since 4.0.4. Add a panel with a ' +
- 'silx.gui.console.IPythonWidget widdget instead')
- self.deprecated(msg)
- try:
- from silx.gui.console import IPythonWidget
- except ImportError:
- self.warning('Cannot import taurus.qt.qtgui.console. ' +
- 'The Console Panel will not be available')
- return
- console = IPythonWidget()
- self.createPanel(console, "Console", permanent=True,
- icon=Qt.QIcon.fromTheme('utilities-terminal'))
-
- def createInstrumentsFromPool(self, macroservername):
- '''
- Creates a list of instrument panel descriptions by gathering the info
- from the Pool. Each panel is a TaurusForm grouping together all those
- elements that belong to the same instrument according to the Pool info
-
- :return: (list)
- '''
- instrument_dict = {}
- try:
- ms = taurus.Device(macroservername)
- instruments = ms.getElementsOfType('Instrument')
- if instruments is None:
- raise Exception()
- except Exception as e:
- msg = 'Could not fetch Instrument list from "%s"' % macroservername
- self.error(msg)
- result = Qt.QMessageBox.critical(self, 'Initialization error', '%s\n\n%s' % (
- msg, repr(e)), Qt.QMessageBox.Abort | Qt.QMessageBox.Ignore)
- if result == Qt.QMessageBox.Abort:
- sys.exit()
- return []
- for i in instruments.values():
- i_name = i.full_name
- #i_name, i_unknown, i_type, i_pools = i.split()
- i_view = PanelDescription(
- i_name, classname='TaurusForm', floating=False, model=[])
- instrument_dict[i_name] = i_view
-
- from operator import attrgetter
- pool_elements = sorted(ms.getElementsWithInterface(
- 'Moveable').values(), key=attrgetter('name'))
- pool_elements += sorted(ms.getElementsWithInterface(
- 'ExpChannel').values(), key=attrgetter('name'))
- pool_elements += sorted(ms.getElementsWithInterface(
- 'IORegister').values(), key=attrgetter('name'))
- for elem in pool_elements:
- instrument = elem.instrument
- if instrument:
- i_name = instrument
- # -----------------------------------------------------------
- # Support sardana v<2.4 (which used tango names instead of
- # taurus full names
- e_name = elem.full_name
- if not e_name.startswith("tango://"):
- e_name = "tango://%s" % e_name
- # -----------------------------------------------------------
- instrument_dict[i_name].model.append(e_name)
- # filter out empty panels
- ret = [instrument for instrument in instrument_dict.values()
- if len(instrument.model) > 0]
- return ret
-
- def __getVarFromXML(self, root, nodename, default=None):
- name = root.find(nodename)
- if name is None or name.text is None:
- return default
- else:
- return name.text
-
- def _importConfiguration(self, confname):
- '''returns the module corresponding to `confname` or to
- `tgconf_`. Note: the `conf` subdirectory of the directory in
- which taurusgui.py file is installed is temporally prepended to sys.path
- '''
- confsubdir = os.path.join(os.path.abspath(os.path.dirname(
- __file__)), 'conf') # the path to a conf subdirectory of the place where taurusgui.py is
- oldpath = sys.path
- try:
- # add the conf subdirectory dir to the pythonpath
- sys.path = [confsubdir] + sys.path
- conf = __import__(confname)
- except ImportError:
- altconfname = "tgconf_%s" % confname
- try:
- conf = __import__(altconfname)
- except ImportError:
- msg = 'cannot import %s or %s' % (confname, altconfname)
- self.error(msg)
- Qt.QMessageBox.critical(
- self, 'Initialization error', msg, Qt.QMessageBox.Abort)
- sys.exit()
- finally:
- sys.path = oldpath # restore the previous sys.path
- return conf
+ def getConfigValue(self, field, default=None):
+ if default is not None:
+ return self.__conf.get(field, default)
+ return self.__conf[field]
def loadConfiguration(self, confname):
'''Reads a configuration file
-
- :param confname: (str or None) the name of module located in the
- PYTHONPATH or in the conf subdirectory of the directory
- in which taurusgui.py file is installed.
- This method will try to import .
- If that fails, it will try to import
- `tgconf_`.
- Alternatively, `confname` can be the path to the
- configuration module (not necessarily in the
- PYTHONPATH).
- `confname` can also be None, in which case a dummy
- empty module will be used.
'''
-
- # import the python config file
try:
- if confname is None:
- import types
- conf = types.ModuleType(
- '__dummy_conf_module__') # dummy module
- confname = str(Qt.qApp.applicationName())
- self._confDirectory = ''
- elif os.path.exists(confname): # if confname is a dir or file name
- import imp
- path, name = os.path.split(confname)
- name, _ = os.path.splitext(name)
- try:
- f, filename, data = imp.find_module(name, [path])
- conf = imp.load_module(name, f, filename, data)
- confname = name
- except ImportError:
- conf = self._importConfiguration(confname)
- self._confDirectory = os.path.dirname(conf.__file__)
- else: # if confname is not a dir name, we assume it is a module name in the python path
- conf = self._importConfiguration(confname)
- self._confDirectory = os.path.dirname(conf.__file__)
+ loaders = getLoaders(confname)
+ for loader in loaders:
+ self.__conf.update(loader.load())
+ self._confDirectory = self.getConfigValue("CONF_DIR")
except Exception:
import traceback
msg = 'Error loading configuration: %s' % traceback.format_exc() # repr(e)
@@ -1055,80 +901,49 @@ def loadConfiguration(self, confname):
self, 'Initialization error', msg, Qt.QMessageBox.Abort)
sys.exit()
- xmlroot = self._loadXmlConfig(conf)
-
- self._loadAppName(conf, confname, xmlroot)
- self._loadOrgName(conf, xmlroot)
- self._loadCustomLogo(conf, xmlroot)
+ self._loadAppName(confname)
+ self._loadOrgName()
+ self._loadCustomLogo()
# do some extra config if we have a TaurusApplication
_app = Qt.QApplication.instance()
if hasattr(_app, 'basicConfig'):
_app.basicConfig()
- self._loadOrgLogo(conf, xmlroot)
+ self._loadOrgLogo()
- self._loadSingleInstance(conf, xmlroot)
+ self._loadSingleInstance()
- self._loadExtraCatalogWidgets(conf, xmlroot)
- self._loadManualUri(conf, xmlroot)
- POOLINSTRUMENTS = self._loadSardanaOptions(conf, xmlroot)
- self._loadSynoptic(conf, xmlroot)
- # TODO: remove deprecated _loadConsole
- self._loadConsole(conf, xmlroot)
+ self._loadExtraCatalogWidgets()
+ self._loadManualUri()
- self._loadCustomPanels(conf, xmlroot, POOLINSTRUMENTS)
- self._loadCustomToolBars(conf, xmlroot)
- self._loadCustomApplets(conf, xmlroot)
- self._loadExternalApps(conf, xmlroot)
- self._loadIniFile(conf, xmlroot)
-
- def _loadXmlConfig(self, conf):
- """
- Get the xml root node from the xml configuration file
- """
+ self._loadCustomPanels()
+ self._loadCustomToolBars()
+ self._loadCustomApplets()
+ self._loadExternalApps()
+ self._loadIniFile()
- xml_config = getattr(conf, 'XML_CONFIG', None)
- if xml_config is None:
- self._xmlConfigFileName = None
- else:
- self._xmlConfigFileName = os.path.join(
- self._confDirectory, xml_config)
- # default fallback (in case of I/O or parse errors)
- xmlroot = etree.fromstring('')
- if xml_config is not None:
- try:
- # If a relative name was given, the conf directory will be used
- # as base path
- xmlfname = os.path.join(self._confDirectory, xml_config)
- xmlFile = open(xmlfname, 'r')
- xmlstring = xmlFile.read()
- xmlFile.close()
- xmlroot = etree.fromstring(xmlstring)
- except Exception as e:
- msg = 'Error reading the XML file: "%s"' % xmlfname
- self.error(msg)
- self.traceback(level=taurus.Info)
- result = Qt.QMessageBox.critical(self, 'Initialization error', '%s\nReason:"%s"' % (
- msg, repr(e)), Qt.QMessageBox.Abort | Qt.QMessageBox.Ignore)
- if result == Qt.QMessageBox.Abort:
- sys.exit()
- return xmlroot
-
- def _loadAppName(self, conf, confname, xmlroot):
- appname = getattr(conf, 'GUI_NAME', self.__getVarFromXML(
- xmlroot, "GUI_NAME", confname))
+ extra_config_property_loaders = getConfigPropertiesLoaders()
+ if extra_config_property_loaders:
+ for ext in extra_config_property_loaders:
+ try:
+ ext(self)
+ except Exception:
+ import traceback
+ msg = 'Error loading extra configuration property: %s' % traceback.format_exc() # repr(e)
+ self.warning(msg)
+
+ def _loadAppName(self, confname):
+ appname = self.getConfigValue("GUI_NAME")
Qt.qApp.setApplicationName(appname)
self.setWindowTitle(appname)
- def _loadOrgName(self, conf, xmlroot):
- orgname = getattr(conf, 'ORGANIZATION', self.__getVarFromXML(
- xmlroot, "ORGANIZATION", str(Qt.qApp.organizationName()) or 'Taurus'))
+ def _loadOrgName(self):
+ orgname = self.getConfigValue("ORGANIZATION")
Qt.qApp.setOrganizationName(orgname)
- def _loadCustomLogo(self, conf, xmlroot):
- custom_logo = getattr(conf, 'CUSTOM_LOGO', getattr(
- conf, 'LOGO', self.__getVarFromXML(xmlroot, "CUSTOM_LOGO", 'logos:taurus.png')))
+ def _loadCustomLogo(self):
+ custom_logo = self.getConfigValue("CUSTOM_LOGO")
if Qt.QFile.exists(custom_logo):
custom_icon = Qt.QIcon(custom_logo)
else:
@@ -1138,15 +953,8 @@ def _loadCustomLogo(self, conf, xmlroot):
if self.APPLETS_TOOLBAR_ENABLED:
self.jorgsBar.addAction(custom_icon, Qt.qApp.applicationName())
- def _loadOrgLogo(self, conf, xmlroot):
- logo = getattr(tauruscustomsettings,
- "ORGANIZATION_LOGO",
- "logos:taurus.png")
- org_logo = getattr(conf,
- "ORGANIZATION_LOGO",
- self.__getVarFromXML(xmlroot,
- "ORGANIZATION_LOGO",
- logo))
+ def _loadOrgLogo(self):
+ org_logo = self.getConfigValue("ORGANIZATION_LOGO")
if Qt.QFile.exists(org_logo):
org_icon = Qt.QIcon(org_logo)
else:
@@ -1155,12 +963,12 @@ def _loadOrgLogo(self, conf, xmlroot):
if self.APPLETS_TOOLBAR_ENABLED:
self.jorgsBar.addAction(org_icon, Qt.qApp.organizationName())
- def _loadSingleInstance(self, conf, xmlroot):
+ def _loadSingleInstance(self):
"""
if required, enforce that only one instance of this GUI can be run
"""
- single_inst = getattr(conf, 'SINGLE_INSTANCE', (self.__getVarFromXML(
- xmlroot, "SINGLE_INSTANCE", 'True').lower() == 'true'))
+ single_inst = self.getConfigValue("SINGLE_INSTANCE")
+
if single_inst:
if not self.checkSingleInstance():
msg = 'Only one instance of %s is allowed to run the same time' % (
@@ -1170,12 +978,12 @@ def _loadSingleInstance(self, conf, xmlroot):
self, 'Multiple copies', msg, Qt.QMessageBox.Abort)
sys.exit(1)
- def _loadExtraCatalogWidgets(self, conf, xmlroot):
+ def _loadExtraCatalogWidgets(self):
"""
get custom widget catalog entries
"""
# @todo: support also loading from xml
- extra_catalog_widgets = getattr(conf, 'EXTRA_CATALOG_WIDGETS', [])
+ extra_catalog_widgets = self.getConfigValue("EXTRA_CATALOG_WIDGETS")
self._extraCatalogWidgets = []
for class_name, pix_map_name in extra_catalog_widgets:
# If a relative file name is given, the conf directory will be used
@@ -1184,126 +992,23 @@ def _loadExtraCatalogWidgets(self, conf, xmlroot):
pix_map_name = os.path.join(self._confDirectory, pix_map_name)
self._extraCatalogWidgets.append((class_name, pix_map_name))
- def _loadManualUri(self, conf, xmlroot):
+ def _loadManualUri(self):
"""
manual panel
"""
- manual_uri = getattr(conf, 'MANUAL_URI',
- self.__getVarFromXML(xmlroot, "MANUAL_URI",
- taurus.Release.url))
+ manual_uri = self.getConfigValue("MANUAL_URI")
self.setHelpManualURI(manual_uri)
if self.HELP_MENU_ENABLED:
self.createPanel(self.helpManualBrowser, 'Manual', permanent=True,
icon=Qt.QIcon.fromTheme('help-browser'))
- ### SARDANA MACRO STUFF ON
- def _loadSardanaOptions(self, conf, xmlroot):
- """configure macro infrastructure"""
- ms = self._loadMacroServerName(conf, xmlroot)
- mp = self._loadMacroPanels(conf, xmlroot)
- # macro infrastructure will only be created if MACROSERVER_NAME is set
- if ms is not None and mp is True:
- from sardana.taurus.qt.qtgui.macrolistener import MacroBroker
- self.__macroBroker = MacroBroker(self)
- self._loadDoorName(conf, xmlroot)
- self._loadMacroEditorsPath(conf, xmlroot)
- pool_instruments = self._loadInstrumentsFromPool(conf, xmlroot, ms)
- return pool_instruments
-
- def _loadMacroServerName(self, conf, xmlroot):
- macro_server_name = getattr(conf, "MACROSERVER_NAME", self.__getVarFromXML(
- xmlroot, "MACROSERVER_NAME", None))
- if macro_server_name:
- self.macroserverNameChanged.emit(macro_server_name)
- return macro_server_name
-
- def _loadMacroPanels(self, conf, xmlroot):
- macro_panels = getattr(conf, "MACRO_PANELS", self.__getVarFromXML(
- xmlroot, "MACRO_PANELS", True))
- return macro_panels
-
- def _loadDoorName(self, conf, xmlroot):
- door_name = getattr(conf, "DOOR_NAME",
- self.__getVarFromXML(xmlroot, "DOOR_NAME", ''))
- if door_name:
- self.doorNameChanged.emit(door_name)
-
- def _loadMacroEditorsPath(self, conf, xmlroot):
- macro_editors_path = getattr(conf, "MACROEDITORS_PATH", self.__getVarFromXML(
- xmlroot, "MACROEDITORS_PATH", ""))
- if macro_editors_path:
- from sardana.taurus.qt.qtgui.extra_macroexecutor.macroparameterseditor.macroparameterseditor import \
- ParamEditorManager
- ParamEditorManager().parsePaths(macro_editors_path)
- ParamEditorManager().browsePaths()
-
- def _loadInstrumentsFromPool(self, conf, xmlroot, macro_server_name):
- """
- Get panel descriptions from pool if required
- """
- instruments_from_pool = getattr(conf, "INSTRUMENTS_FROM_POOL", (self.__getVarFromXML(
- xmlroot, "INSTRUMENTS_FROM_POOL", "False").lower() == "true"))
- if instruments_from_pool:
- try:
- self.splashScreen().showMessage("Gathering Instrument info from Pool")
- except AttributeError:
- pass
- pool_instruments = self.createInstrumentsFromPool(
- macro_server_name) # auto create instruments from pool
- else:
- pool_instruments = []
- return pool_instruments
- ### SARDANA MACRO STUFF OFF
-
- def _loadSynoptic(self, conf, xmlroot):
- # Synoptics
- synoptic = getattr(conf, 'SYNOPTIC', None)
- if isinstance(synoptic, string_types): # old config file style
- self.warning(
- 'Deprecated usage of synoptic keyword (now it expects a list of paths). Please update your configuration file to: "synoptic=[\'%s\']".' % synoptic)
- synoptic = [synoptic]
- if synoptic is None: # we look in the xml config file if not present in the python config
- synoptic = []
- node = xmlroot.find("SYNOPTIC")
- if (node is not None) and (node.text is not None):
- for child in node:
- s = child.get("str")
- # we do not append empty strings
- if s is not None and len(s):
- synoptic.append(s)
- for s in synoptic:
- self.createMainSynoptic(s)
-
- def _loadConsole(self, conf, xmlroot):
- """
- Deprecated CONSOLE command (if you need a IPython Console, just add a
- Panel with a `silx.gui.console.IPythonWidget`
- """
- # TODO: remove this method when making deprecation efective
- console = getattr(conf, 'CONSOLE', self.__getVarFromXML(
- xmlroot, "CONSOLE", []))
- if console:
- self.createConsole([])
-
- def _loadCustomPanels(self, conf, xmlroot, poolinstruments=None):
+ def _loadCustomPanels(self):
"""
get custom panel descriptions from the python config file, xml config and
create panels based on the panel descriptions
"""
- custom_panels = [obj for name, obj in inspect.getmembers(
- conf) if isinstance(obj, PanelDescription)]
-
- panel_descriptions = xmlroot.find("PanelDescriptions")
- if panel_descriptions is not None:
- for child in panel_descriptions:
- if child.tag == "PanelDescription":
- child_str = etree.tostring(child, encoding='unicode')
- pd = PanelDescription.fromXml(child_str)
- if pd is not None:
- custom_panels.append(pd)
-
- for p in custom_panels + poolinstruments:
+ for p in self.getConfigValue("PanelDescriptions"):
try:
try:
self.splashScreen().showMessage("Creating panel %s" % p.name)
@@ -1347,16 +1052,13 @@ def _loadCustomPanels(self, conf, xmlroot, poolinstruments=None):
w.setFormat(p.widget_formatter)
icon = p.icon
- # the pool instruments may change when the pool config changes,
- # so we do not store their config
- registerconfig = p not in poolinstruments
# create a panel
self.createPanel(
w,
p.name,
floating=p.floating,
- registerconfig=registerconfig,
+ registerconfig=True,
instrumentkey=instrumentkey,
permanent=True,
icon=icon
@@ -1371,24 +1073,12 @@ def _loadCustomPanels(self, conf, xmlroot, poolinstruments=None):
if result == Qt.QMessageBox.Abort:
sys.exit()
- def _loadCustomToolBars(self, conf, xmlroot):
+ def _loadCustomToolBars(self):
"""
get custom toolbars descriptions from the python config file, xml config and
create toolbars based on the descriptions
"""
- custom_toolbars = [obj for name, obj in inspect.getmembers(
- conf) if isinstance(obj, ToolBarDescription)]
-
- tool_bar_descriptions = xmlroot.find("ToolBarDescriptions")
- if tool_bar_descriptions is not None:
- for child in tool_bar_descriptions:
- if child.tag == "ToolBarDescription":
- child_str = etree.tostring(child, encoding='unicode')
- d = ToolBarDescription.fromXml(child_str)
- if d is not None:
- custom_toolbars.append(d)
-
- for d in custom_toolbars:
+ for d in self.getConfigValue("ToolbarDescriptinos"):
try:
try:
self.splashScreen().showMessage("Creating Toolbar %s" % d.name)
@@ -1416,32 +1106,12 @@ def _loadCustomToolBars(self, conf, xmlroot):
if result == Qt.QMessageBox.Abort:
sys.exit()
- def _loadCustomApplets(self, conf, xmlroot):
+ def _loadCustomApplets(self):
"""
get custom applet descriptions from the python config file, xml config and
create applet based on the descriptions
"""
- custom_applets = []
- # for backwards compatibility
- MONITOR = getattr(
- conf, "MONITOR", self.__getVarFromXML(xmlroot, "MONITOR", []))
- if MONITOR:
- custom_applets.append(AppletDescription(
- "monitor", classname="TaurusMonitorTiny", model=MONITOR))
-
- custom_applets += [obj for name, obj in inspect.getmembers(
- conf) if isinstance(obj, AppletDescription)]
-
- applet_descriptions = xmlroot.find("AppletDescriptions")
- if applet_descriptions is not None:
- for child in applet_descriptions:
- if child.tag == "AppletDescription":
- child_str = etree.tostring(child, encoding='unicode')
- d = AppletDescription.fromXml(child_str)
- if d is not None:
- custom_applets.append(d)
-
- for d in custom_applets:
+ for d in self.getConfigValue("AppletDescriptions"):
try:
try:
self.splashScreen().showMessage("Creating applet %s" % d.name)
@@ -1465,36 +1135,20 @@ def _loadCustomApplets(self, conf, xmlroot):
if result == Qt.QMessageBox.Abort:
sys.exit()
- def _loadExternalApps(self, conf, xmlroot):
+ def _loadExternalApps(self):
"""
add external applications from both the python and the xml config files
"""
- external_apps = [obj for name, obj in inspect.getmembers(
- conf) if isinstance(obj, ExternalApp)]
-
- ext_apps_node = xmlroot.find("ExternalApps")
- if ext_apps_node is not None:
- for child in ext_apps_node:
- if child.tag == "ExternalApp":
- child_str = etree.tostring(child, encoding='unicode')
- ea = ExternalApp.fromXml(child_str)
- if ea is not None:
- external_apps.append(ea)
-
- for a in external_apps:
+ for a in self.getConfigValue("ExternalApps"):
self._external_app_names.append(str(a.getAction().text()))
self.addExternalAppLauncher(a.getAction())
- def _loadIniFile(self, conf, xmlroot):
+ def _loadIniFile(self):
"""
get the "factory settings" filename. By default, it is called
"default.ini" and resides in the configuration dir
"""
-
- ini_file = getattr(conf, 'INIFILE', self.__getVarFromXML(
- xmlroot, "INIFILE", "default.ini"))
- # if a relative name is given, the conf dir is used as the root path
- ini_file_name = os.path.join(self._confDirectory, ini_file)
+ ini_file = self.getConfigValue("INIFILE")
# read the settings (or the factory settings if the regular file is not
# found)
@@ -1505,7 +1159,7 @@ def _loadIniFile(self, conf, xmlroot):
self.splashScreen().showMessage(msg)
except AttributeError:
pass
- self.loadSettings(factorySettingsFileName=ini_file_name)
+ self.loadSettings(factorySettingsFileName=ini_file)
def setLockView(self, locked):
self.setModifiableByUser(not locked)
diff --git a/lib/taurus/qt/qtgui/taurusgui/test/test_configs/good.py b/lib/taurus/qt/qtgui/taurusgui/test/test_configs/good.py
new file mode 100644
index 000000000..749e02dda
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/test/test_configs/good.py
@@ -0,0 +1,22 @@
+from taurus.qt.qtgui.taurusgui import utils
+
+
+GUI_NAME = "TestGUI"
+ORGANIZATION = "TestOrg"
+CUSTOM_LOGO = ""
+ORGANIZATION_LOGO = ""
+SINGLE_INSTANCE = False
+MANUAL_URI = "http://example.com"
+INIFILE = ""
+
+p1 = utils.PanelDescription(
+ "testpanel1",
+ classname="taurus.qt.qtgui.panel.TaurusForm",
+ model=["eval:1"],
+)
+
+p2 = utils.PanelDescription(
+ "testpanel2",
+ classname="taurus.qt.qtgui.panel.TaurusForm",
+ model=["eval:2"],
+)
diff --git a/lib/taurus/qt/qtgui/taurusgui/test/test_python_config.py b/lib/taurus/qt/qtgui/taurusgui/test/test_python_config.py
new file mode 100644
index 000000000..c72d6dfcc
--- /dev/null
+++ b/lib/taurus/qt/qtgui/taurusgui/test/test_python_config.py
@@ -0,0 +1,26 @@
+import os
+
+from taurus.qt.qtgui.taurusgui import TaurusGui
+from taurus.qt.qtgui.panel import TaurusForm
+
+
+def test_good_config(qtbot):
+ conf = os.path.join(os.path.abspath(__file__), "test_configs", "good.py")
+ gui = TaurusGui(confname=conf, configRecursionDepth=0)
+
+ qtbot.addWidget(gui)
+ assert gui.getConfigValue("GUI_NAME") == "TestGUI"
+ assert gui.getConfigValue("ORGANIZATION") == "TestOrg"
+ assert gui.getConfigValue("CUSTOM_LOGO") == ""
+ assert gui.getConfigValue("ORGANIZATION_LOGO") == ""
+ assert gui.getConfigValue("SINGLE_INSTANCE") is False
+ assert gui.getConfigValue("MANUAL_URI") == "http://example.com"
+ assert gui.getConfigValue("INIFILE") == ""
+
+ w1 = gui.getPanel('testpanel1').widget()
+ qtbot.addWidget(w1)
+ assert isinstance(w1, TaurusForm)
+
+ w2 = gui.getPanel('testpanel2').widget()
+ qtbot.addWidget(w2)
+ assert isinstance(w2, TaurusForm)
diff --git a/lib/taurus/qt/qtgui/taurusgui/utils.py b/lib/taurus/qt/qtgui/taurusgui/utils.py
index a1d9ade0c..8b54eead9 100644
--- a/lib/taurus/qt/qtgui/taurusgui/utils.py
+++ b/lib/taurus/qt/qtgui/taurusgui/utils.py
@@ -113,6 +113,14 @@ def fromXml(xmlstring):
return ExternalApp(" ".join((command, params)), text=text, icon=icon)
+ def to_dict(self):
+ tmp = {
+ "args": self.args,
+ "kwargs": self.kwargs,
+ }
+
+ return tmp
+
class TaurusGuiComponentDescription(object):
'''
@@ -343,6 +351,23 @@ def fromXml(xmlstring):
floating=floating, sharedDataWrite=sharedDataWrite, sharedDataRead=sharedDataRead,
model=model)
+ def to_dict(self):
+ """
+ Return dictionary representation of data
+ """
+ tmp = {
+ "name": self.name,
+ "classname": self.classname,
+ "modulename": self.modulename,
+ "widgetname": self.widgetname,
+ "floating": self.floating,
+ "sharedDataWrite": self.sharedDataWrite,
+ "sharedDataRead": self.sharedDataRead,
+ "model": self.model,
+ }
+
+ return tmp
+
#=========================================================================
# Properties
#=========================================================================
@@ -433,6 +458,22 @@ def fromPanel(panel):
widget_properties=panel.widget_properties
)
+ def to_dict(self):
+ """
+ Return dictionary representation of data
+ """
+ from_parent = TaurusGuiComponentDescription.to_dict(self)
+ custom = {
+ "instrumentkey": self.instrumentkey,
+ "icon": self.icon,
+ "model_in_config": self.model_in_config,
+ "modifiable_by_user": self.modifiable_by_user,
+ "widget_formatter": self.widget_formatter,
+ "widget_properties": self.widget_properties,
+ }
+ from_parent.update(custom)
+ return from_parent
+
class ToolBarDescription(TaurusGuiComponentDescription):
'''
diff --git a/setup.py b/setup.py
index 3ae782d9f..114f5744a 100644
--- a/setup.py
+++ b/setup.py
@@ -136,6 +136,23 @@ def get_release_info():
'{:.5f} = taurus.qt.qtgui.base:floatFormatter',
]
+config_loaders = [
+ 'taurus.py = taurus.qt.qtgui.taurusgui.config_loader.pyconf:PyConfigLoader',
+ 'taurus.json = taurus.qt.qtgui.taurusgui.config_loader.jsonconf:JsonConfigLoader',
+ 'taurus.xml = taurus.qt.qtgui.taurusgui.config_loader.xmlconf:XmlConfigLoader',
+]
+
+config_properties = [
+ 'DOOR_NAME = taurus.qt.qtgui.taurusgui.config_properties.sardana:loadDoorName',
+ 'MACROSERVER_NAME = taurus.qt.qtgui.taurusgui.config_properties.sardana:loadMacroServerName',
+ 'MACRO_PANELS = taurus.qt.qtgui.taurusgui.config_properties.sardana:loadMacroBroker',
+ 'INSTRUMENTS_FROM_POOL = taurus.qt.qtgui.taurusgui.config_properties.sardana:loadInstrumentsFromPool',
+ 'MONITOR = taurus.qt.qtgui.taurusgui.config_properties.deprecated:loadMonitor',
+ 'CONSOLE = taurus.qt.qtgui.taurusgui.config_properties.deprecated:loadConsole',
+ 'XML_CONF = taurus.qt.qtgui.taurusgui.config_properties.bck_compat:loadXmlConf',
+ 'SYNOPTIC = taurus.qt.qtgui.taurusgui.config_properties.jdraw:loadSynoptic'
+]
+
entry_points = {
'console_scripts': console_scripts,
'taurus.cli.subcommands': taurus_subcommands,
@@ -145,6 +162,8 @@ def get_release_info():
'taurus.trend.alts': trend_alternatives,
'taurus.trend2d.alts': trend2d_alternatives,
'taurus.image.alts': image_alternatives,
+ 'taurus.gui.loaders': config_loaders,
+ 'taurus.gui.properties' : config_properties,
}
classifiers = [