diff options
Diffstat (limited to 'src/gui/doc')
26 files changed, 464 insertions, 206 deletions
diff --git a/src/gui/doc/images/qpainter-concentriccircles.png b/src/gui/doc/images/qpainter-concentriccircles.png Binary files differindex 4889dcd76d..d9489a4162 100644 --- a/src/gui/doc/images/qpainter-concentriccircles.png +++ b/src/gui/doc/images/qpainter-concentriccircles.png diff --git a/src/gui/doc/includes/QtGuiDoc b/src/gui/doc/includes/QtGuiDoc index 80292141e2..e8fa73786e 100644 --- a/src/gui/doc/includes/QtGuiDoc +++ b/src/gui/doc/includes/QtGuiDoc @@ -16,3 +16,8 @@ #include <QtGui/qpa/qplatformscreen_p.h> #include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qkeymapper_p.h> + +// rhi +#include <QtGui/rhi/qrhi.h> +#include <QtGui/rhi/qshader.h> +#include <QtGui/rhi/qshaderdescription.h> diff --git a/src/gui/doc/qtgui.qdocconf b/src/gui/doc/qtgui.qdocconf index 333a8d7449..b94f11849c 100644 --- a/src/gui/doc/qtgui.qdocconf +++ b/src/gui/doc/qtgui.qdocconf @@ -39,6 +39,7 @@ depends += \ qtdoc \ qmake \ qtcmake \ + qtshadertools \ qttestlib \ qtplatformintegration \ qthelp @@ -62,7 +63,7 @@ imagedirs += images \ excludefiles += ../kernel/qtestsupport_gui.cpp \ ../painting/qdrawhelper_ssse3.cpp -# manifestmeta.highlighted.names = "QtGui/Analog Clock Window Example" +manifestmeta.highlighted.names = "QtGui/Hello Vulkan Cubes Example" navigation.landingpage = "Qt GUI" navigation.cppclassespage = "Qt GUI C++ Classes" @@ -74,5 +75,5 @@ spurious += "Undocumented enum item '.*' in QGradient::Preset" macro.svgcolor.HTML = "<div style=\"padding:10px;color:#fff;background:\1;\"></div>" macro.svgcolor.DocBook = "<db:phrase role=\"color:\1\">          </db:phrase>" -# Fail the documentation build if there are more warnings than the limit +# Enforce zero documentation warnings warninglimit = 0 diff --git a/src/gui/doc/snippets/code/doc_src_richtext.qdoc b/src/gui/doc/snippets/code/doc_src_richtext.qdoc index 39e29caa8d..0c69514210 100644 --- a/src/gui/doc/snippets/code/doc_src_richtext.qdoc +++ b/src/gui/doc/snippets/code/doc_src_richtext.qdoc @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only //! [7] <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP" /> diff --git a/src/gui/doc/snippets/code/src_gui_image_qicon.cpp b/src/gui/doc/snippets/code/src_gui_image_qicon.cpp index d446f16c3c..a7f27a7fdd 100644 --- a/src/gui/doc/snippets/code/src_gui_image_qicon.cpp +++ b/src/gui/doc/snippets/code/src_gui_image_qicon.cpp @@ -8,7 +8,7 @@ namespace src_gui_image_qicon { struct MyWidget : public QWidget { - void drawIcon(QPainter *painter, QPoint pos); + void drawIcon(QPainter *painter, const QRect &rect); bool isChecked() { return true; } QIcon icon; }; @@ -17,9 +17,13 @@ void wrapper0() { //! [0] QToolButton *button = new QToolButton; -button->setIcon(QIcon("open.xpm")); +button->setIcon(QIcon("open.png")); //! [0] +//! [addFile] +QIcon openIcon("open.png"); +openIcon.addFile("open-disabled.png", QIcon::Disabled); +//! [addFile] //! [1] button->setIcon(QIcon()); @@ -29,29 +33,27 @@ button->setIcon(QIcon()); //! [2] -void MyWidget::drawIcon(QPainter *painter, QPoint pos) +void MyWidget::drawIcon(QPainter *painter, const QRect &rect) { - QPixmap pixmap = icon.pixmap(QSize(22, 22), - isEnabled() ? QIcon::Normal - : QIcon::Disabled, - isChecked() ? QIcon::On - : QIcon::Off); - painter->drawPixmap(pos, pixmap); + icon.paint(painter, rect, Qt::AlignCenter, isEnabled() ? QIcon::Normal + : QIcon::Disabled, + isChecked() ? QIcon::On + : QIcon::Off); } //! [2] void wrapper1() { -//! [3] -QIcon undoicon = QIcon::fromTheme("edit-undo"); -//! [3] +//! [fromTheme] +QIcon undoicon = QIcon::fromTheme(QIcon::ThemeIcon::EditUndo); +//! [fromTheme] } // wrapper1 //! [4] -QIcon undoicon = QIcon::fromTheme("edit-undo", QIcon(":/undo.png")); +QIcon undoicon = QIcon::fromTheme(QIcon::ThemeIcon::EditUndo, QIcon(":/undo.png")); //! [4] diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qapplication.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qapplication.cpp index ab8521b465..9455cacf1c 100644 --- a/src/gui/doc/snippets/code/src_gui_kernel_qapplication.cpp +++ b/src/gui/doc/snippets/code/src_gui_kernel_qapplication.cpp @@ -19,70 +19,6 @@ struct MyWidget int manhattanLength() { return 0; } }; - -//! [0] -QCoreApplication *createApplication(int &argc, char *argv[]) -{ - for (int i = 1; i < argc; ++i) - if (!qstrcmp(argv[i], "-no-gui")) - return new QCoreApplication(argc, argv); - return new QApplication(argc, argv); -} - -int main(int argc, char *argv[]) -{ - QScopedPointer<QCoreApplication> app(createApplication(argc, argv)); - - if (qobject_cast<QApplication *>(app.data())) { - // start GUI version... - } else { - // start non-GUI version... - } - - return app->exec(); -} -//! [0] - - -void wrapper0() { - -//! [1] -QApplication::setStyle(QStyleFactory::create("fusion")); -//! [1] - -} // wrapper0 - - -//! [3] -QSize MyWidget::sizeHint() const -{ - return QSize(80, 25); -} -//! [3] - - -//! [4] -void showAllHiddenTopLevelWidgets() -{ - const auto topLevelWidgets = QApplication::topLevelWidgets(); - for (QWidget *widget : topLevelWidgets) { - if (widget->isHidden()) - widget->show(); - } -} -//! [4] - - -//! [5] -void updateAllWidgets() -{ - const auto topLevelWidgets = QApplication::topLevelWidgets(); - for (QWidget *widget : topLevelWidgets) - widget->update(); -} -//! [5] - - void startTheDrag() {}; void wrapper1() { MyWidget startPos; @@ -96,25 +32,6 @@ if ((startPos - currentPos).manhattanLength() >= startTheDrag(); //! [6] - -//! [7] -QWidget *widget = qApp->widgetAt(x, y); -if (widget) - widget = widget->window(); -//! [7] - } // wrapper1 - -void wrapper2() { -QPoint point; - -//! [8] -QWidget *widget = qApp->widgetAt(point); -if (widget) - widget = widget->window(); -//! [8] - - -} // wrapper2 } // src_gui_kernel_qapplication diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp index e9a2446b91..347b47403e 100644 --- a/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp +++ b/src/gui/doc/snippets/code/src_gui_kernel_qguiapplication.cpp @@ -74,26 +74,4 @@ appname -session id */ // wrap snippet 2 - -void wrapper0() { - - -//! [3] -const QStringList commands = mySession.restartCommand(); -for (const QString &command : commands) - do_something(command); -//! [3] - -} // wrapper0 - - -void wrapper1() { -//! [4] -const QStringList commands = mySession.discardCommand(); -for (const QString &command : mySession.discardCommand()) - do_something(command); -//! [4] - - -} // wrapper1 } // src_gui_kernel_qguiapplication diff --git a/src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp b/src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp index 17436c9de5..cfbf3e44a2 100644 --- a/src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp +++ b/src/gui/doc/snippets/code/src_gui_painting_qpainter.cpp @@ -63,6 +63,7 @@ struct MyWidget : public QWidget void wrapper13(); void wrapper14(); void wrapper15(); + void concentricCircles(); }; QLine drawingCode; @@ -97,15 +98,6 @@ struct QPainter { void setWorldTransform(QTransform matrix, bool); }; -//! [4] -void QPainter::rotate(qreal angle) -{ - QTransform matrix; - matrix.rotate(angle); - setWorldTransform(matrix, true); -} -//! [4] - } // QPainterWrapper void MyWidget::wrapper1() { @@ -123,7 +115,7 @@ painter.drawPath(path); //! [6] QLineF line(10.0, 80.0, 90.0, 20.0); -QPainter(this); +QPainter painter(this); painter.drawLine(line); //! [6] } // MyWidget::wrapper1() @@ -260,7 +252,7 @@ QRectF target(10.0, 20.0, 80.0, 60.0); QRectF source(0.0, 0.0, 70.0, 40.0); QPixmap pixmap(":myPixmap.png"); -QPainter(this); +QPainter painter(this); painter.drawPixmap(target, pixmap, source); //! [16] @@ -364,4 +356,21 @@ painter.drawRect(rectangle.adjusted(0, 0, -pen.width(), -pen.width())); } // MyWidget::wrapper15 -} // src_gui_painting_qpainter2 + +void MyWidget::concentricCircles() +{ +//! [renderHint] + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing, true); +//! [renderHint] + int diameter = 50; +//! [floatBased] + painter.drawEllipse(QRectF(-diameter / 2.0, -diameter / 2.0, diameter, diameter)); +//! [floatBased] +//! [intBased] + painter.drawEllipse(QRect(-diameter / 2, -diameter / 2, diameter, diameter)); +//! [intBased] + +} // MyWidget::concentricCircles + +} // src_gui_painting_qpainter2
\ No newline at end of file diff --git a/src/gui/doc/snippets/code/src_gui_text_qtextdocument.cpp b/src/gui/doc/snippets/code/src_gui_text_qtextdocument.cpp deleted file mode 100644 index 570728f41d..0000000000 --- a/src/gui/doc/snippets/code/src_gui_text_qtextdocument.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -namespace src_gui_text_qtextdocument { - -/* wrap non-code snippet - -//! [0] -<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body>... -//! [0] - -*/ // wrap non-code snippet -} // src_gui_text_qtextdocument diff --git a/src/gui/doc/snippets/code/src_gui_text_qtextlayout.cpp b/src/gui/doc/snippets/code/src_gui_text_qtextlayout.cpp index 2602c2ced0..70ec6b01ea 100644 --- a/src/gui/doc/snippets/code/src_gui_text_qtextlayout.cpp +++ b/src/gui/doc/snippets/code/src_gui_text_qtextlayout.cpp @@ -10,6 +10,7 @@ namespace src_gui_text_qtextlayout { struct Wrapper : public QPaintDevice { void wrapper1(); + void elided(); }; QTextLayout textLayout; @@ -24,7 +25,7 @@ int leading = fontMetrics.leading(); qreal height = 0; textLayout.setCacheEnabled(true); textLayout.beginLayout(); -while (1) { +while (true) { QTextLine line = textLayout.createLine(); if (!line.isValid()) break; @@ -49,4 +50,41 @@ textLayout.draw(&painter, QPoint(0, 0)); } // Wrapper::wrapper1 +void Wrapper::elided() { + +QString content; + +//! [elided] +QPainter painter(this); +QFontMetrics fontMetrics = painter.fontMetrics(); + +int lineSpacing = fontMetrics.lineSpacing(); +int y = 0; + +QTextLayout textLayout(content, painter.font()); +textLayout.beginLayout(); +while (true) { + QTextLine line = textLayout.createLine(); + + if (!line.isValid()) + break; + + line.setLineWidth(width()); + const int nextLineY = y + lineSpacing; + + if (height() >= nextLineY + lineSpacing) { + line.draw(&painter, QPoint(0, y)); + y = nextLineY; + } else { + const QString lastLine = content.mid(line.textStart()); + const QString elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, width()); + painter.drawText(QPoint(0, y + fontMetrics.ascent()), elidedLastLine); + line = textLayout.createLine(); + break; + } +} +textLayout.endLayout(); +//! [elided] +} + } // src_gui_text_qtextlayout diff --git a/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp b/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp index 96c8040eb2..13deb88bc8 100644 --- a/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp +++ b/src/gui/doc/snippets/code/src_gui_util_qdesktopservices.cpp @@ -65,15 +65,6 @@ QDesktopServices::openUrl(QUrl("file:///C:/Program Files", QUrl::TolerantMode)); */ // comment wrapper 2 - -void wrapper3() { -//! [6] -QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + - "/data/organization/application"; -//! [6] -} // wrapper3 - - /* comment wrapper 3 //! [7] <key>com.apple.developer.associated-domains</key> diff --git a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp index a83c6eb7f9..700d933f43 100644 --- a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp +++ b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkanfunctions.cpp @@ -8,20 +8,18 @@ namespace src_gui_vulkan_qvulkanfunctions { struct Window { - void render(); + void init(); QVulkanInstance *vulkanInstance() { return nullptr; } }; -VkDevice_T *device = nullptr; -VkCommandBufferAllocateInfo cmdBufInfo; -VkCommandBuffer cmdBuf; //! [0] -void Window::render() +void Window::init() { QVulkanInstance *inst = vulkanInstance(); QVulkanFunctions *f = inst->functions(); // ... - VkResult err = f->vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuf); + uint32_t count = 0; + VkResult err = f->vkEnumeratePhysicalDevices(inst->vkInstance(), &count, nullptr); // ... } //! [0] diff --git a/src/gui/doc/snippets/image/image.cpp b/src/gui/doc/snippets/image/image.cpp index b1c42d62da..82703c5c0f 100644 --- a/src/gui/doc/snippets/image/image.cpp +++ b/src/gui/doc/snippets/image/image.cpp @@ -25,13 +25,6 @@ buffer.open(QIODevice::WriteOnly); pixmap.save(&buffer, "PNG"); // writes pixmap into bytes in PNG format //! [1] - -//! [2] -QPixmap alpha("image-with-alpha.png"); -QPixmap alphacopy = alpha; -alphacopy.setMask(alphacopy.mask()); -//! [2] - } // wrapper1 } // image diff --git a/src/gui/doc/snippets/qfileopenevent/main.cpp b/src/gui/doc/snippets/qfileopenevent/main.cpp index b733bfc320..a94ff58137 100644 --- a/src/gui/doc/snippets/qfileopenevent/main.cpp +++ b/src/gui/doc/snippets/qfileopenevent/main.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2016 Samuel Gaist <samuel.gaist@edeltech.ch> +// Copyright (C) 2023 Samuel Gaist <samuel.gaist@edeltech.ch> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause //! [QApplication subclass] @@ -19,7 +19,15 @@ public: { if (event->type() == QEvent::FileOpen) { QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event); - qDebug() << "Open file" << openEvent->file(); + const QUrl url = openEvent->url(); + if (url.isLocalFile()) { + QFile localFile(url.toLocalFile()); + // read from local file + } else if (url.isValid()) { + // process according to the URL's schema + } else { + // parse openEvent->file() + } } return QApplication::event(event); diff --git a/src/gui/doc/snippets/rhioffscreen/color.frag b/src/gui/doc/snippets/rhioffscreen/color.frag new file mode 100644 index 0000000000..ad9d953d02 --- /dev/null +++ b/src/gui/doc/snippets/rhioffscreen/color.frag @@ -0,0 +1,16 @@ +//! [0] +#version 440 + +layout(location = 0) in vec3 v_color; +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform buf { + mat4 mvp; + float opacity; +}; + +void main() +{ + fragColor = vec4(v_color * opacity, opacity); +} +//! [0] diff --git a/src/gui/doc/snippets/rhioffscreen/color.vert b/src/gui/doc/snippets/rhioffscreen/color.vert new file mode 100644 index 0000000000..0010e55561 --- /dev/null +++ b/src/gui/doc/snippets/rhioffscreen/color.vert @@ -0,0 +1,18 @@ +//! [0] +#version 440 + +layout(location = 0) in vec4 position; +layout(location = 1) in vec3 color; +layout(location = 0) out vec3 v_color; + +layout(std140, binding = 0) uniform buf { + mat4 mvp; + float opacity; +}; + +void main() +{ + v_color = color; + gl_Position = mvp * position; +} +//! [0] diff --git a/src/gui/doc/snippets/rhioffscreen/main.cpp b/src/gui/doc/snippets/rhioffscreen/main.cpp new file mode 100644 index 0000000000..c2c6f74dc1 --- /dev/null +++ b/src/gui/doc/snippets/rhioffscreen/main.cpp @@ -0,0 +1,151 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +//! [0] +#include <QGuiApplication> +#include <QImage> +#include <QFile> +#include <rhi/qrhi.h> + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + +#if QT_CONFIG(vulkan) + QVulkanInstance inst; +#endif + std::unique_ptr<QRhi> rhi; +#if defined(Q_OS_WIN) + QRhiD3D12InitParams params; + rhi.reset(QRhi::create(QRhi::D3D12, ¶ms)); +#elif QT_CONFIG(metal) + QRhiMetalInitParams params; + rhi.reset(QRhi::create(QRhi::Metal, ¶ms)); +#elif QT_CONFIG(vulkan) + inst.setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions()); + if (inst.create()) { + QRhiVulkanInitParams params; + params.inst = &inst; + rhi.reset(QRhi::create(QRhi::Vulkan, ¶ms)); + } else { + qFatal("Failed to create Vulkan instance"); + } +#endif + if (rhi) + qDebug() << rhi->backendName() << rhi->driverInfo(); + else + qFatal("Failed to initialize RHI"); + + float rotation = 0.0f; + float opacity = 1.0f; + int opacityDir = 1; + + std::unique_ptr<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8, + QSize(1280, 720), + 1, + QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource)); + tex->create(); + std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ tex.get() })); + std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor()); + rt->setRenderPassDescriptor(rp.get()); + rt->create(); + + QMatrix4x4 viewProjection = rhi->clipSpaceCorrMatrix(); + viewProjection.perspective(45.0f, 1280 / 720.f, 0.01f, 1000.0f); + viewProjection.translate(0, 0, -4); + + static float vertexData[] = { // Y up, CCW + 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, + }; + + std::unique_ptr<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable, + QRhiBuffer::VertexBuffer, + sizeof(vertexData))); + vbuf->create(); + + std::unique_ptr<QRhiBuffer> ubuf(rhi->newBuffer(QRhiBuffer::Dynamic, + QRhiBuffer::UniformBuffer, + 64 + 4)); + ubuf->create(); + + std::unique_ptr<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings()); + srb->setBindings({ + QRhiShaderResourceBinding::uniformBuffer(0, + QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, + ubuf.get()) + }); + srb->create(); + + std::unique_ptr<QRhiGraphicsPipeline> ps(rhi->newGraphicsPipeline()); + QRhiGraphicsPipeline::TargetBlend premulAlphaBlend; + premulAlphaBlend.enable = true; + ps->setTargetBlends({ premulAlphaBlend }); + static auto getShader = [](const QString &name) { + QFile f(name); + return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader(); + }; + ps->setShaderStages({ + { QRhiShaderStage::Vertex, getShader(QLatin1String("color.vert.qsb")) }, + { QRhiShaderStage::Fragment, getShader(QLatin1String("color.frag.qsb")) } + }); + QRhiVertexInputLayout inputLayout; + inputLayout.setBindings({ + { 5 * sizeof(float) } + }); + inputLayout.setAttributes({ + { 0, 0, QRhiVertexInputAttribute::Float2, 0 }, + { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) } + }); + ps->setVertexInputLayout(inputLayout); + ps->setShaderResourceBindings(srb.get()); + ps->setRenderPassDescriptor(rp.get()); + ps->create(); + + QRhiCommandBuffer *cb; + for (int frame = 0; frame < 20; ++frame) { + rhi->beginOffscreenFrame(&cb); + + QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch(); + if (frame == 0) + u->uploadStaticBuffer(vbuf.get(), vertexData); + + QMatrix4x4 mvp = viewProjection; + mvp.rotate(rotation, 0, 1, 0); + u->updateDynamicBuffer(ubuf.get(), 0, 64, mvp.constData()); + rotation += 5.0f; + + u->updateDynamicBuffer(ubuf.get(), 64, 4, &opacity); + opacity += opacityDir * 0.2f; + if (opacity < 0.0f || opacity > 1.0f) { + opacityDir *= -1; + opacity = qBound(0.0f, opacity, 1.0f); + } + + cb->beginPass(rt.get(), Qt::green, { 1.0f, 0 }, u); + cb->setGraphicsPipeline(ps.get()); + cb->setViewport({ 0, 0, 1280, 720 }); + cb->setShaderResources(); + const QRhiCommandBuffer::VertexInput vbufBinding(vbuf.get(), 0); + cb->setVertexInput(0, 1, &vbufBinding); + cb->draw(3); + QRhiReadbackResult readbackResult; + u = rhi->nextResourceUpdateBatch(); + u->readBackTexture({ tex.get() }, &readbackResult); + cb->endPass(u); + + rhi->endOffscreenFrame(); + + QImage image(reinterpret_cast<const uchar *>(readbackResult.data.constData()), + readbackResult.pixelSize.width(), + readbackResult.pixelSize.height(), + QImage::Format_RGBA8888_Premultiplied); + if (rhi->isYUpInFramebuffer()) + image = image.mirrored(); + image.save(QString::asprintf("frame%d.png", frame)); + } + + return 0; +} +//! [0] diff --git a/src/gui/doc/snippets/separations/separations.qdoc b/src/gui/doc/snippets/separations/separations.qdoc index ad670f305a..ee567030bb 100644 --- a/src/gui/doc/snippets/separations/separations.qdoc +++ b/src/gui/doc/snippets/separations/separations.qdoc @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only /* \example painting/separations diff --git a/src/gui/doc/src/coordsys.qdoc b/src/gui/doc/src/coordsys.qdoc index eb39239e37..087916635b 100644 --- a/src/gui/doc/src/coordsys.qdoc +++ b/src/gui/doc/src/coordsys.qdoc @@ -213,11 +213,11 @@ \row \li {2,1} - \snippet analogclock/main.cpp 1 + \snippet ../widgets/widgets/analogclock/analogclock.cpp 9 We translate the coordinate system so that point (0, 0) is in the widget's center, instead of being at the top-left corner. We also - scale the system by \c side / 100, where \c side is either the + scale the system by \c side / 200, where \c side is either the widget's width or the height, whichever is shortest. We want the clock to be square, even if the device isn't. @@ -227,7 +227,7 @@ See also the \l {Window-Viewport Conversion} section. - \snippet analogclock/main.cpp 2 + \snippet ../widgets/widgets/analogclock/analogclock.cpp 18 We draw the clock's hour hand by rotating the coordinate system and calling QPainter::drawConvexPolygon(). Thank's to the @@ -235,26 +235,35 @@ The polygon is specified as an array of alternating \e x, \e y values, stored in the \c hourHand static variable (defined at the - beginning of the function), which corresponds to the four points - (2, 0), (0, 2), (-2, 0), and (0, -25). + beginning of the function), which corresponds to the three points + (7, 8), (-7, 8), (0, -40). The calls to QPainter::save() and QPainter::restore() surrounding the code guarantees that the code that follows won't be disturbed by the transformations we've used. - \snippet analogclock/main.cpp 3 + \snippet ../widgets/widgets/analogclock/analogclock.cpp 21 + + After that, we draw the hour markers for the clock face, which + consists of twelve short lines at 30-degree intervals. When that + loop is done, the painter has been rotated a full circle back to + its original state, so we don't need to save and restore the state. + + \snippet ../widgets/widgets/analogclock/analogclock.cpp 24 We do the same for the clock's minute hand, which is defined by - the four points (1, 0), (0, 1), (-1, 0), and (0, -40). These + the three points (7, 8), (-7, 8), (0, -70). These coordinates specify a hand that is thinner and longer than the minute hand. - \snippet analogclock/main.cpp 4 + \snippet ../widgets/widgets/analogclock/analogclock.cpp 27 - Finally, we draw the clock face, which consists of twelve short - lines at 30-degree intervals. At the end of that, the painter is - rotated in a way which isn't very useful, but we're done with - painting so that doesn't matter. + Finally, we draw the minute markers for the clock face, which + consists of sixty short lines at 6-degree intervals. We skip every + fifth minute marker because we don't want to draw over the hour + markers. At the end of that, the painter is rotated in a way which + isn't very useful, but we're done with painting so that doesn't + matter. \endtable For more information about the transformation matrix, see the @@ -422,5 +431,5 @@ \endtable \endomit - \sa {Analog Clock Window Example} + \sa {Analog Clock} */ diff --git a/src/gui/doc/src/dnd.qdoc b/src/gui/doc/src/dnd.qdoc index e8276f3465..7a756b304e 100644 --- a/src/gui/doc/src/dnd.qdoc +++ b/src/gui/doc/src/dnd.qdoc @@ -335,7 +335,9 @@ For example, we can copy the contents of a QLineEdit to the clipboard with the following code: - \snippet ../widgets/widgets/charactermap/mainwindow.cpp 11 + \code + QGuiApplication::clipboard()->setText(lineEdit->text(), QClipboard::Clipboard); + \endcode Data with different MIME types can also be put on the clipboard. Construct a QMimeData object and set data with setData() function in @@ -364,8 +366,6 @@ \li \l{draganddrop/draggableicons}{Draggable Icons} \li \l{draganddrop/draggabletext}{Draggable Text} \li \l{draganddrop/dropsite}{Drop Site} - \li \l{draganddrop/fridgemagnets}{Fridge Magnets} - \li \l{draganddrop/puzzle}{Drag and Drop Puzzle} \endlist \section1 Interoperating with Other Applications diff --git a/src/gui/doc/src/external-resources.qdoc b/src/gui/doc/src/external-resources.qdoc index cea63f59cc..16bca2475d 100644 --- a/src/gui/doc/src/external-resources.qdoc +++ b/src/gui/doc/src/external-resources.qdoc @@ -29,15 +29,24 @@ /*! \externalpage https://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html - \title Icon Theme Specification + \title Freedesktop Icon Theme Specification */ /*! + \externalpage https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html + \title Freedesktop Icon Naming Specification +*/ +/*! \externalpage https://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#directory_layout \title Icon Theme Specification - Directory Layout */ /*! + \externalpage https://freedesktop.org/ + \title Freedesktop +*/ + +/*! \externalpage https://www.khronos.org/vulkan/ \title Vulkan */ @@ -46,3 +55,13 @@ \externalpage https://www.lunarg.com/vulkan-sdk/ \title LunarG Vulkan SDK */ + +/*! + \externalpage https://developer.android.com/reference/androidx/core/content/FileProvider + \title Android: FileProvider +*/ + +/*! + \externalpage https://developer.android.com/training/secure-file-sharing/setup-sharing.html + \title Android: Setting up file sharing +*/ diff --git a/src/gui/doc/src/includes/qiconengine-virtualhookhelper.qdocinc b/src/gui/doc/src/includes/qiconengine-virtualhookhelper.qdocinc index b17d2bd66f..8b7e333df8 100644 --- a/src/gui/doc/src/includes/qiconengine-virtualhookhelper.qdocinc +++ b/src/gui/doc/src/includes/qiconengine-virtualhookhelper.qdocinc @@ -1,3 +1,3 @@ -\note This is a helper method and the actual work is done by the -virtual_hook() method, hence this method depends on icon engine support +\note If the icon engine does not reimplement this function, the actual work is +done by the virtual_hook() method, hence this method depends on icon engine support and may not work with all icon engines. diff --git a/src/gui/doc/src/qt6-changes.qdoc b/src/gui/doc/src/qt6-changes.qdoc index 109a7f1750..60e1bffba8 100644 --- a/src/gui/doc/src/qt6-changes.qdoc +++ b/src/gui/doc/src/qt6-changes.qdoc @@ -5,7 +5,7 @@ \page gui-changes-qt6.html \title Changes to Qt GUI \ingroup changes-qt-5-to-6 - \brief Migrate Qt GUI to Qt 6. + \brief Kernel, Text, Painting, and Utility classes are modified. Qt 6 is a result of the conscious effort to make the framework more efficient and easy to use. @@ -114,4 +114,38 @@ Metal, in addition to OpenGL. On Windows the default choice is Direct 3D, therefore the removal of ANGLE is alleviated by having support for graphics APIs other than OpenGL as well. + + \section2 Native clipboard integration + + Qt 5 provided interfaces for integrating platform specific or custom + clipboard formats into Qt through \c QMacPasteboardMime in \c QtMacExtras, + and \c QWindowsMime from the Windows QPA API. Since Qt 6.6, the + equivalent functionality is provided by the classes QUtiMimeConverter for + \macos, and the QWindowsMimeConverter for Windows. + + Porting from QWindowsMime to QWindowsMimeConverter requires practically no + changes, as the virtual interface is identical. However, in Qt 6 it is no + longer needed to register a QWindowsMimeConverter implementation; + instantiating the type implicitly registers the converter. + + Porting a QMacPasteboardMime to QUtiMimeConverter requires renaming some of + the virtual functions. Note that the \c{QMacPasteboardMime} API used the + outdated term \c{flavor} for the native clipboard format on \macos, whereas + the platform now uses \c{Uniform Type Identifiers}, i.e. \c{UTI}s, which Qt + has adapted for function and parameter names. + + The \c{mimeFor} and \c{flavorFor} functions are replaced by the + \l{QUtiMimeConverter::}{mimeForUti} and \l{QUtiMimeConverter::}{utiForMime} + implementations, respectively. Those should return the name of the mime + type or \c{UTI} that the converter can convert the input format to, so a + port usually just involves renaming existing overrides. The + \c{convertToMime}, \c{convertFromMime}, and \c{count} functions in + QUtiMimeConverter are identical to their QMacPasteboardMime versions. + + The \c{canConvert}, \c{converterName} functions are no longer needed, they + are implied by implementation of the above functions, so overrides of those + functions can be removed. + + As with the the QWindowsMimeConverter, registration is done by instantiating + the type. */ diff --git a/src/gui/doc/src/qtgui-overview.qdoc b/src/gui/doc/src/qtgui-overview.qdoc index ecd34f0e9e..446479c9be 100644 --- a/src/gui/doc/src/qtgui-overview.qdoc +++ b/src/gui/doc/src/qtgui-overview.qdoc @@ -51,6 +51,68 @@ that prefer more low-level APIs to text and font handling can use classes like QRawFont and QGlyphRun. + \section1 RHI Graphics + + The Qt Rendering Hardware Interface is an abstraction for hardware accelerated + graphics APIs, such as, \l{https://www.khronos.org/opengl/}{OpenGL}, + \l{https://www.khronos.org/opengles/}{OpenGL ES}, + \l{https://docs.microsoft.com/en-us/windows/desktop/direct3d}{Direct3D}, + \l{https://developer.apple.com/metal/}{Metal}, and + \l{https://www.khronos.org/vulkan/}{Vulkan}. + + As an alternative to using OpenGL or Vulkan directly to render to a + QWindow, \l QRhi and the related classes provide a portable, cross-platform + 3D graphics and compute API complemented by a shader conditioning and + transpiling pipeline. This way applications can avoid directly depending on + a single, and, in some cases, vendor or platform-specific 3D API. + + Below is a list of the main RHI-related classes. These are complemented by + a number of additional classes and structs. + + \list + \li QRhi + \li QShader + \li QShaderDescription + \li QRhiCommandBuffer + \li QRhiResourceUpdateBatch + \li QRhiBuffer + \li QRhiRenderBuffer + \li QRhiTexture + \li QRhiSampler + \li QRhiTextureRenderTarget + \li QRhiShaderResourceBindings + \li QRhiGraphicsPipeline + \li QRhiComputePipeline + \li QRhiSwapChain + \endlist + + See the \l{RHI Window Example} for an introductory example of creating a + portable, cross-platform application that performs accelerated 3D rendering + onto a QWindow using QRhi. + + Working directly with QWindow is the most advanced and often the most + flexible way of rendering with the QRhi API. It is the most low-level + approach, however, and limited in the sense that Qt's UI technologies, + widgets and Qt Quick, are not utilized at all. In many cases applications + will rather want to integrate QRhi-based rendering into a widget or Qt + Quick-based user interface. QWidget-based applications may choose to embed + the window as a native child into the widget hierarchy via + QWidget::createWindowContainer(), but in many cases \l QRhiWidget will + offer a more convenient enabler to integrate QRhi-based rendering into a + widget UI. Qt Quick provides its own set of enablers for extending the + 2D/3D scene with QRhi-based custom rendering. + + \note The RHI family of APIs are currently offered with a limited + compatibility guarantee, as opposed to regular Qt public APIs. See \l QRhi + for details. + + \section1 3D Matrix and Vector Math + + The Qt GUI module also contains a few math classes to aid with the most + common mathematical operations related to 3D graphics. These classes + include \l {QMatrix4x4}, \l {QVector2D}, \l {QVector3D}, \l {QVector4D}, + and \l {QQuaternion}. + \section1 OpenGL and OpenGL ES Integration QWindow supports rendering using OpenGL and OpenGL ES, depending on what the @@ -86,10 +148,6 @@ For more information, see the \l {OpenGL Window Example}. - The Qt GUI module also contains a few math classes to aid with the most - common mathematical operations related to 3D graphics. These classes include - \l {QMatrix4x4}, \l {QVector4D}, and \l {QQuaternion}. - A \l {QWindow} created with the \l {QSurface::OpenGLSurface} can be used in combination with \l QPainter and \l QOpenGLPaintDevice to have OpenGL hardware-accelerated 2D graphics by sacrificing some of the visual quality. @@ -104,20 +162,23 @@ On Android, Vulkan headers were added in API level 24 of the NDK. - Relevant classes: + The main relevant classes for low-level Vulkan support are: \list - \li QVulkanDeviceFunctions - \li QVulkanExtension - \li QVulkanFunctions - \li QVulkanInfoVector \li QVulkanInstance - \li QVulkanWindow - \li QVulkanWindowRenderer + \li QVulkanFunctions + \li QVulkanDeviceFunctions \endlist + In addition, \l QVulkanWindow provides a convenience subclass of QWindow + that makes it easier to get started with implementing Vulkan-based + rendering targeting a QWindow. Using this helper class is completely + optional; applications with more advanced Vulkan-based renderers may + instead want to use a QWindow with the \l {QSurface::VulkanSurface} type + directly. + For more information, see the \l{Hello Vulkan Widget Example} - and the \l {Hello Vulkan Window Example}. + and the \l {Hello Vulkan Triangle Example}. \section1 Drag and Drop diff --git a/src/gui/doc/src/qtgui.qdoc b/src/gui/doc/src/qtgui.qdoc index d39fa72221..2a1d69d4d3 100644 --- a/src/gui/doc/src/qtgui.qdoc +++ b/src/gui/doc/src/qtgui.qdoc @@ -15,6 +15,23 @@ */ /*! + \module QtGuiPrivate + \title Qt GUI Private C++ Classes + \qtcmakepackage Gui + \qtvariable gui-private + + \brief Provides access to private GUI functionality. + + Use the following CMake commands in your \c {CMakeLists.txt} to access + private Qt GUI APIs: + + \badcode + find_package(Qt6 REQUIRED COMPONENTS Gui) + target_link_libraries(mytarget PRIVATE Qt6::GuiPrivate) + \endcode +*/ + +/*! \page qtgui-index.html \title Qt GUI @@ -54,6 +71,8 @@ \list \li \l {Application Windows} {Qt GUI Application Windows} \li \l {2D Graphics} {Qt GUI 2D Graphics} + \li \l {RHI Graphics} {Qt GUI Accelerated 2D and 3D Graphics using the Qt RHI} + \li \l {3D Matrix and Vector Math} {Qt GUI Matrix and Vector Math} \li \l {OpenGL and OpenGL ES Integration} {Qt GUI OpenGL and OpenGL ES Integration} \li \l {Vulkan Integration} {Qt GUI Vulkan Integration} diff --git a/src/gui/doc/src/richtext.qdoc b/src/gui/doc/src/richtext.qdoc index 5ae7739481..10d9962850 100644 --- a/src/gui/doc/src/richtext.qdoc +++ b/src/gui/doc/src/richtext.qdoc @@ -11,10 +11,9 @@ \page richtext.html \title Rich Text Processing \brief An overview of Qt's rich text processing, editing and display features. - + \ingroup explanations-ui \ingroup frameworks-technologies \ingroup qt-basic-concepts - \ingroup best-practices \nextpage Rich Text Document Structure @@ -839,7 +838,11 @@ \section1 Supported Tags The following table lists the HTML tags supported by Qt's - \l{Rich Text Processing}{rich text} engine: + \l{Rich Text Processing}{rich text} engine. + + \note The functionality implemented for tags listed below is a subset of + the full HTML 4 specification. Not all attributes are supported, + see comments for each tag. \table 70% \header \li Tag |