Paul
Paul

Reputation: 2469

Pasting QMimeData to another window's QTextEdit

I'm still quite a newbie with Python and PyQt so I have a really basic question. I have some text and images in a parent window inside a QTextEdit widget and I'm trying to copy all the content to a child window's QTextEdit. But for some reason I can't get it to copy the image - only the text is copied not the image. Here's a snippet of the code that's giving me trouble:

self.textEdit.selectAll()
data = self.textEdit.createMimeDataFromSelection()
self.child_window.textEdit.insertFromMimeData(data) # doesn't work with images

Here's is the small program that I'm trying to run:

import sys
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyWindow(QtGui.QWidget):

    def __init__(self,parent=None):
        super(MyWindow,self).__init__(parent)

        self.textEdit = QtGui.QTextEdit(self)
        self.textEdit.setText("Hello World\n")

        self.pushButton = QtGui.QPushButton(self)
        self.pushButton.setText("Copy and paste to Child Window")
        self.pushButton.clicked.connect(self.click_copy_data)

        self.pushButton2 = QtGui.QPushButton(self)
        self.pushButton2.setText("Insert Image")
        self.pushButton2.clicked.connect(self.click_file_dialog)

        self.layoutVertical = QtGui.QVBoxLayout(self)
        self.layoutVertical.addWidget(self.textEdit)
        self.layoutVertical.addWidget(self.pushButton2)
        self.layoutVertical.addWidget(self.pushButton)

        self.setGeometry(150, 150,640, 480)
        self.child_window = CustomWindow(self)
        self.child_window.show()

    def click_copy_data(self):

        self.textEdit.selectAll()
        data = self.textEdit.createMimeDataFromSelection()
        self.child_window.textEdit.insertFromMimeData(data)

    def click_file_dialog(self):
        filePath = QtGui.QFileDialog.getOpenFileName(
            self,
            "Select an image",
            ".",
            "Image Files(*.png *.gif *.jpg *jpeg *.bmp)"
        )

        if not filePath.isEmpty():
            self.insertImage(filePath)


    def insertImage(self,filePath):

        imageUri = QtCore.QUrl(QtCore.QString("file://{0}".format(filePath)))
        image    = QtGui.QImage(QtGui.QImageReader(filePath).read())

        self.textEdit.document().addResource(
            QtGui.QTextDocument.ImageResource,
            imageUri,
            QtCore.QVariant(image)
        )

        imageFormat = QtGui.QTextImageFormat()
        imageFormat.setWidth(image.width())
        imageFormat.setHeight(image.height())
        imageFormat.setName(imageUri.toString())

        textCursor = self.textEdit.textCursor()
        textCursor.movePosition(
            QtGui.QTextCursor.End,
            QtGui.QTextCursor.MoveAnchor
        )
        textCursor.insertImage(imageFormat)

        # This will hide the cursor
        blankCursor = QtGui.QCursor(QtCore.Qt.BlankCursor)
        self.textEdit.setCursor(blankCursor)

class CustomWindow(QtGui.QDialog):
    def __init__(self,parent=None):
        super(CustomWindow,self).__init__(parent)

        self.textEdit = QtGui.QTextEdit(self)

        self.layoutVertical = QtGui.QVBoxLayout(self)
        self.layoutVertical.addWidget(self.textEdit)


if __name__ == "__main__":

    app = QtGui.QApplication(sys.argv)
    app.setApplicationName('MyWindow')
    main = MyWindow()
    main.show()

    sys.exit(app.exec_())

The way the program works is that you have some text inside the main window and then you insert an image. Then you click "Copy and paste to Child Window" button and it should paste all the contents to the child, including the image - but that doesn't work that way it's supposed to - the text is copied but I get a little file icon where the image should be.

I would appreciate your help on this.

Paul

Upvotes: 1

Views: 1799

Answers (2)

Paul
Paul

Reputation: 2469

This is the solution I ended using as suggested by X.Jacobs.

html = parent_textEdit.toHtml()
child_textEdit.setHtml(html)

I was making things more complicated. When I realized that QTextEdit keeps track of where the image is stored as a url inside the html generated by toHtml() then it all made sense.

Upvotes: 0

user1006989
user1006989

Reputation:

QTextEdit doesn't decode image MIME types by default, so just subclass it to add support, you'll need to reimplement canInsertFromMimeData and insertFromMimeData, also try QTextBrowser instead. Just add this to your script:

class MyTextBrowser(QtGui.QTextBrowser):
    def __init__(self, parent=None):
        super(MyTextBrowser, self).__init__(parent)

        self.setReadOnly(False)

    def canInsertFromMimeData(self, source):
        if source.hasImage():
            return True

        else:
            return super(MyTextBrowser, self).canInsertFromMimeData(source)

    def insertFromMimeData(self, source):
        if source.hasImage():
            image = QtCore.QVariant(source.imageData())

            document = self.document()
            document.addResource(
                QtGui.QTextDocument.ImageResource,
                QtCore.QUrl("image"),
                image
            )

            cursor = self.textCursor()
            cursor.insertImage("image")

        super(MyTextBrowser, self).insertFromMimeData(source)

And change self.textEdit = QtGui.QTextEdit(self) into self.textEdit = MyTextBrowser(self) on both widgets.

Upvotes: 1

Related Questions