QmlDesigner: Optimize requesting an image info for tooltips

Avoid loading an image for the sole purpose of getting the dimensions.
Also small relevant tweaks.

Change-Id: I3d11175340cb77d3634fe7e69481ad26db8a74ef
Reviewed-by: Samuel Ghinet <samuel.ghinet@qt.io>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
Mahmoud Badri
2022-12-14 18:39:29 +02:00
parent 0feeb37ef7
commit bb37d782ca
5 changed files with 81 additions and 36 deletions

View File

@@ -22,6 +22,7 @@ add_qtc_library(QmlDesignerUtils STATIC
SOURCES
designersettings.cpp designersettings.h
hdrimage.cpp hdrimage.h
imageutils.cpp imageutils.h
qmldesignerutils_global.h
)

View File

@@ -3,8 +3,8 @@
#include "materialbrowsertexturesmodel.h"
#include "designeractionmanager.h"
#include "designmodewidget.h"
#include "imageutils.h"
#include "qmldesignerplugin.h"
#include "qmlobjectnode.h"
#include "variantproperty.h"
@@ -52,24 +52,18 @@ QVariant MaterialBrowserTexturesModel::data(const QModelIndex &index, int role)
return m_textureList.at(index.row()).internalId();
if (role == RoleTexToolTip) {
QString source = QmlObjectNode(m_textureList.at(index.row())).modelValue("source").toString();
QString source = data(index, RoleTexSource).toString(); // absolute path
if (source.isEmpty())
return tr("Texture has no source image.");
const QString noData = tr("Texture has no data.");
ModelNode texNode = m_textureList.at(index.row());
QString info = ImageUtils::imageInfo(source);
auto op = QmlDesignerPlugin::instance()->viewManager().designerActionManager()
.modelNodePreviewOperation(m_textureList.at(index.row()));
if (!op)
return noData;
if (info.isEmpty())
return tr("Texture has no data.");
QVariantMap imgMap = op(m_textureList.at(index.row())).toMap();
if (imgMap.isEmpty())
return noData;
return QLatin1String("%1\n%2\n%3").arg(imgMap.value("id").toString(),
source.split('/').last(),
imgMap.value("info").toString());
QString sourceRelative = QmlObjectNode(texNode).modelValue("source").toString();
return QLatin1String("%1\n%2\n%3").arg(texNode.id(), sourceRelative, info);
}
return {};

View File

@@ -25,6 +25,7 @@
#include "createscenecommand.h"
#include "debugoutputcommand.h"
#include "informationchangedcommand.h"
#include "imageutils.h"
#include "inputeventcommand.h"
#include "nodeabstractproperty.h"
#include "nodeinstanceserverproxy.h"
@@ -83,6 +84,8 @@
#include <QDirIterator>
#include <QFileSystemWatcher>
#include <QImageReader>
#include <QLocale>
#include <QMultiHash>
#include <QPainter>
#include <QPicture>
@@ -135,13 +138,13 @@ NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager
// related to a single event to be received before we act.
m_resetTimer.setSingleShot(true);
m_resetTimer.setInterval(100);
QObject::connect(&m_resetTimer, &QTimer::timeout, [this] {
QObject::connect(&m_resetTimer, &QTimer::timeout, this, [this] {
if (isAttached())
resetPuppet();
});
m_updateWatcherTimer.setSingleShot(true);
m_updateWatcherTimer.setInterval(100);
QObject::connect(&m_updateWatcherTimer, &QTimer::timeout, [this] {
QObject::connect(&m_updateWatcherTimer, &QTimer::timeout, this, [this] {
for (const auto &path : std::as_const(m_pendingUpdateDirs))
updateWatcher(path);
m_pendingUpdateDirs.clear();
@@ -152,11 +155,11 @@ NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager
// unnecessary generation when project with multiple shaders is opened.
m_generateQsbFilesTimer.setSingleShot(true);
m_generateQsbFilesTimer.setInterval(100);
QObject::connect(&m_generateQsbFilesTimer, &QTimer::timeout, [this] {
QObject::connect(&m_generateQsbFilesTimer, &QTimer::timeout, this, [this] {
handleShaderChanges();
});
connect(m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged,
connect(m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged, this,
[this](const QString &path) {
const QSet<QString> pendingDirs = m_pendingUpdateDirs;
for (const auto &pendingPath : pendingDirs) {
@@ -172,7 +175,7 @@ NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager
m_updateWatcherTimer.start();
});
connect(m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, [this](const QString &path) {
connect(m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, this, [this](const QString &path) {
if (m_qsbTargets.contains(path)) {
m_qsbTargets.insert(path, true);
m_generateQsbFilesTimer.start();
@@ -1910,23 +1913,7 @@ QVariant NodeInstanceView::previewImageDataForImageNode(const ModelNode &modelNo
imageData.pixmap = originalPixmap.scaled(dim, dim, Qt::KeepAspectRatio);
imageData.pixmap.setDevicePixelRatio(ratio);
imageData.time = modified;
double imgSize = double(imageFi.size());
static QStringList units({::QmlDesigner::NodeInstanceView::tr("B"),
::QmlDesigner::NodeInstanceView::tr("KB"),
::QmlDesigner::NodeInstanceView::tr("MB"),
::QmlDesigner::NodeInstanceView::tr("GB")});
int unitIndex = 0;
while (imgSize > 1024. && unitIndex < units.size() - 1) {
++unitIndex;
imgSize /= 1024.;
}
imageData.info = QStringLiteral("%1 x %2\n%3%4 (%5)")
.arg(originalPixmap.width())
.arg(originalPixmap.height())
.arg(QString::number(imgSize, 'g', 3))
.arg(units[unitIndex])
.arg(imageFi.suffix());
imageData.info = ImageUtils::imageInfo(imageSource);
m_imageDataMap.insert(imageData.id, imageData);
}
}

View File

@@ -0,0 +1,46 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "imageutils.h"
#include <QFile>
#include <QFileInfo>
#include <QImageReader>
namespace QmlDesigner {
QString QmlDesigner::ImageUtils::imageInfo(const QString &path)
{
QFileInfo info(path);
if (!info.exists())
return {};
int width = 0;
int height = 0;
if (info.suffix() == "hdr") {
QFile file(path);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return {};
while (!file.atEnd()) {
QByteArray line = file.readLine();
if (sscanf(line.constData(), "-Y %d +X %d", &height, &width))
break;
}
} else {
QSize size = QImageReader(path).size();
width = size.width();
height = size.height();
}
if (width == 0 && height == 0)
return {};
return QLatin1String("%1 x %2\n%3 (%4)")
.arg(QString::number(width),
QString::number(height),
QLocale::system().formattedDataSize(info.size(), 2, QLocale::DataSizeTraditionalFormat),
info.suffix());
}
} // namespace QmlDesigner

View File

@@ -0,0 +1,17 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#pragma once
#include <QString>
namespace QmlDesigner {
class ImageUtils
{
public:
ImageUtils();
static QString imageInfo(const QString &path);
};
} // namespace QmlDesigner