5#include <private/qtquickglobal_p.h>
11#if QT_CONFIG(quick_shadereffect)
12#include "qquickshadereffectsource_p.h"
15#include <QtQml/QQmlEngine>
16#include <QtQml/QQmlInfo>
18#include <private/qquickpixmap_p.h>
19#include <private/qquickitem_p.h>
20#include <private/qsgcontext_p.h>
21#include <private/qsgadaptationlayer_p.h>
23#include <QtCore/qpointer.h>
46 qmlEngine->handle()->memoryManager->changeUnmanagedHeapSizeUsage(-image.sizeInBytes());
50 bool hasCallback()
const {
return qmlEngine && callback.isCallable(); }
53 if (url.isEmpty() && !image.isNull()) {
54 url.setScheme(QQuickPixmap::itemGrabberScheme);
55 url.setPath(QVariant::fromValue(item.data()).toString());
56 static uint counter = 0;
57 url.setFragment(QString::number(++counter));
58 cacheEntry =
new QQuickPixmap(url, image);
62 static QQuickItemGrabResult *
create(QQuickItem *item,
const QSize &size);
81
82
83
84
85
86
87
88
89
90
91
92
95
96
97
98
99
100
101
102
103
104
107
108
109
110
111
114
115
116
117
118
119
120
123
124
125
126
127
128
131
132
133
134
137
138
139
140
141
142
143
144
145
146
147
148
150QQuickItemGrabResult::QQuickItemGrabResult(QObject *parent)
151 : QObject(*
new QQuickItemGrabResultPrivate, parent)
156
157
158
159
160
164
165
166
167
168
169bool QQuickItemGrabResult::saveToFile(
const QString &fileName)
const
171 Q_D(
const QQuickItemGrabResult);
172 if (fileName.startsWith(QLatin1String(
"file:/")))
173 return saveToFile(QUrl(fileName));
174 return d->image.save(fileName);
178
179
180
181
182
183
184bool QQuickItemGrabResult::saveToFile(
const QUrl &filePath)
const
186 Q_D(
const QQuickItemGrabResult);
187 if (!filePath.isLocalFile()) {
188 qWarning() <<
"saveToFile can only save to a file on the local filesystem";
191 return d->image.save(filePath.toLocalFile());
194#if QT_VERSION < QT_VERSION_CHECK(6
, 0
, 0
)
195#if QT_DEPRECATED_SINCE(5
, 15
)
197
198
199
200bool QQuickItemGrabResult::saveToFile(
const QString &fileName)
202 return std::as_const(*
this).saveToFile(fileName);
207QUrl QQuickItemGrabResult::url()
const
209 Q_D(
const QQuickItemGrabResult);
210 d->ensureImageInCache();
214QImage QQuickItemGrabResult::image()
const
216 Q_D(
const QQuickItemGrabResult);
221
222
223bool QQuickItemGrabResult::event(QEvent *e)
225 Q_D(QQuickItemGrabResult);
226 if (e->type() == Event_Grab_Completed) {
227 if (d->hasCallback()) {
231 QQmlEngine::setObjectOwnership(
this, QQmlEngine::JavaScriptOwnership);
233 d->callback.call(QJSValueList() << d->qmlEngine->newQObject(
this));
239 return QObject::event(e);
242void QQuickItemGrabResult::setup()
244 Q_D(QQuickItemGrabResult);
246 disconnect(d->window.data(), &QQuickWindow::beforeSynchronizing,
this, &QQuickItemGrabResult::setup);
247 disconnect(d->window.data(), &QQuickWindow::afterRendering,
this, &QQuickItemGrabResult::render);
248 QCoreApplication::postEvent(
this,
new QEvent(Event_Grab_Completed));
252 QSGRenderContext *rc = QQuickWindowPrivate::get(d->window.data())->context;
253 d->devicePixelRatio = d->window->effectiveDevicePixelRatio();
254 d->texture = rc->sceneGraphContext()->createLayer(rc);
255 d->texture->setDevicePixelRatio(d->devicePixelRatio);
256 d->texture->setItem(QQuickItemPrivate::get(d->item)->itemNode());
257 d->itemSize = QSizeF(d->item->width(), d->item->height());
260void QQuickItemGrabResult::render()
262 Q_D(QQuickItemGrabResult);
266 d->texture->setRect(QRectF(0, d->itemSize.height(), d->itemSize.width(), -d->itemSize.height()));
267 const QSize minSize = QQuickWindowPrivate::get(d->window.data())->context->sceneGraphContext()->minimumFBOSize();
268 const QSize effectiveTextureSize = d->textureSize * d->devicePixelRatio;
269 d->texture->setSize(QSize(qMax(minSize.width(), effectiveTextureSize.width()),
270 qMax(minSize.height(), effectiveTextureSize.height())));
271 d->texture->scheduleUpdate();
272 d->texture->updateTexture();
274 const qsizetype oldImageSize = d->image.sizeInBytes();
275 d->image = d->texture->toImage();
276 d->image.setDevicePixelRatio(d->devicePixelRatio);
277 const qsizetype newImageSize = d->image.sizeInBytes();
278 if (d->hasCallback()) {
286 d->qmlEngine->handle()->memoryManager->changeUnmanagedHeapSizeUsage(
287 newImageSize - oldImageSize);
291 d->texture =
nullptr;
293 disconnect(d->window.data(), &QQuickWindow::beforeSynchronizing,
this, &QQuickItemGrabResult::setup);
294 disconnect(d->window.data(), &QQuickWindow::afterRendering,
this, &QQuickItemGrabResult::render);
295 QCoreApplication::postEvent(
this,
new QEvent(Event_Grab_Completed));
300 QSize size = targetSize;
302 size = QSize(item->width(), item->height());
304 if (size.width() < 1 || size.height() < 1) {
305 qmlWarning(item) <<
"grabToImage: item has invalid dimensions";
309 if (!item->window()) {
310 qmlWarning(item) <<
"grabToImage: item is not attached to a window";
314 QWindow *effectiveWindow = item->window();
315 if (QWindow *renderWindow = QQuickRenderControl::renderWindowFor(item->window()))
316 effectiveWindow = renderWindow;
318 if (!effectiveWindow->isVisible()) {
319 qmlWarning(item) <<
"grabToImage: item's window is not visible";
325 QQuickItemGrabResult *result =
new QQuickItemGrabResult(item);
328 d->window = item->window();
329 d->textureSize = size;
331 QQuickItemPrivate::get(item)->refFromEffectItem(
false);
334 item->window()->update();
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357QSharedPointer<QQuickItemGrabResult> QQuickItem::grabToImage(
const QSize &targetSize)
359 QQuickItemGrabResult *result = QQuickItemGrabResultPrivate::create(
this, targetSize);
361 return QSharedPointer<QQuickItemGrabResult>();
363 connect(window(), &QQuickWindow::beforeSynchronizing, result, &QQuickItemGrabResult::setup, Qt::DirectConnection);
364 connect(window(), &QQuickWindow::afterRendering, result, &QQuickItemGrabResult::render, Qt::DirectConnection);
366 return QSharedPointer<QQuickItemGrabResult>(result);
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
400
401
402
403bool QQuickItem::grabToImage(
const QJSValue &callback,
const QSize &targetSize)
405 QQmlEngine *engine = qmlEngine(
this);
407 qmlWarning(
this) <<
"grabToImage: item has no QML engine";
411 if (!callback.isCallable()) {
412 qmlWarning(
this) <<
"grabToImage: 'callback' is not a function";
416 QSize size = targetSize;
418 size = QSize(width(), height());
420 if (size.width() < 1 || size.height() < 1) {
421 qmlWarning(
this) <<
"grabToImage: item has invalid dimensions";
426 qmlWarning(
this) <<
"grabToImage: item is not attached to a window";
430 QQuickItemGrabResult *result = QQuickItemGrabResultPrivate::create(
this, size);
434 connect(window(), &QQuickWindow::beforeSynchronizing, result, &QQuickItemGrabResult::setup, Qt::DirectConnection);
435 connect(window(), &QQuickWindow::afterRendering, result, &QQuickItemGrabResult::render, Qt::DirectConnection);
439 QQuickItemGrabResultPrivate *d = result->d_func();
440 d->qmlEngine = engine;
441 d->callback = callback;
447#include "moc_qquickitemgrabresult.cpp"
QQuickItemGrabResultPrivate()
~QQuickItemGrabResultPrivate()
void ensureImageInCache() const
QPointer< QQuickWindow > window
QQuickPixmap * cacheEntry
static QQuickItemGrabResult * create(QQuickItem *item, const QSize &size)
QPointer< QQuickItem > item
Combined button and popup list for selecting options.
QT_BEGIN_NAMESPACE const QEvent::Type Event_Grab_Completed