Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to trigger a mousePressEvent artificially on a QWebView?

Tags:

python

pyqt

pyqt4

Due to an astronomically atrocious bug on PyQt4, I need to fire a mousePressEvent artificially on a QWebView as a last breath of hope. For some obscure reason, QWebView's linkClicked and urlChanged signals do not pass a QUrl when the clicked link has Javascript involved (It does not work on Youtube videos, for example) and when the link was clicked with the left mouse button. The QUrl can be perfectly accessed when the link was clicked with the middle and right buttons.

class CQWebView(QtWebKit.QWebView): 

    def mousePressEvent(self, event):
        if type(event) == QtGui.QMouseEvent:
            if event.button() == QtCore.Qt.LeftButton:
                # FIRE A QtCore.Qt.MiddleButton EVENT HERE,
                # SO THAT I CAN GET THE BLOODY LINK AFTERWARDS.
            elif event.button() == QtCore.Qt.MiddleButton:
                self.emit(QtCore.SIGNAL("OPEN_IN_NEW_TAB")) # Example
            elif event.button() == QtCore.Qt.RightButton:
                self.emit(QtCore.SIGNAL("XXX")) # Example

So, I literally want to "click artificially", click without clicking, just trigger the event of clicking with the middle right button on a link, so that I can catch the QUrl correctly.

like image 479
Ericson Willians Avatar asked May 25 '16 05:05

Ericson Willians


2 Answers

You can do it using the QtTest module as well. Set an event filter on your web view and check for left click mouse events and send a middle mouse click

def __init__(...)
    self.ui_web_view.installEventFilter(self)

def eventFilter(self, obj, event):
    if obj == self.ui_web_view:
        if event.type() == QtCore.QEvent.MouseButtonPress:
            if event.button() == QtCore.Qt.LeftButton:
                print 'Handled'
                QtTest.QTest.mouseClick(self.ui_web_view, QtCore.Qt.MiddleButton, QtCore.Qt.NoModifier, event.pos())
                return True
    return False
like image 93
Brendan Abel Avatar answered Oct 01 '22 23:10

Brendan Abel


I've managed to click with the middle button by clicking with the left button using the sendEvent method from QtGui.QApplication.

class CQWebView(QtWebKit.QWebView): 

    app = None

    def __init__(self, app):
        QtWebKit.QWebView.__init__(self)
        CQWebView.app = app

    def mousePressEvent(self, event):
        if type(event) == QtGui.QMouseEvent:
            if event.button() == QtCore.Qt.LeftButton:
                CQWebView.app.sendEvent(self, QtGui.QMouseEvent(event.type(), event.pos(), QtCore.Qt.MiddleButton, event.buttons(), event.modifiers()))
            elif event.button() == QtCore.Qt.MiddleButton:
                self.emit(QtCore.SIGNAL("linkClicked(const QUrl&)")) # Problem
            elif event.button() == QtCore.Qt.RightButton:
                self.emit(QtCore.SIGNAL("XXX")) # Example

I just needed to pass the instance of the QApplication to the instance of the custom QWebView on instantiation:

def compose_tab(self, index):
        self.tabs[index].append(CQWebView(self))

This way, I click on the QWebView with the left mouse button and I click artificially on it with the middle button. The problem is that doing so I'm overriding the default behavior of the linkClicked and urlChanged signals from the QWebView. Even though I can emit these signals, I can't have access to the address of the link that was clicked, since by accessing QWebView.url() only gives me the present QUrl, and not the future clicked one.

Really frustrating.

like image 44
Ericson Willians Avatar answered Sep 28 '22 23:09

Ericson Willians