From 8004909f79d087344eef0701443784ed665a09c5 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Fri, 3 Sep 2021 16:35:59 +0300 Subject: [PATCH] QmlDesigner: Fix crash on asset library refresh Asset library refresh will crash if done while there is a modal dialog open, so postpone it a bit in that case. The timer used for this will also reduce unnecessary refreshes, improving overall performance. Change-Id: Ib2ff29f5f79428c6543a20f611c708ba80e88ded Reviewed-by: Mahmoud Badri Reviewed-by: Qt CI Bot --- .../itemlibrary/itemlibrarywidget.cpp | 34 +++++++++++++------ .../itemlibrary/itemlibrarywidget.h | 1 + 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp index 1a38eb509ef..3c8a76597bd 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.cpp @@ -161,6 +161,8 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache, { m_compressionTimer.setInterval(200); m_compressionTimer.setSingleShot(true); + m_assetCompressionTimer.setInterval(200); + m_assetCompressionTimer.setSingleShot(true); ItemLibraryModel::registerQmlTypes(); setWindowTitle(tr("Library", "Title of library view")); @@ -234,17 +236,7 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache, // reconstruct the model to update the icons connect(m_fileSystemWatcher, &Utils::FileSystemWatcher::directoryChanged, [this](const QString & changedDirPath) { Q_UNUSED(changedDirPath) - // TODO: find a clever way to only refresh the changed directory part of the model - - m_assetsModel->refresh(); - if (!QApplication::activeModalWidget()) { - // reload assets qml so that an overridden file's image shows the new image - QTimer::singleShot(100, this, [this] { - const QString assetsQmlPath = qmlSourcesPath() + "/Assets.qml"; - m_assetsWidget->engine()->clearComponentCache(); - m_assetsWidget->setSource(QUrl::fromLocalFile(assetsQmlPath)); - }); - } + m_assetCompressionTimer.start(); }); m_stackedWidget = new QStackedWidget(this); @@ -270,6 +262,26 @@ ItemLibraryWidget::ItemLibraryWidget(AsynchronousImageCache &imageCache, connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &ItemLibraryWidget::reloadQmlSource); connect(&m_compressionTimer, &QTimer::timeout, this, &ItemLibraryWidget::updateModel); + connect(&m_assetCompressionTimer, &QTimer::timeout, this, [this]() { + // TODO: find a clever way to only refresh the changed directory part of the model + + // Don't bother with asset updates after model has detached, project is probably closing + if (!m_model.isNull()) { + if (QApplication::activeModalWidget()) { + // Retry later, as updating file system watchers can crash when there is an active + // modal widget + m_assetCompressionTimer.start(); + } else { + m_assetsModel->refresh(); + // reload assets qml so that an overridden file's image shows the new image + QTimer::singleShot(100, this, [this] { + const QString assetsQmlPath = qmlSourcesPath() + "/Assets.qml"; + m_assetsWidget->engine()->clearComponentCache(); + m_assetsWidget->setSource(QUrl::fromLocalFile(assetsQmlPath)); + }); + } + } + }); m_itemViewQuickWidget->engine()->addImageProvider("itemlibrary_preview", new ItemLibraryIconImageProvider{m_imageCache}); diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h index 6116b0d9d42..4910fedc182 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h @@ -119,6 +119,7 @@ private: void handlePriorityImportsChanged(); QTimer m_compressionTimer; + QTimer m_assetCompressionTimer; QSize m_itemIconSize; SynchronousImageCache &m_fontImageCache;