summaryrefslogtreecommitdiff
path: root/lib/taurus/qt/qtgui/util
diff options
context:
space:
mode:
Diffstat (limited to 'lib/taurus/qt/qtgui/util')
-rw-r--r--lib/taurus/qt/qtgui/util/__init__.py37
-rw-r--r--lib/taurus/qt/qtgui/util/qdraganddropdebug.py64
-rw-r--r--lib/taurus/qt/qtgui/util/taurusaction.py317
-rw-r--r--lib/taurus/qt/qtgui/util/taurusactionfactory.py147
-rw-r--r--lib/taurus/qt/qtgui/util/tauruscolor.py93
-rw-r--r--lib/taurus/qt/qtgui/util/taurusropepatch.py95
-rw-r--r--lib/taurus/qt/qtgui/util/taurusscreenshot.py136
-rw-r--r--lib/taurus/qt/qtgui/util/tauruswidget_qtdesignerplugin_template21
-rw-r--r--lib/taurus/qt/qtgui/util/tauruswidget_template141
-rw-r--r--lib/taurus/qt/qtgui/util/tauruswidgetfactory.py209
-rw-r--r--lib/taurus/qt/qtgui/util/tauruswidgettree.py229
-rw-r--r--lib/taurus/qt/qtgui/util/test/__init__.py26
-rw-r--r--lib/taurus/qt/qtgui/util/test/test_ui/__init__.py29
-rw-r--r--lib/taurus/qt/qtgui/util/test/test_ui/mywidget3/__init__.py34
-rw-r--r--lib/taurus/qt/qtgui/util/test/test_ui/mywidget3/ui/MyWidget3.ui32
-rw-r--r--lib/taurus/qt/qtgui/util/test/test_ui/test_ui.py102
-rw-r--r--lib/taurus/qt/qtgui/util/test/test_ui/ui/MyWidget1.ui32
-rw-r--r--lib/taurus/qt/qtgui/util/test/test_ui/ui/mywidget2/mywidget2_custom.ui32
-rw-r--r--lib/taurus/qt/qtgui/util/ui.py187
-rw-r--r--lib/taurus/qt/qtgui/util/widgetgen.py114
20 files changed, 2077 insertions, 0 deletions
diff --git a/lib/taurus/qt/qtgui/util/__init__.py b/lib/taurus/qt/qtgui/util/__init__.py
new file mode 100644
index 00000000..44c8730f
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/__init__.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""This package provides a set of taurus wiget utilities like color management,
+configuration, actions."""
+
+__docformat__ = 'restructuredtext'
+
+from .taurusactionfactory import *
+from .taurusaction import *
+from .tauruscolor import *
+from .tauruswidgetfactory import *
+from .taurusscreenshot import *
+from .qdraganddropdebug import *
+from .ui import *
diff --git a/lib/taurus/qt/qtgui/util/qdraganddropdebug.py b/lib/taurus/qt/qtgui/util/qdraganddropdebug.py
new file mode 100644
index 00000000..c767e011
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/qdraganddropdebug.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+__all__ = ["DropDebugger"]
+__docformat__ = 'restructuredtext'
+
+from taurus.external.qt import Qt
+
+class DropDebugger(Qt.QLabel):
+ '''A simple utility for debugging drag&drop.
+ This widget will accept drops and show a pop-up with the contents
+ of the MIME data passed in the drag&drop'''
+
+ def __init__(self, parent=None):
+ Qt.QLabel.__init__(self, parent)
+ self.setAcceptDrops(True)
+ self.setText('Drop something here')
+ self.setMinimumSize(300,200)
+ self.setWindowTitle('Drag&Drop Debugger')
+
+ def dragEnterEvent(self,event):
+ event.acceptProposedAction()
+
+ def dropEvent(self, event):
+ '''reimplemented to support drag&drop of models. See :class:`QWidget`'''
+ msg = '<b>MIMETYPE</b>: DATA. <ul>'
+ mimedata = event.mimeData()
+ for format in mimedata.formats():
+ data = mimedata.data(format)
+ msg += '<li><b>{0}</b>: "{1}"</li>'.format(format, data)
+ msg+='</ul>'
+ Qt.QMessageBox.information( self, "Drop event received", msg)
+
+
+if __name__=='__main__':
+ import sys
+ from taurus.qt.qtgui.application import TaurusApplication
+
+ app = TaurusApplication()
+ w=DropDebugger()
+ w.show()
+ sys.exit(app.exec_())
diff --git a/lib/taurus/qt/qtgui/util/taurusaction.py b/lib/taurus/qt/qtgui/util/taurusaction.py
new file mode 100644
index 00000000..a53767dc
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/taurusaction.py
@@ -0,0 +1,317 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""This module is designed to provide a library of taurus Qt actions"""
+
+#__all__ = []
+
+__docformat__ = 'restructuredtext'
+
+import os
+import xml.dom.minidom
+
+from taurus.external.qt import Qt
+from taurus.qt.qtcore.configuration import BaseConfigurableClass
+from taurus.qt.qtgui.resource import getThemeIcon
+
+class ExternalAppAction(Qt.QAction, BaseConfigurableClass):
+ """ An specialized QAction for launching external applications
+
+ Signals: apart of those from QAction, it emits a "cmdArgsChanged" signal
+ with the current cmdArgs list as its argument.
+ """
+ DEFAULT_ICON_NAME = 'application-x-executable'
+ def __init__(self, cmdargs, text=None, icon=None, parent=None, interactive=True):
+ '''creator
+
+ :param cmdargs: (list<str> or str) A list of strings to be passed to
+ :meth:`subprocess.Popen` for launching the external
+ application. It can also be a single string containing a
+ command. See :meth:`setCmdArgs`
+ :param text: (str) see :class:`Qt.QAction`
+ :param icon: (QIcon or any other object that can be passed to QIcon creator) see :class:`Qt.QAction`
+ :param parent: (QObject) The parent object
+ '''
+ if isinstance(cmdargs, (basestring, Qt.QString)):
+ import shlex
+ cmdargs = shlex.split(str(cmdargs))
+ self.path = os.path.realpath(cmdargs and cmdargs[0] or '')
+ if text is None: text = os.path.basename(cmdargs and cmdargs[0] or '')
+ if icon is None:
+ icon = getThemeIcon(self.DEFAULT_ICON_NAME)
+ elif isinstance(icon,basestring):
+ tmp = getThemeIcon(icon)
+ if not tmp.isNull(): icon=tmp
+
+ Qt.QAction.__init__(self, Qt.QIcon(icon), text, parent)
+ BaseConfigurableClass.__init__(self)
+ self.interactive = interactive
+ self._process = []
+ self.setCmdArgs(cmdargs)
+ self.connect(self, Qt.SIGNAL("triggered()"), self.actionTriggered)
+ self.setToolTip("Launches %s (external application)"%text)
+ self.registerConfigProperty(self.cmdArgs, self.setCmdArgs, 'cmdArgs')
+
+ def setCmdArgs(self, cmdargs):
+ '''Sets the command args for executing this external application.
+
+ It emits the "cmdArgsChanged" signal with the new cmdArgs list
+
+ :param cmdargs: (list<str> or str) A list of strings to be passed to
+ :meth:`subprocess.Popen` for launching the external
+ application. It can also be a string containing a
+ command, which will be automatically converted to a list
+ '''
+ if isinstance(cmdargs, (basestring, Qt.QString)):
+ import shlex
+ cmdargs = shlex.split(str(cmdargs))
+ self.__cmdargs = cmdargs
+ self.emit(Qt.SIGNAL("cmdArgsChanged"), self.__cmdargs)
+
+ def cmdArgs(self):
+ return self.__cmdargs
+
+ @Qt.pyqtSignature("triggered()")
+ def actionTriggered(self,args=None):
+ '''launches the external application as a subprocess'''
+ import subprocess
+ try:
+ if args is not None:
+ if isinstance(args, (basestring, Qt.QString)):
+ import shlex
+ args = shlex.split(str(args))
+ args = self.cmdArgs()+args
+ else:
+ args = self.cmdArgs()
+ if any(args):
+ #Qt.QMessageBox.warning(self.parentWidget(),'Warning','In ExternalAppAction(%s)'%args)
+ self._process.append(subprocess.Popen(args))
+ return True
+ else:
+ return False
+ except OSError:
+ err = "Error launching %s"%unicode(self.text())
+ msg = "Cannot launch application:\n" + \
+ " ".join(self.__cmdargs) + \
+ "\nHint: Check that %s is installed and in the path"%unicode(self.text())
+ if self.interactive:
+ Qt.QMessageBox.warning(self.parentWidget(), err, msg)
+ from taurus.core.util import Logger
+ Logger().warning('%s:\n%s'%(err,msg))
+ return False
+
+ def kill(self):
+ #Kills all processes opened by this application
+ [p.kill() for p in self._process]
+
+ def check(self):
+ '''Returns True if the application is available for executing
+
+ :return: (bool)
+ '''
+ #raise NotImplementedError #@todo: implement a checker (check if self.cmdargs[0] is in the execution path and is executable
+ path = os.path.realpath(self.cmdArgs()[0])
+ try:
+ os.stat(path)
+ return True
+ except:
+ return False
+
+class TaurusMenu(Qt.QMenu):
+ """Base class for Taurus Menus"""
+
+ def __init__(self, parent):
+ Qt.QMenu.__init__(self, parent)
+
+ def build(self, data):
+ m_node = xml.dom.minidom.parseString(data).childNodes[0]
+ self.buildFromXML(m_node)
+
+ def getActionFactory(self):
+ import taurusactionfactory
+ return taurusactionfactory.ActionFactory()
+
+ def buildFromXML(self, m_node):
+ widget = self.parent()
+ if m_node.hasAttribute('label'):
+ self.setTitle(m_node.getAttribute('label'))
+
+ for node in m_node.childNodes:
+ name = node.nodeName
+ if name == 'Menu':
+ m = self.getActionFactory().buildMenu(widget, node)
+ if m:
+ self.addMenu(m)
+ else:
+ a = self.getActionFactory().buildAction(widget, node)
+ if a:
+ self.addAction(a)
+
+
+class TaurusAction(Qt.QAction):
+ """Base class for Taurus Actions"""
+
+ def __init__(self, parent):
+ import taurus.qt.qtgui.base
+
+ if (parent is None) or \
+ (not isinstance(parent, Qt.QWidget)) or \
+ (not isinstance(parent, taurus.qt.qtgui.base.TaurusBaseComponent)):
+ raise RuntimeError("Invalid parent. Must be a valid Taurus widget.")
+
+ Qt.QAction.__init__(self, parent)
+
+ self.connect(parent, Qt.SIGNAL('modelChanged(const QString &)'), self.modelChanged)
+ self.connect(self, Qt.SIGNAL("triggered()"), self.actionTriggered)
+
+ self.update()
+
+ def update(self):
+ model = self.parent().getModelObj()
+ self.setDisabled(model is None)
+
+ @Qt.pyqtSignature("modelChanged(const QString &)")
+ def modelChanged(self, modelName):
+ self.update()
+
+ @Qt.pyqtSignature("triggered()")
+ def actionTriggered(self):
+ pass
+
+
+class SeparatorAction(TaurusAction):
+
+ menuID = "_Separator_"
+
+ def __init__(self, parent=None):
+ Qt.QAction.__init__(self, parent)
+ self.setSeparator(True)
+
+
+class AttributeHistoryAction(TaurusAction):
+
+ menuID = "AttrHistory"
+
+ def __init__(self, parent=None):
+ TaurusAction.__init__(self, parent)
+ self.setText("Show history...")
+
+ def actionTriggered(self):
+ dialog = Qt.QDialog()
+ dialog.exec_()
+
+
+class AttributeAllConfigAction(TaurusAction):
+
+ menuID = "AttrConfig"
+
+ def __init__(self, parent=None):
+ TaurusAction.__init__(self, parent)
+ self.setText("All...")
+
+ def actionTriggered(self):
+ #raise NotImplementedError('This action is not yet implemented')
+ taurus_widget = self.parent()
+ from taurus.qt.qtgui.dialog.taurusconfigurationdialog import TaurusConfigurationDialog
+ d = TaurusConfigurationDialog()
+ d.setModel(taurus_widget.getModelName())
+ d.exec_()
+
+
+class AttributeMonitorDeviceAction(TaurusAction):
+
+ menuID = "MonitorDevice"
+
+ def __init__(self, parent=None):
+ TaurusAction.__init__(self, parent)
+ self.setText("&Monitor device ...")
+
+ def actionTriggered(self):
+ taurus_widget = self.parent()
+ model_name = taurus_widget.getModelName()
+ w = model_name.split("/")
+ if len(w) == 3:
+ dev_name = model_name
+ elif len(w) == 4:
+ dev_name = w[0] + "/" + w[1] + "/" + w[2]
+ elif len(w) == 5:#FB: If the first parameter is the database
+ dev_name = w[1] + "/" + w[2] + "/" + w[3]
+ else:
+ return
+
+ cmd = "atkpanel " + dev_name + " &"
+ os.system(cmd)
+
+
+class AttributeImageDisplayAction(TaurusAction):
+
+ menuID = "ImageDisplay"
+
+ def __init__(self, parent=None):
+ TaurusAction.__init__(self, parent)
+ self.setText("&Image Display ...")
+
+ def actionTriggered(self):
+ taurus_widget = self.parent()
+ model_name = taurus_widget.getModelName()
+ w = model_name.split("/")
+ if len(w) == 3:
+ dev_name = model_name
+ elif len(w) == 4:
+ dev_name = w[0] + "/" + w[1] + "/" + w[2]
+ else:
+ return
+
+ attr_name = dev_name + "/Image"
+
+ import qub
+ im = qub._TaurusQubDataImageDisplay(data=attr_name)
+ im.show()
+
+
+class AttributeMenu(TaurusMenu):
+
+ menuID = "AttrMenu"
+ menuData = "<Menu label='Attribute'>" \
+ "<MenuItem class='AttrHistory'/>"\
+ "<MenuItem class='_Separator_'/>"\
+ "<Menu class='AttrConfig'/>"\
+ "</Menu>"
+
+ def __init__(self, parent):
+ TaurusMenu.__init__(self, parent)
+ self.build(self.menuData)
+
+
+class ConfigurationMenu(TaurusMenu):
+ menuID = "AttrConfigMenu"
+ menuData = "<Menu label='Configuration'>" \
+ "<MenuItem class='AttrConfig'/>"\
+ "</Menu>"
+
+ def __init__(self, parent):
+ TaurusMenu.__init__(self, parent)
+ self.build(self.menuData)
+
diff --git a/lib/taurus/qt/qtgui/util/taurusactionfactory.py b/lib/taurus/qt/qtgui/util/taurusactionfactory.py
new file mode 100644
index 00000000..53ced986
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/taurusactionfactory.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""This module is designed to provide a factory class for taurus Qt actions """
+
+__all__ = ["ActionFactory"]
+
+__docformat__ = 'restructuredtext'
+
+from taurus.core.util.log import Logger
+from taurus.core.util.singleton import Singleton
+from taurus.external.qt import Qt
+from taurus.qt.qtgui.resource import getThemeIcon
+
+import taurusaction
+
+
+class ActionFactory(Singleton, Logger):
+ """A Singleton class designed to provide Action related objects."""
+
+ def __init__(self):
+ """ Initialization. Nothing to be done here for now."""
+ pass
+
+ def init(self, *args):
+ """Singleton instance initialization."""
+ self.call__init__(Logger, 'ActionFactory')
+ self.actions = self.__getActions()
+ self.menus = self.__getMenus()
+
+ def __getClasses(self, super_class):
+ ret = {}
+ klass_type = type(super_class)
+ for name in dir(taurusaction):
+ klass = getattr(taurusaction, name)
+ if klass == super_class:
+ continue
+ if (type(klass) == klass_type and issubclass(klass, super_class)):
+ ret[klass.menuID] = klass
+ return ret
+
+ def __getActions(self):
+ """Calculates the map of existing action classes"""
+ return self.__getClasses(taurusaction.TaurusAction)
+
+ def __getMenus(self):
+ """Calculates the map of existing menu classes"""
+ return self.__getClasses(taurusaction.TaurusMenu)
+
+ def getActions(self):
+ return self.actions
+
+ def getMenus(self):
+ return self.menus
+
+ def getNewAction(self, widget, id):
+ klass = self.actions.get(id)
+ if klass is None:
+ return None
+ return klass(widget)
+
+ def getNewMenu(self, widget, data):
+ import xml.dom.minidom
+ doc = xml.dom.minidom.parseString(data)
+ m_node = doc.childNodes[0]
+ return self.buildMenu(widget, m_node)
+
+ def buildAction(self, widget, a_node):
+ if not a_node.hasAttribute('class'):
+ return None
+
+ id = a_node.getAttribute('class')
+ action = self.getNewAction(widget, id)
+
+ # if node has alternative label, display it instead
+ if a_node.hasAttribute('label'):
+ action.setText(a_node.getAttribute('label'))
+
+ if a_node.hasAttribute('checkable'):
+ action.setCheckable(bool(a_node.getAttribute('checkable')))
+
+ if a_node.hasAttribute('icon'):
+ icon = a_node.getAttribute('icon')
+ #TODO
+ #action.setIcon(icon)
+ return action
+
+ def buildMenu(self, widget, m_node):
+ menu = None
+ if m_node.hasAttribute('class'):
+ klass = self.menus.get(m_node.getAttribute('class'))
+ if klass is None:
+ return None
+ menu = klass(widget)
+ else:
+ menu = taurusaction.TaurusMenu(widget)
+ menu.buildFromXML(m_node)
+ return menu
+
+ def createAction(self, parent, text, shortcut=None, icon=None, tip=None,
+ toggled=None, triggered=None, data=None,
+ context=Qt.Qt.WindowShortcut):
+ """Create a QAction"""
+ action = Qt.QAction(text, parent)
+ if triggered is not None:
+ parent.connect(action, Qt.SIGNAL("triggered()"), triggered)
+ if toggled is not None:
+ parent.connect(action, Qt.SIGNAL("toggled(bool)"), toggled)
+ action.setCheckable(True)
+ if icon is not None:
+ if isinstance(icon, (str, unicode)):
+ icon = getThemeIcon(icon)
+ action.setIcon( icon )
+ if shortcut is not None:
+ action.setShortcut(shortcut)
+ if tip is not None:
+ action.setToolTip(tip)
+ action.setStatusTip(tip)
+ if data is not None:
+ action.setData(data)
+ #TODO: Hard-code all shortcuts and choose context=Qt.WidgetShortcut
+ # (this will avoid calling shortcuts from another dockwidget
+ # since the context thing doesn't work quite well with these widgets)
+ action.setShortcutContext(context)
+ return action \ No newline at end of file
diff --git a/lib/taurus/qt/qtgui/util/tauruscolor.py b/lib/taurus/qt/qtgui/util/tauruscolor.py
new file mode 100644
index 00000000..eb450efe
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/tauruscolor.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""This module provides Qt color management for taurus"""
+
+__docformat__ = 'restructuredtext'
+
+from taurus.external.qt import Qt
+
+from taurus.core.util.colors import ColorPalette, \
+ DEVICE_STATE_DATA, ATTRIBUTE_QUALITY_DATA
+
+class QtColorPalette(ColorPalette):
+
+ def __init__(self, dat, int_decoder_dict):
+ ColorPalette.__init__(self, dat, int_decoder_dict)
+ self._qcolor_cache_fg = dict()
+ self._qcolor_cache_bg = dict()
+ self._qbrush_cache_fg = dict()
+ self._qbrush_cache_bg = dict()
+ self._qvariant_cache_fg = dict()
+ self._qvariant_cache_bg = dict()
+
+ def qbrush(self, stoq):
+ #print stoq
+ """Returns the brush for the specified state or quality"""
+ name = self._decoder(stoq)
+
+ f = self._qbrush_cache_fg
+ b = self._qbrush_cache_bg
+ if not f.has_key(name):
+ f[name] = Qt.QBrush(self.qcolor(stoq)[1])
+
+ if not b.has_key(name):
+ b[name] = Qt.QBrush(self.qcolor(stoq)[0])
+ if name == 'None':
+ b[name].setStyle(Qt.Qt.BDiagPattern)
+
+ return ( b[name], f[name] )
+
+ def qcolor(self, stoq):
+ """Returns the color for the specified state or quality"""
+ name = self._decoder(stoq)
+
+ f = self._qcolor_cache_fg
+ b = self._qcolor_cache_bg
+ if not f.has_key(name):
+ f[name] = Qt.QColor(self.number(name, True))
+
+ if not b.has_key(name):
+ b[name] = Qt.QColor(self.number(name))
+
+ return ( b[name], f[name] )
+
+ def qvariant(self, stoq):
+ """Returns the color for the specified state or quality"""
+ name = self._decoder(stoq)
+
+ f = self._qvariant_cache_fg
+ b = self._qvariant_cache_bg
+ if not f.has_key(name):
+ (back,fore) = self.qcolor(name)
+ f[name] = Qt.QVariant(fore)
+ b[name] = Qt.QVariant(back)
+
+ return ( b[name], f[name] )
+
+import PyTango
+
+QT_DEVICE_STATE_PALETTE = QtColorPalette(DEVICE_STATE_DATA, PyTango.DevState)
+QT_ATTRIBUTE_QUALITY_PALETTE = QtColorPalette(ATTRIBUTE_QUALITY_DATA, PyTango.AttrQuality)
diff --git a/lib/taurus/qt/qtgui/util/taurusropepatch.py b/lib/taurus/qt/qtgui/util/taurusropepatch.py
new file mode 100644
index 00000000..4c7a4291
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/taurusropepatch.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""Rope patch for better performances. Based on spyderlib.rope_patch"""
+
+__all__ = ["apply"]
+
+__docformat__ = 'restructuredtext'
+
+def apply():
+ """Monkey patching rope for better performances"""
+ import rope
+ if rope.VERSION not in ('0.9.3', '0.9.2'):
+ raise ImportError, "rope %s can't be patched" % rope.VERSION
+
+ # Patching pycore.PyCore, so that forced builtin modules (i.e. modules
+ # that were declared as 'extension_modules' in rope preferences)
+ # will be indeed recognized as builtins by rope, as expected
+ from rope.base import pycore
+ class PatchedPyCore(pycore.PyCore):
+ def get_module(self, name, folder=None):
+ """Returns a `PyObject` if the module was found."""
+ # check if this is a builtin module
+ pymod = self._builtin_module(name)
+ if pymod is not None:
+ return pymod
+ module = self.find_module(name, folder)
+ if module is None:
+ raise pycore.ModuleNotFoundError(
+ 'Module %s not found' % name)
+ return self.resource_to_pyobject(module)
+ pycore.PyCore = PatchedPyCore
+
+ # Patching BuiltinFunction for the calltip/doc functions to be
+ # able to retrieve the function signatures with forced builtins
+ from rope.base import builtins, pyobjects
+ from spyderlib.utils.dochelpers import getargs
+ class PatchedBuiltinFunction(builtins.BuiltinFunction):
+ def __init__(self, returned=None, function=None, builtin=None,
+ argnames=[], parent=None):
+ builtins._BuiltinElement.__init__(self, builtin, parent)
+ pyobjects.AbstractFunction.__init__(self)
+ self.argnames = argnames
+ if not argnames and builtin:
+ self.argnames = getargs(self.builtin)
+ if self.argnames is None:
+ self.argnames = []
+ self.returned = returned
+ self.function = function
+ builtins.BuiltinFunction = PatchedBuiltinFunction
+
+ # Patching BuiltinName for the go to definition feature to simply work
+ # with forced builtins
+ from rope.base import libutils
+ import inspect
+ class PatchedBuiltinName(builtins.BuiltinName):
+ def _pycore(self):
+ p = self.pyobject
+ while p.parent is not None:
+ p = p.parent
+ if isinstance(p, builtins.BuiltinModule) and p.pycore is not None:
+ return p.pycore
+ def get_definition_location(self):
+ if not inspect.isbuiltin(self.pyobject):
+ _lines, lineno = inspect.getsourcelines(self.pyobject.builtin)
+ path = inspect.getfile(self.pyobject.builtin)
+ pycore = self._pycore()
+ if pycore and pycore.project:
+ resource = libutils.path_to_resource(pycore.project, path)
+ module = pyobjects.PyModule(pycore, None, resource)
+ return (module, lineno)
+ return (None, None)
+ builtins.BuiltinName = PatchedBuiltinName
diff --git a/lib/taurus/qt/qtgui/util/taurusscreenshot.py b/lib/taurus/qt/qtgui/util/taurusscreenshot.py
new file mode 100644
index 00000000..8dea6e6d
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/taurusscreenshot.py
@@ -0,0 +1,136 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""This module provides Qt color management for taurus"""
+
+__all__ = ["Grabber", "grabWidget"]
+
+__docformat__ = 'restructuredtext'
+
+import time
+import threading
+import os.path
+
+from taurus.external.qt import Qt
+from taurus.core.util.log import Logger
+
+_LOGGER = None
+
+def _getLogger():
+ global _LOGGER
+ if _LOGGER is None:
+ _LOGGER = Logger('Grabber')
+ return _LOGGER
+
+
+class GrabberThread(threading.Thread):
+
+ def __init__(self, widget, fileName, period):
+ threading.Thread.__init__(self, name="Grabber")
+ self.daemon = True
+ if period <= 0:
+ raise ValueError("period MUST be greater than 0")
+ self._period = period
+ self._continue = True
+ self._grabber = Grabber(widget, fileName)
+
+ def run(self):
+ period = self._period
+ while self._continue:
+ self._grabber.grabTrigger()
+ time.sleep(period)
+
+ def stop(self):
+ self._continue = False
+
+
+class Grabber(Qt.QObject, Logger):
+
+ def __init__(self, widget, fileName):
+ Qt.QObject.__init__(self)
+ Logger.__init__(self)
+ self._widget = widget
+ self._fileName = fileName
+ self.connect(self, Qt.SIGNAL("grab"), self.onGrab)
+
+ def grabTrigger(self):
+ self.emit(Qt.SIGNAL("grab"))
+
+ def onGrab(self):
+ Grabber._grabWidget(self._widget, self._fileName)
+
+ @staticmethod
+ def _grabWidget(widget, fileName):
+ _getLogger().debug("Grabbing widget to '%s':", fileName)
+ try:
+ pixmap = Qt.QPixmap.grabWidget(widget)
+ if fileName.endswith('.svg'):
+ from taurus.external.qt import QtSvg
+ generator = QtSvg.QSvgGenerator()
+ generator.setFileName(fileName)
+ generator.setSize(pixmap.size());
+ if hasattr(generator, 'setViewBox'):
+ viewBox = Qt.QRect(Qt.QPoint(0, 0), pixmap.size())
+ generator.setViewBox(viewBox)
+ generator.setTitle("Taurus widget")
+ generator.setDescription("An SVG drawing created by the taurus "
+ "widget grabber")
+ painter = Qt.QPainter()
+ painter.begin(generator)
+ try:
+ painter.drawPixmap(0, 0, -1, -1, pixmap)
+ finally:
+ painter.end()
+ else:
+ pixmap.save(fileName, quality=100)
+ except:
+ _getLogger().warning("Could not save file into '%s':", fileName,
+ exc_info=1)
+
+ @staticmethod
+ def grabWidget(widget, fileName, period=None):
+ """Grabs the given widget into the given image filename. If period is
+ not given (or given with None) means grab immediately once and return.
+ If period is given and >0 means grab the image every period seconds
+
+ .. warning:
+ this method **MUST** be called from the same thread which created
+ the widget
+
+ :param widget: (Qt.QWidget) the qt widget to be grabbed
+ :param fileName: (str) the name of the image file
+ :param period: (float) period (seconds)
+ """
+ if period is None:
+ return Grabber._grabWidget(widget, fileName)
+ ret = GrabberThread(widget, fileName, period)
+ ret.start()
+ return ret
+
+
+def grabWidget(widget, fileName, period=None):
+ return Grabber.grabWidget(widget, fileName, period=period)
+
+grabWidget.__doc__ = Grabber.grabWidget.__doc__
diff --git a/lib/taurus/qt/qtgui/util/tauruswidget_qtdesignerplugin_template b/lib/taurus/qt/qtgui/util/tauruswidget_qtdesignerplugin_template
new file mode 100644
index 00000000..d76bfef9
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/tauruswidget_qtdesignerplugin_template
@@ -0,0 +1,21 @@
+import tauplugin
+
+from <_Module_> import <_TauClass_>
+
+class <_TauClass_>Plugin(tauplugin.TauWidgetPlugin):
+
+ """<_TauClass_>Plugin(tauplugin.TauWidgetPlugin)
+
+ Provides a Python custom plugin for Qt Designer by implementing the
+ QDesignerCustomWidgetPlugin via a PyQt-specific custom plugin class.
+ """
+
+ def getWidgetClass(self):
+ return <_TauClass_>
+
+ def getIconName(self):
+ # give your widget icon file name here
+ return 'label.png'
+
+ def includeFile(self):
+ return "<_Module_>" \ No newline at end of file
diff --git a/lib/taurus/qt/qtgui/util/tauruswidget_template b/lib/taurus/qt/qtgui/util/tauruswidget_template
new file mode 100644
index 00000000..3cab2f00
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/tauruswidget_template
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+
+""" module containing the Tau Widget: <_TauClass_> """
+
+from taurus.qt import QtGui, QtCore
+import tau.core
+from tau.widget import TauBaseWidget
+
+class <_TauClass_>(<_SuperClass_>, TauBaseWidget):
+ """ <_TauClass_> is a Tau widget designed to represent..."""
+
+ #---------------------------------------------------------------------------
+ # Write your own code here to define the signals generated by this widget
+ #
+ __pyqtSignals__ = ("modelChanged(const QString &)",)
+
+ def __init__(self, parent = None, designMode = False):
+ name = self.__class__.__name__
+
+ self.call__init__wo_kw(<_SuperClass_>, parent)
+ self.call__init__(TauBaseWidget, name, parent, designMode=designMode)
+
+ self.defineStyle()
+
+ def defineStyle(self):
+ """ Defines the initial style for the widget """
+ #-----------------------------------------------------------------------
+ # Write your own code here to set the initial style of your widget
+ #
+ self.updateStyle()
+
+ def sizeHint(self):
+ return <_SuperClass_>.sizeHint(self)
+
+ def minimumSizeHint(self):
+ return <_SuperClass_>.minimumSizeHint(self)
+
+ #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
+ # TauBaseWidget over writing
+ #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
+
+ def getModelClass(self):
+ #-----------------------------------------------------------------------
+ # [MANDATORY]
+ # Replace your own code here
+ # ex.: return tau.core.Attribute
+ raise RuntimeError("Forgot to overwrite %s.getModelClass" % str(self))
+
+
+ def attach(self):
+ """Attaches the widget to the model"""
+
+ if self.isAttached():
+ return True
+
+ #-----------------------------------------------------------------------
+ # Write your own code here before attaching widget to attribute connect
+ # the proper signal so that the first event is correctly received by the
+ # widget
+ #
+ # Typical code is:
+ #self.connect(self, QtCore.SIGNAL('valueChangedDueToEvent(QString)'),
+ # self.setTextValue)
+
+
+ ret = TauBaseWidget.attach(self)
+
+ # by default enable/disable widget according to attach state
+ self.setEnabled(ret)
+ return ret
+
+ def detach(self):
+ """Detaches the widget from the model"""
+
+ TauBaseWidget.detach(self)
+
+ #-----------------------------------------------------------------------
+ # Write your own code here after detaching the widget from the model
+ #
+ # Typical code is:
+ #self.emit(QtCore.SIGNAL('valueChangedDueToEvent(QString)'),
+ # QtCore.QString(value_str))
+ #self.disconnect(self, QtCore.SIGNAL('valueChangedDueToEvent(QString)'),
+ # self.setTextValue)
+
+ # by default disable widget when dettached
+ self.setEnabled(False)
+
+ def eventReceived(self, src, type, data):
+ """ eventReceived(src, TauEventType type, data) -> None
+
+ Called by the model when an event is fired.
+
+ Parameters:
+ src: Source of the event. Usually a tau.core.Attribute or
+ tau.core.Device object
+ type: a TauEventType describing the type of event.
+ data: A PyTango object with the event data. It can be None.
+ - For TauEventType.change events is a PyTango.AttributeValue
+ object or None;
+ - For TauEventType.attr_conf events is a
+ PyTango.AttrConfEventData object or None.
+ Return:
+ None
+ """
+ #-----------------------------------------------------------------------
+ # Write your own code here to handle event
+ pass
+
+ #---------------------------------------------------------------------------
+ # [MANDATORY]
+ # Uncomment the following method if your superclass does not provide with a
+ # isReadOnly() method or if you need to change its behavior
+
+ #def isReadOnly(self):
+ # return True
+
+ def updateStyle(self):
+ #-----------------------------------------------------------------------
+ # Write your own code here to update your widget style
+
+ # send a repaint in the end
+ self.repaint()
+
+ #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
+ # QT properties
+ #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
+
+ model = QtCore.pyqtProperty("QString", TauBaseWidget.getModel,
+ TauBaseWidget.setModel,
+ TauBaseWidget.resetModel)
+
+ useParentModel = QtCore.pyqtProperty("bool",
+ TauBaseWidget.getUseParentModel,
+ TauBaseWidget.setUseParentModel,
+ TauBaseWidget.resetUseParentModel)
+
+ #---------------------------------------------------------------------------
+ # Write your own code here for your own widget properties
+
+
diff --git a/lib/taurus/qt/qtgui/util/tauruswidgetfactory.py b/lib/taurus/qt/qtgui/util/tauruswidgetfactory.py
new file mode 100644
index 00000000..8a45c5f2
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/tauruswidgetfactory.py
@@ -0,0 +1,209 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""
+tauruswidgetfactory.py:
+"""
+
+__all__ = ["TaurusWidgetFactory", "getWidgetsOfType"]
+
+__docformat__ = 'restructuredtext'
+
+import imp
+import os.path
+
+from taurus.external.qt import Qt
+
+from taurus.core.util.log import Logger
+from taurus.core.util.singleton import Singleton
+
+import taurus.qt.qtgui.base
+
+def _getWidgetsOfType(widget, widgets, class_or_type_or_tuple):
+
+ if isinstance(widget, class_or_type_or_tuple):
+ widgets.append(widget)
+ for w in widget.children():
+ if isinstance(w, Qt.QWidget):
+ _getWidgetsOfType(w, widgets, class_or_type_or_tuple)
+
+def getWidgetsOfType(widget, class_or_type_or_tuple):
+ """Returns all widgets in a hierarchy of a certain type
+
+ :param widget: the widget to be inspected
+ :type widget: Qt.QWidget
+ :param class-or-type-or-tuple: type to be checked
+ :type class-or-type-or-tuple: type class or a tuple of type classes
+
+ :return: a sequence containning all widgets in the hierarchy that match the
+ given type
+ :rtype: seq<Qt.QWidget>"""
+ widgets = []
+ _getWidgetsOfType(widget, widgets, class_or_type_or_tuple)
+ return widgets
+
+
+class TaurusWidgetFactory(Singleton, Logger):
+ """The TaurusWidgetFactory is a utility class that provides information
+ about all Qt widgets (Taurus and non Taurus) that are found in the
+ current taurus distribution.
+ TaurusWidgetFactory is a singleton class so you can freely create new
+ instances since they will all reference the same object.
+ Usage::
+
+ from taurus.qt.qtgui.util import TaurusWidgetFactory
+
+ wf = TaurusWidgetFactory()
+ print wf.getTaurusWidgetClassNames()"""
+
+ skip_modules = ('widget', 'util', 'qtdesigner', 'uic')
+
+ def __init__(self):
+ """ Initialization. Nothing to be done here for now."""
+
+ def init(self, *args):
+ """Singleton instance initialization."""
+ name = self.__class__.__name__
+ self.call__init__(Logger, name)
+
+ path = os.path.dirname(os.path.abspath(__file__))
+ path, tail = os.path.split(path)
+ self._taurus_widgets, self._qt_widgets = self._buildWidgets('taurus.qt.qtgui', path)
+ self._addExtraTaurusWidgets(self._taurus_widgets, self._qt_widgets)
+
+ def _buildWidgets(self, module_name, path, recursive = True):
+ import taurus.qt.qtgui.base
+
+ if Qt.QApplication.instance() is None:
+ app = Qt.QApplication([])
+ #raise Exception("Cannot build widget list without an instance of "\
+ # "QApplication. Please create one before.")
+
+ elems = os.listdir(path)
+ taurus_ret, qt_ret = {}, {}
+ if not '__init__.py' in elems:
+ return taurus_ret, qt_ret
+
+ try:
+ m = __import__(module_name, fromlist=['*'], level=0)
+ dir_names = dir(m)
+ for dir_name in dir_names:
+ if dir_name.startswith("_"):
+ continue
+ try:
+ attr = getattr(m, dir_name)
+ if issubclass(attr, Qt.QWidget):
+ package = m.__package__
+ qt_ret[dir_name] = package, attr
+ if issubclass(attr, taurus.qt.qtgui.base.TaurusBaseWidget):
+ taurus_ret[dir_name] = package, attr
+ except Exception, e:
+ pass
+ except Exception,e:
+ return taurus_ret, qt_ret
+
+ if not recursive:
+ return taurus_ret, qt_ret
+
+ for elem in elems:
+ abs_elem = os.path.join(path, elem)
+ if (not elem.startswith('.')) and os.path.isdir(abs_elem) and \
+ (not elem in self.skip_modules):
+ m_name = os.path.splitext(elem)[0]
+ new_module_name = '%s.%s' % (module_name, m_name)
+ new_taurus_ret, new_qt_ret = self._buildWidgets(new_module_name, abs_elem, True)
+ taurus_ret.update(new_taurus_ret)
+ qt_ret.update(new_qt_ret)
+ return taurus_ret, qt_ret
+
+ def _addExtraTaurusWidgets(self, taurus_ret, qt_widgets):
+ designer_path = os.environ.get('TAURUSQTDESIGNERPATH')
+ if designer_path is None:
+ return taurus_ret
+ designer_path = designer_path.split(os.path.pathsep)
+ for path in designer_path:
+ self._addExtraTaurusWidgetsPath(taurus_ret, qt_widgets, path)
+
+ def _addExtraTaurusWidgetsPath(self, taurus_ret, qt_widgets, path):
+ self.debug("Trying extra taurus widgets in %s", path)
+ path = os.path.abspath(path)
+ if not os.path.isdir(path):
+ return
+ elems = os.listdir(path)
+ for elem in elems:
+ m_name, ext = os.path.splitext(elem)
+ if ext != '.py': continue
+ try:
+ self.debug("Trying to find extra module %s", m_name)
+ f, fname, data = imp.find_module(m_name, [path])
+ except ImportError, ie:
+ self.debug("Could not find extra module %s:%s", m_name, ie)
+ continue
+ try:
+ self.debug("Trying to load extra module %s", m_name)
+ mod = imp.load_module(m_name, f, fname, data)
+ except ImportError, ie:
+ self.debug("Could not load extra module %s:%s", m_name, ie)
+ continue
+ dir_names = dir(mod)
+ for dir_name in dir_names:
+ if dir_name.startswith("_"):
+ continue
+ if dir_name in taurus_ret:
+ continue
+ try:
+ attr = getattr(mod, dir_name)
+ if issubclass(attr, Qt.QWidget):
+ if issubclass(attr, taurus.qt.qtgui.base.TaurusBaseWidget):
+ qt_info = attr.getQtDesignerPluginInfo()
+ taurus_ret[dir_name] = qt_info['module'], attr
+ qt_widgets[dir_name] = qt_info['module'], attr
+ self.debug("registered taurus widget %s", dir_name)
+ except Exception, e:
+ pass
+
+ def getWidgets(self):
+ return self._qt_widgets
+
+ def getTaurusWidgets(self):
+ return self._taurus_widgets
+
+ def getWidgetClassNames(self):
+ return self._qt_widgets.keys()
+
+ def getWidgetClasses(self):
+ return [ klass for mod_name, klass in self._qt_widgets.values()]
+
+ def getWidgetClass(self, name):
+ return self._qt_widgets[name][1]
+
+ def getTaurusWidgetClassNames(self):
+ return self._taurus_widgets.keys()
+
+ def getTaurusWidgetClasses(self):
+ return [ klass for mod_name, klass in self._taurus_widgets.values()]
+
+ def getTaurusWidgetClass(self, name):
+ return self._taurus_widgets.get(name)[1]
diff --git a/lib/taurus/qt/qtgui/util/tauruswidgettree.py b/lib/taurus/qt/qtgui/util/tauruswidgettree.py
new file mode 100644
index 00000000..dbaecc47
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/tauruswidgettree.py
@@ -0,0 +1,229 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""
+"""
+
+__all__ = ["QObjectRepresentation", "get_qobject_tree", "get_qobject_tree_str",
+ "TreeQObjectModel", "TreeQObjectWidget"]
+
+__docformat__ = 'restructuredtext'
+
+import weakref
+
+from taurus.external.qt import Qt
+
+from taurus.core.util.enumeration import Enumeration
+
+QObjectRepresentation = Enumeration('QObjectRepresentation',
+ ('ClassName', 'ObjectName', 'FullName'))
+
+def _build_qobjects_as_dict(qobject, container):
+
+ container[qobject] = childs = {}
+ for child in qobject.children():
+ if isinstance(child, Qt.QWidget):
+ _build_qobjects_as_dict(child, childs)
+
+def get_qobject_tree_as_dict(qobject=None):
+
+ if qobject is None:
+ app = Qt.QApplication.instance()
+ qobjects = app.topLevelWidgets()
+ else:
+ qobjects = [qobject]
+
+ tree = {}
+ for qobject in qobjects:
+ _build_qobjects_as_dict(qobject, tree)
+
+ return tree
+
+def _build_qobjects_as_list(qobject, container):
+
+ children = qobject.children()
+ node = qobject, []
+ container.append(node)
+ for child in children:
+ if isinstance(child, Qt.QWidget):
+ _build_qobjects_as_list(child, node[1])
+
+def get_qobject_tree_as_list(qobject=None):
+
+ if qobject is None:
+ app = Qt.QApplication.instance()
+ qobjects = app.topLevelWidgets()
+ else:
+ qobjects = [qobject]
+
+ tree = []
+ for qobject in qobjects:
+ _build_qobjects_as_list(qobject, tree)
+
+ return tree
+
+get_qobject_tree = get_qobject_tree_as_list
+
+def _get_qobject_str(qobject, representation):
+ if representation == QObjectRepresentation.ClassName:
+ return qobject.__class__.__name__
+ elif representation == QObjectRepresentation.ObjectName:
+ return str(qobject.objectName())
+ elif representation == QObjectRepresentation.FullName:
+ return '{0}("{1}")'.format(qobject.__class__.__name__, str(qobject.objectName()))
+ return str(qobject)
+
+def _build_qobject_str(node, str_tree, representation=QObjectRepresentation.ClassName):
+
+ qobject, children = node
+ str_node = _get_qobject_str(qobject, representation)
+ str_children = []
+ str_tree.append((str_node, str_children))
+ for child in children:
+ _build_qobject_str(child, str_children, representation=representation)
+
+def get_qobject_tree_str(qobject=None, representation=QObjectRepresentation.ClassName):
+
+ tree, str_tree = get_qobject_tree(qobject=qobject), []
+ for e in tree:
+ _build_qobject_str(e, str_tree, representation=representation)
+ return str_tree
+
+
+from taurus.qt.qtgui.tree.qtree import QBaseTreeWidget
+from taurus.qt.qtcore.model import TaurusBaseModel, TaurusBaseTreeItem
+
+QR = QObjectRepresentation
+
+
+class TreeQObjecttItem(TaurusBaseTreeItem):
+
+ def __init__(self, model, data, parent = None):
+ TaurusBaseTreeItem.__init__(self, model, data, parent=parent)
+ if data is not None:
+ self.qobject = weakref.ref(data)
+ dat = _get_qobject_str(data, QR.ClassName), \
+ _get_qobject_str(data, QR.ObjectName)
+ self.setData(0, dat)
+
+
+class TreeQObjectModel(TaurusBaseModel):
+
+ ColumnNames = "Class", "Object name"
+ ColumnRoles = (QR.ClassName,), QR.ObjectName
+
+ def __init__(self, parent=None, data=None):
+ TaurusBaseModel.__init__(self, parent=parent, data=data)
+
+# def createNewRootItem(self):
+# return TreeQObjecttItem(self, self.ColumnNames)
+
+ def role(self, column, depth=0):
+ if column == 0:
+ return self.ColumnRoles[column][0]
+ return self.ColumnRoles[column]
+
+ def roleIcon(self, taurus_role):
+ return Qt.QIcon()
+
+ def roleSize(self, taurus_role):
+ return Qt.QSize(300, 70)
+
+ def roleToolTip(self, role):
+ return "widget information"
+
+ @staticmethod
+ def _build_qobject_item(model, parent, node):
+ qobject, children = node
+ item = TreeQObjecttItem(model, qobject, parent)
+ parent.appendChild(item)
+ for child in children:
+ TreeQObjectModel._build_qobject_item(model, item, child)
+
+ def setupModelData(self, data):
+ if data is None:
+ return
+ rootItem = self._rootItem
+ for node in data:
+ TreeQObjectModel._build_qobject_item(self, rootItem, node)
+
+
+class TreeQObjectWidget(QBaseTreeWidget):
+
+ KnownPerspectives = {
+ "Default" : {
+ "label" : "Default perspecive",
+ "tooltip" : "QObject tree view",
+ "icon" : "",
+ "model" : [TreeQObjectModel],
+ },
+ }
+
+ DftPerspective = "Default"
+
+
+ def __init__(self, parent=None, designMode=False, with_navigation_bar=True,
+ with_filter_widget=True, perspective=None, proxy=None,
+ qobject_root=None):
+ QBaseTreeWidget.__init__(self, parent, designMode=designMode,
+ with_navigation_bar=with_navigation_bar,
+ with_filter_widget=with_filter_widget,
+ perspective=perspective, proxy=proxy)
+ qmodel = self.getQModel()
+ qmodel.setDataSource(get_qobject_tree(qobject=qobject_root))
+
+
+def build_gui():
+ mw = Qt.QMainWindow()
+ mw.setObjectName("main window")
+ w = Qt.QWidget()
+ w.setObjectName("central widget")
+ mw.setCentralWidget(w)
+ l = Qt.QVBoxLayout()
+ w.setLayout(l)
+ l1 = Qt.QLabel("H1")
+ l1.setObjectName("label 1")
+ l.addWidget(l1)
+ l2 = Qt.QLabel("H2")
+ l2.setObjectName("label 2")
+ l.addWidget(l2)
+ mw.show()
+ return mw
+
+
+def main():
+ from taurus.qt.qtgui.application import TaurusApplication
+ app = TaurusApplication()
+
+ w = build_gui()
+ tree = TreeQObjectWidget(qobject_root=w)
+ tree.show()
+ #import pprint
+ #pprint.pprint(get_qobject_tree_str())
+ w.dumpObjectTree()
+ app.exec_()
+
+if __name__ == "__main__":
+ main()
diff --git a/lib/taurus/qt/qtgui/util/test/__init__.py b/lib/taurus/qt/qtgui/util/test/__init__.py
new file mode 100644
index 00000000..bfa1d383
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/test/__init__.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""tests for taurus.qt.qtgui.util"""
diff --git a/lib/taurus/qt/qtgui/util/test/test_ui/__init__.py b/lib/taurus/qt/qtgui/util/test/test_ui/__init__.py
new file mode 100644
index 00000000..c8c1e555
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/test/test_ui/__init__.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""This package provides a set of taurus wiget utilities like color management,
+configuration, actions."""
+
+from .test_ui import *
diff --git a/lib/taurus/qt/qtgui/util/test/test_ui/mywidget3/__init__.py b/lib/taurus/qt/qtgui/util/test/test_ui/mywidget3/__init__.py
new file mode 100644
index 00000000..9ffe6b53
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/test/test_ui/mywidget3/__init__.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+from taurus.external.qt import Qt
+from taurus.qt.qtgui.util.ui import UILoadable
+
+@UILoadable
+class MyWidget3(Qt.QWidget):
+
+ def __init__(self, parent=None):
+ Qt.QWidget.__init__(self, parent)
+ self.loadUi()
diff --git a/lib/taurus/qt/qtgui/util/test/test_ui/mywidget3/ui/MyWidget3.ui b/lib/taurus/qt/qtgui/util/test/test_ui/mywidget3/ui/MyWidget3.ui
new file mode 100644
index 00000000..7dcbbfa0
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/test/test_ui/mywidget3/ui/MyWidget3.ui
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <widget class="QPushButton" name="my_button">
+ <property name="geometry">
+ <rect>
+ <x>120</x>
+ <y>80</y>
+ <width>91</width>
+ <height>27</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>PushButton</string>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/lib/taurus/qt/qtgui/util/test/test_ui/test_ui.py b/lib/taurus/qt/qtgui/util/test/test_ui/test_ui.py
new file mode 100644
index 00000000..3673099c
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/test/test_ui/test_ui.py
@@ -0,0 +1,102 @@
+# -*- coding: utf-8 -*-
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""Unit tests for UILoadable decorator"""
+
+import os.path
+
+from taurus.external import unittest
+from taurus.external.qt import Qt
+from taurus.qt.qtgui.util.ui import UILoadable
+from taurus.qt.qtgui.test import BaseWidgetTestCase
+from mywidget3 import MyWidget3
+
+
+class UILoadableTestCase(unittest.TestCase):
+ """
+ Test cases for UILoadable decorator
+ """
+
+ @UILoadable
+ class MyWidget1(Qt.QWidget):
+
+ def __init__(self, parent=None):
+ Qt.QWidget.__init__(self, parent)
+ self.loadUi()
+ self.my_button.setText("This is MY1 button")
+
+ @UILoadable(with_ui="ui")
+ class MyWidget2(Qt.QWidget):
+
+ def __init__(self, parent=None):
+ Qt.QWidget.__init__(self, parent)
+ path = os.path.join(os.path.dirname(__file__), "ui", "mywidget2")
+ self.loadUi(filename="mywidget2_custom.ui", path=path)
+ self.ui.my_button.setText("This is MY2 button")
+
+ def setUp(self):
+ app = Qt.QApplication.instance()
+ if app is None:
+ app = Qt.QApplication([])
+ self.__app = app
+
+ def test_uiloadable_default(self):
+ """Test UILoadable with default arguments"""
+ widget = self.MyWidget1()
+ self.assertEquals(widget.my_button.text(), "This is MY1 button",
+ "button text differs from expected")
+
+ def test_uiloadable_customized(self):
+ """Test UILoadable with customized filename and path"""
+ widget = self.MyWidget2()
+ self.assertTrue(hasattr(widget, "ui"),
+ "widget doesn't have 'ui' member")
+ self.assertTrue(hasattr(widget.ui, "my_button"),
+ "widget.ui doesn't have a 'my_button' member")
+ self.assertFalse(hasattr(widget, "my_button"),
+ "widget has a my_button member")
+ self.assertEquals(widget.ui.my_button.text(), "This is MY2 button",
+ "button text differs from expected")
+
+
+class Bug339_TestCase(BaseWidgetTestCase, unittest.TestCase):
+ '''Test for bug 339: https://sourceforge.net/p/sardana/tickets/339/'''
+ def test_bug339(self):
+ '''Check inheritance of UILoadable classes across packages (bug #339)
+ '''
+ class Bug339_Widget(MyWidget3):
+ pass
+ try:
+ Bug339_Widget()
+ except:
+ self.fail('Inheriting from UILoadable from another package fails')
+
+
+def main():
+ unittest.main()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/lib/taurus/qt/qtgui/util/test/test_ui/ui/MyWidget1.ui b/lib/taurus/qt/qtgui/util/test/test_ui/ui/MyWidget1.ui
new file mode 100644
index 00000000..7dcbbfa0
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/test/test_ui/ui/MyWidget1.ui
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <widget class="QPushButton" name="my_button">
+ <property name="geometry">
+ <rect>
+ <x>120</x>
+ <y>80</y>
+ <width>91</width>
+ <height>27</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>PushButton</string>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/lib/taurus/qt/qtgui/util/test/test_ui/ui/mywidget2/mywidget2_custom.ui b/lib/taurus/qt/qtgui/util/test/test_ui/ui/mywidget2/mywidget2_custom.ui
new file mode 100644
index 00000000..7dcbbfa0
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/test/test_ui/ui/mywidget2/mywidget2_custom.ui
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <widget class="QPushButton" name="my_button">
+ <property name="geometry">
+ <rect>
+ <x>120</x>
+ <y>80</y>
+ <width>91</width>
+ <height>27</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>PushButton</string>
+ </property>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/lib/taurus/qt/qtgui/util/ui.py b/lib/taurus/qt/qtgui/util/ui.py
new file mode 100644
index 00000000..0c939738
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/ui.py
@@ -0,0 +1,187 @@
+# -*- coding: utf-8 -*-
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""utilities to load ui files for widgets"""
+
+import os
+import sys
+import functools
+
+from taurus.external.qt import Qt
+from taurus.external.qt import uic
+
+
+class __UI(object):
+ pass
+
+
+def loadUi(obj, filename=None, path=None, with_ui=None):
+ """
+ Loads a QtDesigner .ui file into the given widget.
+ If no filename is given, it tries to load from a file name which is the
+ widget class name plus the extension ".ui" (example: if your
+ widget class is called MyWidget it tries to find a MyWidget.ui).
+ If path is not given it uses the directory where the python file which
+ defines the widget is located plus a *ui* directory (example: if your widget
+ is defined in a file /home/homer/workspace/taurusgui/my_widget.py then it uses
+ the path /home/homer/workspace/taurusgui/ui)
+
+ :param filename: the QtDesigner .ui file name [default: None, meaning
+ calculate file name with the algorithm explained before]
+ :type filename: str
+ :param path: directory where the QtDesigner .ui file is located
+ [default: None, meaning calculate path with algorithm explained
+ before]
+ :type path: str
+ :param with_ui: if True, the objects defined in the ui file will be
+ accessible as submembers of an ui member of the widget. If
+ False, such objects will directly be members of the widget.
+ :type with_ui: bool
+ """
+ if path is None:
+ obj_file = sys.modules[obj.__module__].__file__
+ path = os.path.join(os.path.dirname(obj_file), 'ui')
+ if filename is None:
+ filename = obj.__class__.__name__ + os.path.extsep + 'ui'
+ full_name = os.path.join(path, filename)
+
+ if with_ui is not None:
+ ui_obj = __UI()
+ setattr(obj, with_ui, ui_obj)
+ previous_members = set(dir(obj))
+
+ uic.loadUi(full_name, baseinstance=obj)
+
+ post_members = set(dir(obj))
+ new_members = post_members.difference(previous_members)
+ for member_name in new_members:
+ member = getattr(obj, member_name)
+ setattr(ui_obj, member_name, member)
+ delattr(obj, member_name)
+ else:
+ uic.loadUi(full_name, baseinstance=obj)
+
+def UILoadable(klass=None, with_ui=None):
+ """
+ A class decorator intended to be used in a Qt.QWidget to make its UI
+ loadable from a predefined QtDesigner UI file.
+ This decorator will add a :func:`loadUi` method to the decorated class and
+ optionaly a property with a name given by *with_ui* parameter.
+
+ The folowing example assumes the existence of the ui file
+ :file:`<my_widget_dir>/ui/MyWidget.ui` which is a QWidget panel with *at
+ least* a QPushButton with objectName *my_button* ::
+
+ from taurus.external.qt import Qt
+ from taurus.qt.qtgui.util.ui import UILoadable
+
+ @UILoadable
+ class MyWidget(Qt.QWidget):
+
+ def __init__(self, parent=None):
+ Qt.QWidget.__init__(self, parent)
+ self.loadUi()
+ self.my_button.setText("This is MY button")
+
+ Another example using a :file:`superUI.ui` file in the same directory as
+ the widget. The widget UI components can be accessed through the widget
+ member *_ui* ::
+
+ import os.path
+
+ from taurus.external.qt import Qt
+ from taurus.qt.qtgui.util.ui import UILoadable
+
+ @UILoadable(with_ui="_ui")
+ class MyWidget(Qt.QWidget):
+
+ def __init__(self, parent=None):
+ Qt.QWidget.__init__(self, parent)
+ self.loadUi(filename="superUI.ui", path=os.path.dirname(__file__))
+ self._ui.my_button.setText("This is MY button")
+
+ :param with_ui: assigns a member to the decorated class from which you
+ can access all UI components [default: None, meaning no
+ member is created]
+ :type with_ui: str
+
+ .. warning::
+ the current implementation (Jul14) doesn't prevent Qt from overloading
+ any members you might have defined previously by the widget object names
+ from the UI file. This happens even if *with_ui* parameter is given.
+ For example, if the UI contains a QPushButton with objectName
+ *my_button*::
+
+ @UILoadable(with_ui="_ui")
+ class MyWidget(Qt.QWidget):
+
+ def __init__(self, parent=None):
+ Qt.QWidget.__init__(self, parent)
+ self.my_button = "hello"
+ self.loadUi()
+ widget = MyWidget()
+ print widget.my_button
+ <PyQt4.QtGui.QPushButton object at 0x159e2f8>
+
+ This little problem should be solved in the next taurus version.
+ """
+ if klass is None:
+ return functools.partial(UILoadable, with_ui=with_ui)
+
+ klass_name = klass.__name__
+ klass_file = sys.modules[klass.__module__].__file__
+ klass_path = os.path.join(os.path.dirname(klass_file), 'ui')
+
+ def _loadUi(self, filename=None, path=None):
+ if filename is None:
+ filename = klass_name + os.path.extsep + 'ui'
+ if path is None:
+ path = klass_path
+ return loadUi(self, filename=filename, path=path, with_ui=with_ui)
+
+ klass.loadUi = _loadUi
+ return klass
+
+
+def main():
+ from taurus.qt.qtgui.application import TaurusApplication
+
+ app = TaurusApplication([])
+
+ @UILoadable(with_ui="ui")
+ class A(Qt.QWidget):
+
+ def __init__(self, parent=None):
+ Qt.QWidget.__init__(self, parent)
+ import taurus.qt.qtgui.panel.ui
+ path = os.path.dirname(taurus.qt.qtgui.panel.ui.__file__)
+ self.loadUi(filename='TaurusMessagePanel.ui', path=path)
+
+ gui = A()
+ gui.show()
+ app.exec_()
+
+if __name__ == "__main__":
+ main()
diff --git a/lib/taurus/qt/qtgui/util/widgetgen.py b/lib/taurus/qt/qtgui/util/widgetgen.py
new file mode 100644
index 00000000..757950aa
--- /dev/null
+++ b/lib/taurus/qt/qtgui/util/widgetgen.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## 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 <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""
+widgetgen.py:
+"""
+
+#!/usr/bin/env python
+
+import os, sys
+
+usage = "usage: %s <widget class name> <widget super class> <output file name> [<qt designer plugin file>]" % os.path.basename(sys.argv[0])
+
+DftModule = "taurus.widget"
+DftIconFilename = "label.png"
+DftIsContainer = str(False)
+
+def go(class_name, super_class, output_name):
+
+ path = ''
+ try:
+ path = os.path.dirname(__file__)
+ except:
+ pass
+ input_name = os.path.realpath(path) + '/tauruswidget_template'
+
+ try:
+ output = open(output_name, 'w')
+ except:
+ raise
+
+ try:
+ input = open(input_name, 'r')
+ except:
+ output.close()
+ raise
+
+ for s in input:
+ o = s.replace('<_SuperClass_>', super_class)
+ o = o.replace('<_TaurusClass_>', class_name)
+ o = o.replace('<_Module_>', DftModule)
+ o = o.replace('<_IconFileName_>', DftIconFilename)
+ o = o.replace('<_Container_>', DftIsContainer)
+ output.write(o)
+
+ input.close()
+ output.close()
+
+
+def go_with_designer(class_name, super_class, output_name, plugin_output_name):
+
+ go(class_name, super_class, output_name)
+
+ path = ''
+ try:
+ path = os.path.dirname(__file__)
+ except:
+ pass
+ input_name = os.path.realpath(path) + '/tauruswidget_qtdesignerplugin_template'
+
+ try:
+ output = open(plugin_output_name, 'w')
+ except:
+ raise
+
+ try:
+ input = open(input_name, 'r')
+ except:
+ output.close()
+ raise
+
+ for s in input:
+ o = s.replace('<_SuperClass_>',super_class)
+ o = o.replace('<_TaurusClass_>',class_name)
+ o = o.replace('<_Module_>', DftModule)
+ o = o.replace('<_IconFileName_>', DftIconFilename)
+ o = o.replace('<_Container_>', DftIsContainer)
+ output.write(o)
+
+ input.close()
+ output.close()
+
+if __name__ == "__main__":
+
+ argc = len(sys.argv)
+ if argc < 4:
+ print usage
+ elif argc == 4:
+ go(sys.argv[1],sys.argv[2],sys.argv[3])
+ else:
+ go_with_designer(sys.argv[1],sys.argv[2],sys.argv[3],sys.argv[4])
+ \ No newline at end of file