mouseeventqgraphicsviewqtexteditpyside6

Is it possible to select texts with mouse in the case of horizontally allocated QTextEdit?


There are three QGraphicsView in one line. If these QGraphicsView is vertically located (orientation is 0), to select texts with mouse is no problem. But if these QGrahpicsView is horizontally located, goes bad.Even if horizontally located, I must select texts vertically.

It seems that the mouse point at the time of mouse press event is decided by QTextEdit coordinate at first. At the time of mouse move event, the mouse point is decided by the position of mouse press event as the anchor. So is the time of mouse release event.

Is there way to select texts with mouse naturally? Or does Qt allow us to select texts with mouse vertically only?

from PySide6.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsProxyWidget, QTextEdit
from PySide6.QtGui import QTextDocument, QPageSize, QPainter, QBrush, QTextCharFormat, QTextOption
from PySide6.QtCore import Qt, Signal, QRect, QRectF, QEvent, QSize, QSizeF, QPointF



class MainGraphicsView(QGraphicsView):

    
    def __init__(self, parent=None):

        super(MainGraphicsView, self).__init__(parent)


        self._mainscene = MainGraphicsScene(1)
        self._mainscene._mainview = self
        self.setScene(self._mainscene)          

class MainGraphicsScene(QGraphicsScene):  

    def __init__(self, orientation = 1, parent=None):

        super(MainGraphicsScene, self).__init__(parent)
        
        if orientation == 0:

            self.rootView = TextGraphicsView()        
            self.rootView.main_scene = self
            self.root_proxywidget = self.addWidget(self.rootView)
            self.rootView.setSceneRect(0, 0, self.document()._pageWidth, self.document()._pageHeight)

            self.secondaryView = SecondaryTextGraphicsView(2, self.rootView.scene())
            self.secondaryView.setSceneRect(0, self.document()._pageHeight, self.document()._pageWidth, self.document()._pageHeight)
            self.secondary_proxywidget = self.addWidget(self.secondaryView)
            self.secondary_proxywidget.setPos(0, self.document()._pageHeight)

            self.thirdView = SecondaryTextGraphicsView(3, self.rootView.scene())
            self.thirdView.setSceneRect(0, self.document()._pageHeight*2, self.document()._pageWidth, self.document()._pageHeight)
            self.third_proxywidget = self.addWidget(self.thirdView)
            self.third_proxywidget.setPos(0, self.document()._pageHeight*2)

            
        if orientation == 1:
            
            self.rootView = TextGraphicsView()        
            self.rootView.main_scene = self
            self.root_proxywidget = self.addWidget(self.rootView)
            self.rootView.setSceneRect(0, 0, self.document()._pageWidth, self.document()._pageHeight)

            self.secondaryView = SecondaryTextGraphicsView(2, self.rootView.scene())
            self.secondaryView.setSceneRect(0, self.document()._pageHeight, self.document()._pageWidth, self.document()._pageHeight)
            self.secondary_proxywidget = self.addWidget(self.secondaryView)
            self.secondary_proxywidget.setPos(self.document()._pageWidth, 0)

            self.thirdView = SecondaryTextGraphicsView(3, self.rootView.scene())
            self.thirdView.setSceneRect(0, self.document()._pageHeight*2, self.document()._pageWidth, self.document()._pageHeight)
            self.third_proxywidget = self.addWidget(self.thirdView)
            self.third_proxywidget.setPos(self.document()._pageWidth*2, 0)

        self.setBackgroundBrush(QBrush(Qt.gray))      
   
    def view(self):

        return self._mainview

    def textedit(self):

        return self.document().parent()

    def document(self):

        return self.rootView.document()
    
    
