On 10/6/07, Phil Thompson <[EMAIL PROTECTED]> wrote:
>
> On Saturday 06 October 2007, Arve Knudsen wrote:
> > On 10/6/07, Phil Thompson <[EMAIL PROTECTED]> wrote:
> > > On Friday 05 October 2007, Arve Knudsen wrote:
> > > > Hi
> > > > I've just written a Designer plugin in Python, which I have to say
> is
> > >
> > > very
> > >
> > > > nice. However I discovered some surprising behaviour in pyuic. My
> > > > widget contains Qt properties (defined using pyqtProperty), but the
> > > > generated
> > >
> > > code
> > >
> > > > don't use the properties, instead it tries to use the underlying
> > >
> > > methods!?
> > >
> > > > I discovered this for the reason that I use a different naming
> > >
> > > convention
> > >
> > > > than pyuic apparently expected. For instance, I had a property
> "value",
> > >
> > > for
> > >
> > > > which pyuic expected there to be a setter method "setValue". I hope
> it
> > > > isn't on purpose that pyuic tries to use underlying methods instead
> of
> > >
> > > the
> > >
> > > > properties themselves?
> > > >
> > > > I'm using PyQt 4.3 commercial edition.
> > > >
> > > > Thanks,
> > > > Arve
> > >
> > > If everything is working as it should then it depends on what you have
> > > called
> > > the setter. If it begins with "set" then pyuic (and uic) should use it
> > > directly and not use setProperty(). However this has probably not had
> a
> > > lot
> > > of testing.
> > >
> > > What have you called your setter?
> >
> > Let's say the property is called "value". I called my setter _set_value,
> > pyuic inferred the setter's name to be setValue.
> >
> > Does uic behave differently to pyuic?
> >
> >
> > I haven't used uic for some time, but this point is kind of moot since
> C++
> > doesn't have properties while Python does :)
>
> Qt/C++ does have properties.
>
> > The point is that I can't see
> > that there is any reason for pyuic to try and use the setter method,
> when
> > it can simply use the property (i.e., obj.value = something).
>
> Because it needs to have the same behaviour as uic. If it doesn't then it
> is
> clearly a pyuic bug. If not then it may be a bug in the implementation of
> pyqtProperty.


I'm not sure I follow you here, but I'll let you comment on my attached
example first.

Can you send me a .ui file?


Better yet, I've attached a modified PyDemo example where the setZoom method
is renamed to _set_zoom (to mimic my naming convention) and a basic form
using the widget. This illustrates the problem. There's no problem modifying
PyDemo's zoom property as it were another attribute, e.g., demo.zoom = 1,
but the pyuic generated code insists on calling setZoom which isn't there.

Arve
#!/usr/bin/env python

# A demonstration custom widget.
#
# Copyright (c) 2007 Riverbank Computing Limited


from PyQt4 import QtCore, QtGui


# The purpose of this class is to show that Designer's property editor shows
# all Python classes in the hierarchy that define properties.
class PyTextViewer(QtGui.QTextEdit):

    # Initialise the instance.
    def __init__(self, parent=None):
        QtGui.QTextEdit.__init__(self, parent)

        self.setReadOnly(True)

        # Initialise the author property by calling it's reset function.
        self.resetAuthor()

    # The getter for the author property.  Note that we cannot follow the Qt
    # naming convention (ie. by using the naming the getter "author") because
    # it would conflict with the property name.
    def getAuthor(self):
        return self._author

    # The setter for the author property.
    def setAuthor(self, name):
        self._author = name

    # The resetter for the author property.  Only Qt Designer uses this.  Qt
    # Designer does not use the deleter function of the property.
    def resetAuthor(self):
        self._author = "David Boddie"

    # Define the author property.  This will look like a C++ property to Qt
    # Designer and a Python property to Python.
    author = QtCore.pyqtProperty("QString", getAuthor, setAuthor, resetAuthor)


# This is the class that implements the custom widget.
class PyDemo(PyTextViewer):

    # Define the Qt signals as a sequence of C++ function signatures excluding
    # the return type.  These may be connected to other signals or slots in Qt
    # Designer.
    __pyqtSignals__ = ("zoomChanged(int)")

    # Initialise the instance.
    def __init__(self, parent=None):
        PyTextViewer.__init__(self, parent)

        self.setWindowTitle("PyQt Demonstration Widget")
        self.setText(_demo_text)

        # Initialise the zoom property.  We don't just call the resetter
        # because it assumes that this has already been initialised.
        self._zoom = 0

    # The getter for the zoom property.
    def getZoom(self):
        return self._zoom

    # The setter for the zoom property.  We also make define this as a Qt slot
    # which can be connected to Qt signals in Qt Designer.
    @QtCore.pyqtSignature("int")
    def _set_zoom(self, zoom):
        # Don't do anything if nothing has changed.
        if self._zoom == zoom:
            return

        # Zoom in or out according to the relative zoom levels.
        if self._zoom < zoom:
            self.zoomIn(zoom - self._zoom)
        elif self._zoom > zoom:
            self.zoomOut(self._zoom - zoom)

        # Remember the new zoom level.
        self._zoom = zoom

        # Emit the Qt signal to say that the zoom level has changed.
        self.emit(QtCore.SIGNAL("zoomChanged(int)"), zoom)

    # The resetter for the zoom property.
    def resetZoom(self):
        self._set_zoom(0)

    # Define the zoom property.  Changing the value of this in Qt Designer's
    # property editor causes the zoom level to change dynamically.
    zoom = QtCore.pyqtProperty("int", getZoom, _set_zoom, resetZoom)


