-
Notifications
You must be signed in to change notification settings - Fork 0
[Bug] Asynchronous loading of adjacent pages fails #171
Description
Describe the bug
When opening a document with multiple pages from the document view, you can see the following message in the log output:
QObject::connect: Cannot queue arguments of type 'std::shared_ptr<UBDocumentProxy>'
(Make sure 'std::shared_ptr<UBDocumentProxy>' is registered using qRegisterMetaType().)
The reason is that adjacent pages are asynchronously loaded using the UBPersistenceWorker. When it is finished, it emits
| emit sceneLoaded(UBSvgSubsetAdaptor::loadSceneAsText(info.proxy,info.sceneIndex), info.proxy, info.sceneIndex); |
The second parameter to this signal is of type
std::shared_ptr<UBDocumentProxy>, which is not known to the meta type system and can therefore not be sent over a queued connection.
To Reproduce
- Start OpenBoard, create a multi-page document and close it again
- Start OpenBoard a second time
- Go to document mode and select the previously created document
- Click on "Opening Board"
Expected behavior
The first (or the selected) document page should appear. Adjacent pages should be loaded asynchronously to the scene cache.
Actual behavior
The first (or the selected) document page appears as expected. But loading adjacent pages fails and is broken in several aspects:
- First the
UBPersistenceWorkerreads the scene file text usingUBSvgSubsetAdaptor::loadSceneAsText. - Then the signal described above is emitted, but will never arrive because the
shared_ptrcannot be sent over a queued connection. - But if it arrives, then
UBPersistenceManager::onSceneLoadedwould be called:
OpenBoard/src/core/UBPersistenceManager.cpp
Lines 175 to 183 in 0e69a0a
void UBPersistenceManager::onSceneLoaded(QByteArray scene, std::shared_ptr<UBDocumentProxy> proxy, int sceneIndex) { Q_UNUSED(scene); qDebug() << "scene loaded " << sceneIndex; QElapsedTimer time; time.start(); mSceneCache.insert(proxy, sceneIndex, loadDocumentScene(proxy, sceneIndex, false)); qDebug() << "millisecond for sceneCache " << time.elapsed(); } - Here the loaded scene is not used at all. Instead
loadDocumentScenewould be called on the main thread, which again reads the file text.
Additional resources
The following are just some assumptions, but might provide background for further analysis.
- The initial idea of loading adjacent pages in the background is perfect and should improve user experience when switching pages.
- It may be that a first attempt was to load the
UBGraphicsScenein the worker thread. But if we do that, then the scene is owned by the worker thread and cannot easily be transferred to the main thread, as it consists of many objects. - So the second idea was to do just the I/O in the background and to send the data as
QByteArrayover a connection to the main thread. Here it should be scanned and the scene created from that. - For some unknown reason however
loadDocumentSceneis used, which again reads the scene from disk. Why not using
OpenBoard/src/adaptors/UBSvgSubsetAdaptor.cpp
Lines 341 to 345 in 0e69a0a
std::shared_ptr<UBGraphicsScene> UBSvgSubsetAdaptor::loadScene(std::shared_ptr<UBDocumentProxy> proxy, const QByteArray& pArray) { UBSvgSubsetReader reader(proxy, UBTextTools::cleanHtmlCData(QString(pArray)).toUtf8()); return reader.loadScene(proxy); }
which is exactly doing this?
Context
- reproducibility :
systematic - OpenBoard version :
- bug happens with :
1.7.01.7.1a-x.y.z - didn't check :
1.6.4
- bug happens with :
- OS :
- bug happens with :
Linux - didn't check :
WindowsmacOS
- bug happens with :
- Installation source :
own build - If you built OpenBoard from source, please provide the branch you're working on :
dev