forked from qt-creator/qt-creator
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:
@@ -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
|
||||
)
|
||||
|
||||
|
@@ -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 {};
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
46
src/plugins/qmldesigner/utils/imageutils.cpp
Normal file
46
src/plugins/qmldesigner/utils/imageutils.cpp
Normal 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
|
17
src/plugins/qmldesigner/utils/imageutils.h
Normal file
17
src/plugins/qmldesigner/utils/imageutils.h
Normal 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
|
Reference in New Issue
Block a user