Source code for taurus.qt.qtgui.util.ui
# -*- 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
[docs]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)
[docs]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
[docs]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()