# The text displayed in the custom widget.
_demo_text = """<h3>PyQt Demonstration Widget</h3>
<p>This simple example demonstrates the following features.</p>
<ul>
 <li>The definition of properties that behave as C++ properties to Qt and
     Python properties to Python.</li>
 <li>The definition of new Qt signals that can be connected to other signals
     and Qt slots in Designer.</li>
 <li>The definition of new Qt slots that can be connected to signals in
     Designer.</li>
</ul>
"""


# Display the custom widget if the script is being run directly from the
# command line.
if __name__ == "__main__":
    import sys

    app = QtGui.QApplication(sys.argv)

    demo = PyDemo()
    demo.show()

    sys.exit(app.exec_())
# A demonstration custom widget plugin for Qt Designer.
# 
# Copyright (c) 2007 Riverbank Computing Limited.


from PyQt4 import QtGui, QtDesigner

from pydemo import PyDemo


# This class implements the interface expected by Qt Designer to access the
# custom widget.  See the description of the QDesignerCustomWidgetInterface
# class for full details.
class PyDemoPlugin(QtDesigner.QPyDesignerCustomWidgetPlugin):

    # Initialise the instance.
    def __init__(self, parent=None):
        QtDesigner.QPyDesignerCustomWidgetPlugin.__init__(self)

        self._initialized = False

    # Initialise the custom widget for use with the specified formEditor
    # interface.
    def initialize(self, formEditor):
        if self._initialized:
            return

        self._initialized = True

    # Return True if the custom widget has been intialised.
    def isInitialized(self):
        return self._initialized

    # Return a new instance of the custom widget with the given parent.
    def createWidget(self, parent):
        return PyDemo(parent)

    # Return the name of the class that implements the custom widget.
    def name(self):
        return "PyDemo"

    # Return the name of the group to which the custom widget belongs.  A new
    # group will be created if it doesn't already exist.
    def group(self):
        return "PyQt Examples"

    # Return the icon used to represent the custom widget in Designer's widget
    # box.
    def icon(self):
        return QtGui.QIcon(_logo_pixmap)

    # Return a short description of the custom widget used by Designer in a
    # tool tip.
    def toolTip(self):
        return "PyQt demonstration widget"

    # Return a full description of the custom widget used by Designer in
    # "What's This?" help for the widget.
    def whatsThis(self):
        return "PyDemo is a demonstration custom widget written in Python " \
               "using PyQt."

    # Return True if the custom widget acts as a container for other widgets.
    def isContainer(self):
        return False

    # Return an XML fragment that allows the default values of the custom
    # widget's properties to be overridden.
    def domXml(self):
        return '<widget class="PyDemo" name="pyDemo">\n' \
               ' <property name="toolTip" >\n' \
               '  <string>PyQt demonstration widget</string>\n' \
               ' </property>\n' \
               ' <property name="whatsThis" >\n' \
               '  <string>PyDemo is a demonstration custom widget written ' \
               'in Python using PyQt.</string>\n' \
               ' </property>\n' \
               '</widget>\n'

    # Return the name of the module containing the class that implements the
    # custom widget.  It may include a module path.
    def includeFile(self):
        return "pydemo"


# Define the image used for the icon.
_logo_16x16_xpm = [
    "16 16 6 1",
    " 	c None",
    ".	c #FFFFFF",
    "a	c #01E0FC",
    "b	c #D8D508",
    "c	c #01AC01",
    "d	c #0180E8",
    "aaa...bbbb...aaa",
    "aaaa.bbbbbb.aaaa",
    "aaaa.bbbbbb.aaaa",
    "aaaa.bbbbbb.aaaa",
    "aaa...bbbb...aaa",
    "................",
    "cccccccccccccccc",
    "cccccccccccccccc",
    "cccccccccccccccc",
    "cccccccccccccccc",
    "................",
    "dddddddddddddddd",
    "dddddddddddddddd",
    "dddddddddddddddd",
    "dddddddddddddddd",
    "                "]

_logo_pixmap = QtGui.QPixmap(_logo_16x16_xpm)

Attachment: pydemo.ui
Description: Binary data

_______________________________________________
PyQt mailing list    PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Reply via email to