Snippet to embed a widget in an editor.

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Snippet to embed a widget in an editor.

Phlip
Hi, group. I'm trying to embed an object into a QTextEdit which is NOT
(shocked gasp!) an SVG image.

Foundational for embedding a panel, I'm trying to embed a widget. But
I can't seem to get the size right. Here's the sauce:

#!/usr/bin/env python

try:
    # This is only needed for Python v2 but is harmless for Python v3.
    import sip
    sip.setapi('QVariant', 2)
except ImportError:
    pass

from PyQt4 import QtCore, QtGui


class YoWindow(QtGui.QWidget):

    TEXT_OBJECT_WRAPPER = QtGui.QTextFormat.UserObject + 1001

    def __init__(self):
        super(YoWindow, self).__init__()

        self.setWindowTitle('YoWindow')

        self.textEdit = QtGui.QTextEdit()
        widget = QtGui.QLineEdit()
        widget.setText('I am here!')
        self.text_object_wrapper(self.textEdit, widget)

        layout = _vertical( self.textEdit )

        self.setLayout(layout)

        cursor = self.textEdit.textCursor()
        cursor.insertText('previously\n')

        self.insertTextObject(cursor)

        cursor.insertText('subsequently')
        self.textEdit.setTextCursor(cursor)

    def text_object_wrapper(self, editor, widget):

        class _TextObject(QtGui.QPyTextObject):

            def intrinsicSize(self, doc, posInDocument, format):

                size = widget.baseSize()  #  <-- other sizes just gave
whack results
                return QtCore.QSizeF(size)

            def drawObject(self, painter, rect, doc, posInDocument, format):
                widget.render(painter, QtCore.QPoint(int(rect.x()),
int(rect.y())))

        interface = _TextObject(self)
        editor.document().documentLayout().registerHandler(YoWindow.TEXT_OBJECT_WRAPPER,
interface)

    def insertTextObject(self, cursor):

        charFormat = QtGui.QTextCharFormat()
        charFormat.setObjectType(YoWindow.TEXT_OBJECT_WRAPPER)

        try:
            # Python v2.
            orc = unichr(0xfffc)
        except NameError:
            # Python v3.
            orc = chr(0xfffc)

        cursor.insertText(orc, charFormat)


def _vertical(*things):
    return _lay_out(QtGui.QVBoxLayout, *things)

def _lay_out(LayoutClass, *things):
    layout = LayoutClass()

    for thing in things:
        if hasattr(thing, 'BottomToTop'):
            layout.addLayout(thing)
        else:
            layout.addWidget(thing)

    return layout


if __name__ == '__main__':

    import sys

    app = QtGui.QApplication(sys.argv)
    window = YoWindow()
    window.show()
    sys.exit(app.exec_())

If you ran that, you'd get:

   previously
   subsequently
   [I am here!]

Presumably if the size were set right, the editor would push down the
"subsequently".

Contrarily, maybe I'm setting the size correctly, but then screwing
something up with the cursors.

--
  Phlip
  http://c2.com/cgi/wiki?ZeekLand
_______________________________________________
PyQt mailing list    [hidden email]
http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Snippet to embed a widget in an editor.

David Boddie
On Sun Jul 17 04:57:00 BST 2011, Phlip wrote:

> Hi, group. I'm trying to embed an object into a QTextEdit which is NOT
> (shocked gasp!) an SVG image.
>
> Foundational for embedding a panel, I'm trying to embed a widget. But
> I can't seem to get the size right. Here's the sauce:

[...]

> If you ran that, you'd get:
>
>    previously
>    subsequently
>    [I am here!]
>
> Presumably if the size were set right, the editor would push down the
> "subsequently".

The size is a null size, so I'm guessing the text engine just ignores it.

I changed the code for the text object to use the widget's size hint.

  class _TextObject(QtGui.QPyTextObject):

      def intrinsicSize(self, doc, posInDocument, format):

          size = widget.sizeHint()
          return QtCore.QSizeF(size)

      def drawObject(self, painter, rect, doc, posInDocument, format):
          widget.resize(widget.sizeHint())
          widget.render(painter, QtCore.QPoint(int(rect.x()), int(rect.y())))

I also made the widget resize itself to its size hint before rendering it.
I'm not sure why that is necessary.

> Contrarily, maybe I'm setting the size correctly, but then screwing
> something up with the cursors.

No, I think it's the size. The above code should at least get you started.

David
_______________________________________________
PyQt mailing list    [hidden email]
http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Snippet to embed a widget in an editor.

Phlip
In reply to this post by Phlip
> I changed the code for the text object to use the widget's size hint.

Awesome, thanks, but..!

I can't click on the form; the point was simulating a web page's form.
I switched to a vertically scrolling layout, and I'll just stuff what
I need into it, one by one.

(I'm going for a chat scroll, like Skype...)

New question: Given a QWidget, how to I collect every control
(QLineEdit, QLabel, etc.) in it?

Walking the object model it appears I must traverse each layout, each
layout's children, etc. Is this already bottled up for me?

--
  Phlip
  http://c2.com/cgi/wiki?ZeekLand
_______________________________________________
PyQt mailing list    [hidden email]
http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|

Re: Snippet to embed a widget in an editor.

Phlip
In reply to this post by Phlip
David Boddie wrote:

>> I switched to a vertically scrolling layout, and I'll just stuff what
>> I need into it, one by one.

> Have you thought about just using a layout and putting rich text QLabel
> widgets and buttons into it?

C-;

> Call the findChildren() method, optionally passing the class of the widgets
> you're looking for. Pass QWidget if you want to get them all.

Awesome. It's amazing how much stuff is in here, under the surface. Tx!

--
  Phlip
  http://c2.com/cgi/wiki?ZeekLand
_______________________________________________
PyQt mailing list    [hidden email]
http://www.riverbankcomputing.com/mailman/listinfo/pyqt