class TextGraphicsView(QGraphicsView):
    
    def __init__(self,  parent=None):

        super().__init__(parent)

        self.page = 1

        self.initScene()

    def mousePressEvent(self, event):

        SecondaryTextGraphicsView.selectedPage = self.page
        return QGraphicsView.mousePressEvent(self, event)

    def initScene(self):
        
        self.common_scene = TextGraphicsScene()
        self.common_scene.root_view = self
        
        self.setScene(self.common_scene)
        self.setSceneRect(0, self.document()._pageHeight*(self.page -1), self.document()._pageWidth, self.document()._pageHeight)
        self.resize(int(self.document()._pageWidth), int(self.document()._pageHeight))

        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

    def view(self):

        return self.main_scene._mainview
    
    def textedit(self):

        return self.common_scene.textedit
    
    def document(self):

        return self.common_scene.textedit.document()       

class SecondaryTextGraphicsView(QGraphicsView):

    def __init__(self, page, scene, parent=None):

        super().__init__(scene, parent)

        self.page = page

        self.initScene()

        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)    

    def initScene(self):
        
        self.setSceneRect(0, self.document()._pageHeight*(self.page-1), self.document()._pageWidth, self.document()._pageHeight)
        self.resize(int(self.document()._pageWidth), int(self.document()._pageHeight))

    def view(self):

        return self.scene().root_view.view()

    def textedit(self):

        return self.scene().textedit()
    

    def document(self):

        return self.scene().textedit.document()


class TextGraphicsScene(QGraphicsScene):


    def __init__(self, parent=None):

        super().__init__(parent)        

        self.textedit = TextEdit(scene=self)        
       
        self.addWidget(self.textedit)


    def view(self):

        return self.root_view

    def document(self):

        return self.textedit.document()     
    

class TextEdit(QTextEdit):
    
    def __init__(self,  scene, parent=None):

        super().__init__(parent)
        
        self.setAttribute(Qt.WA_InputMethodEnabled, True)
        self.setMouseTracking(False)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)       
      
        self.scene = scene
        self.setDocument(TextDocument(parent=self))

        self.setWordWrapMode(QTextOption.WrapAtWordBoundaryOrAnywhere)
        self.setLineWrapMode(self.LineWrapMode.FixedPixelWidth)
        self.setLineWrapColumnOrWidth(self.document()._pageWidth)
        self.setAttribute(Qt.WA_InputMethodEnabled, True)
        self.setInputMethodHints(Qt.ImhMultiLine)
        self.resize(self.document()._pageSize.toSize().width(), self.document()._pageSize.toSize().height()*3)
        self.setPlainText("Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
                        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
                        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
                        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
                        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
                        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
                        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
                        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
                        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
                        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
                        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
                        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
                        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
                        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
                        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
                        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
                        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
                        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
                        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
                        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
                        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
                        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
                        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
                        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
                        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
                        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
                        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
                        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
                        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
                        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
                        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
                        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
                        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
                        \Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
                        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
                        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
                        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
                        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
                        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
                        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
                        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
                        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit, \
                        sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
                        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \
                        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \
                        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")

    def mouseMoveEvent(self, event):


        print(event.position())
        return QTextEdit.mouseMoveEvent(self, event)

    
    def view(self):

        return self.scene.root_view
    
    def pageSize(self):

        return self.document()._pageSize    
        

class TextDocument(QTextDocument):
    
    def __init__(self, parent=None):
        super().__init__(parent)

        self._pageSize = QPageSize.size(QPageSize.A4, QPageSize.Point)       
 
        self._pageHeight = self._pageSize.height()
        self._pageWidth  = self._pageSize.width()
        self.setDocumentMargin(30.5) 


def main():
    import sys
    
    app = QApplication([]) if QApplication.instance() is None else QApplication.instance()
    m = MainGraphicsView()
    m.show()
    sys.exit(app.exec())

if __name__ == "__main__":
    main()

Solution

  • from your comment:

    if I use QGraphicsView and shows the each page, I don't have to calculate the position of QTextLines when the document is horizontally layouted. QGraphicsView can show each page horizontally, but in actual QTextEdit is all vertically layouted. That is why it is very simple.

    You need not to draw the lines on the basis of QTextLayout.

    QTextLine also has draw method.

    Please use QTextLine instead of QTextLayout.

    QTextLine draw