Hello. I already asked this on the PyQt mailing list but I guess it was not the 
right place; this is more of a Qt problem. I’m trying to implement a custom URI 
scheme handler, in a context where the underlying data will actually be fetched 
asynchronously. I reduced the problem to the « minimal » code pasted below 
(python 3.5, PyQt 5.8/Qt 5.8). Basically the problem is that when I call 
QWebEngineUrlRequestJob.reply() with an instance of my custom QIODevice, I 
expect the following:

1. bytesAvailable() is called, returns 0 (no data available yet)
2. The request job waits for readyRead to be emitted
3. The proceeds with bytesAvailable() / readData() until data is exhausted
4. Goto 2, until readChannelFinished is emitted

What actually happens:

1. bytesAvailable() is called, returns 0
2. The request job tries to read 32 Kb nonetheless
3. It gets no data, closes the QIODevice

Did I miss something here ? This happens on both mac OS and Linux. Didn’t try 
on Windows yet.

TIA
Jérôme Laheurte

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWebEngineCore import QWebEngineUrlSchemeHandler


class TestIODevice(QtCore.QIODevice):
   def __init__(self):
       super().__init__()
       self.open(self.ReadOnly | self.Unbuffered)
       self._data = b''
       QtCore.QTimer.singleShot(1000, self._dataReceived)

   def _dataReceived(self):
       print('== RECV')
       self._data = b'foo'
       self.readyRead.emit()

   def bytesAvailable(self):
       count = len(self._data) + super().bytesAvailable()
       print('== AVAIL', count)
       return count

   def isSequential(self):
       return True

   def readData(self, maxSize):
       print('== READ', maxSize)
       data, self._data = self._data[:maxSize], self._data[maxSize:]
       return data

   def close(self):
       print('== CLOSE')
       super().close()


class TestHandler(QWebEngineUrlSchemeHandler):
   def requestStarted(self, request):
       self._dev = TestIODevice() # Must keep ref
       request.reply(b'text/plain', self._dev)


class TestWindow(QtWidgets.QMainWindow):
   def __init__(self):
       super().__init__()
       self._view = QWebEngineView(self)
       self._handler = TestHandler() # Must keep ref
       self._view.page().profile().installUrlSchemeHandler(b'spam', 
self._handler)
       self._view.setHtml('<html><head><title>Test</title></head><body><img 
src="spam:eggs" /></body></html>')
       self.setCentralWidget(self._view)
       self.show()
       self.raise_()


if __name__ == '__main__':
   app = QtWidgets.QApplication([])
   win = TestWindow()
   app.exec_()
_______________________________________________
Interest mailing list
Interest@qt-project.org
http://lists.qt-project.org/mailman/listinfo/interest

Reply via email to