6.5.3 clean

This commit is contained in:
kleuter
2023-11-01 18:02:52 +01:00
parent bbe896803b
commit 7018d9e6c8
2170 changed files with 57471 additions and 43550 deletions

View File

@ -0,0 +1,46 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(permissions LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/corelib/permissions")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(permissions
MANUAL_FINALIZATION
main.cpp
)
set_target_properties(permissions PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist"
MACOSX_BUNDLE_GUI_IDENTIFIER "io.qt.examples.permissions"
QT_ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android"
)
target_link_libraries(permissions PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
install(TARGETS permissions
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)
if(APPLE AND NOT CMAKE_GENERATOR STREQUAL "Xcode")
add_custom_command(TARGET permissions
POST_BUILD COMMAND codesign -s - permissions.app)
endif()
qt_finalize_executable(permissions)

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>LSMinimumSystemVersion</key>
<string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Testing BluetoothAlways</string>
<key>NSCalendarsUsageDescription</key>
<string>Testing Calendars</string>
<key>NSCameraUsageDescription</key>
<string>Testing Camera</string>
<key>NSContactsUsageDescription</key>
<string>Testing Contacts</string>
<key>NSHealthShareUsageDescription</key>
<string>Testing HealthShare</string>
<key>NSHealthUpdateUsageDescription</key>
<string>Testing HealthUpdate</string>
<key>NSLocationUsageDescription</key>
<string>Testing Location on macOS</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Testing Location when in use on iOS</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Testing Location always and when in use on iOS</string>
<key>NSMicrophoneUsageDescription</key>
<string>Testing Microphone</string>
</dict>
</plist>

View File

@ -0,0 +1,53 @@
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.qtproject.example"
android:installLocation="auto"
android:versionCode="-- %%INSERT_VERSION_CODE%% --"
android:versionName="-- %%INSERT_VERSION_NAME%% --">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<!-- %%INSERT_PERMISSIONS -->
<!-- %%INSERT_FEATURES -->
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true" />
<application
android:name="org.qtproject.qt.android.bindings.QtApplication"
android:hardwareAccelerated="true"
android:label="-- %%INSERT_APP_NAME%% --"
android:requestLegacyExternalStorage="true"
android:allowNativeHeapPointerTagging="false"
android:allowBackup="true"
android:fullBackupOnly="false">
<activity
android:name="org.qtproject.qt.android.bindings.QtActivity"
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
android:label="-- %%INSERT_APP_NAME%% --"
android:launchMode="singleTop"
android:screenOrientation="unspecified"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="-- %%INSERT_APP_LIB_NAME%% --" />
<meta-data
android:name="android.app.extract_android_style"
android:value="minimal" />
</activity>
</application>
</manifest>

View File

@ -0,0 +1,87 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtCore/qmetaobject.h>
#include <QtWidgets/qapplication.h>
#include <QtWidgets/qwidget.h>
#include <QtWidgets/qpushbutton.h>
#include <QtWidgets/qlayout.h>
#include <QtWidgets/qmessagebox.h>
#if !QT_CONFIG(permissions)
#error "This example requires the permissions feature, which is not enabled on this platform"
#endif
#include <QtCore/qpermissions.h>
class PermissionWidget : public QWidget
{
Q_OBJECT
public:
explicit PermissionWidget(QWidget *parent = nullptr) : QWidget(parent)
{
QVBoxLayout *layout = new QVBoxLayout(this);
static const QPermission permissions[] = {
QCameraPermission{},
QMicrophonePermission{},
QBluetoothPermission{},
QContactsPermission{},
QCalendarPermission{},
QLocationPermission{}
};
for (auto permission : permissions) {
auto permissionName = QString::fromLatin1(permission.type().name());
QPushButton *button = new QPushButton(permissionName.sliced(1, permissionName.length() - 11));
connect(button, &QPushButton::clicked, this, &PermissionWidget::buttonClicked);
button->setProperty("permission", QVariant::fromValue(permission));
layout->addWidget(button);
}
QPalette pal = palette();
pal.setBrush(QPalette::Window, QGradient(QGradient::HappyAcid));
setPalette(pal);
}
private:
void buttonClicked()
{
auto *button = static_cast<QPushButton*>(sender());
auto permission = button->property("permission").value<QPermission>();
Q_ASSERT(permission.type().isValid());
switch (qApp->checkPermission(permission)) {
case Qt::PermissionStatus::Undetermined:
qApp->requestPermission(permission, this,
[button](const QPermission &permission) {
Q_UNUSED(permission);
emit button->clicked(); // Try again
}
);
return;
case Qt::PermissionStatus::Denied:
QMessageBox::warning(this, button->text(),
tr("Permission is needed to use %1. Please grant permission "\
"to this application in the system settings.").arg(button->text()));
return;
case Qt::PermissionStatus::Granted:
break; // Proceed
}
// All good, can use the feature
QMessageBox::information(this, button->text(),
tr("Accessing %1").arg(button->text()));
}
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);
PermissionWidget widget;
widget.show();
return app.exec();
}
#include "main.moc"

View File

@ -0,0 +1,53 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(qopenglwidget LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/opengl/qopenglwidget")
find_package(Qt6 REQUIRED COMPONENTS Core Gui OpenGL OpenGLWidgets Widgets)
qt_standard_project_setup()
qt_add_executable(qopenglwidget
bubble.cpp bubble.h
glwidget.cpp glwidget.h
main.cpp
mainwindow.cpp mainwindow.h
)
set_target_properties(qopenglwidget PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(qopenglwidget PRIVATE
Qt6::Core
Qt6::Gui
Qt6::OpenGL
Qt6::OpenGLWidgets
Qt6::Widgets
)
# Resources:
set(texture_resource_files
"qt.png"
)
qt6_add_resources(qopenglwidget "texture"
PREFIX
"/"
FILES
${texture_resource_files}
)
install(TARGETS qopenglwidget
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,99 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include "bubble.h"
Bubble::Bubble(const QPointF &position, qreal radius, const QPointF &velocity)
: position(position), vel(velocity), radius(radius)
{
innerColor = randomColor();
outerColor = randomColor();
updateBrush();
}
//! [0]
void Bubble::updateCache()
{
delete cache;
cache = new QImage(qRound(radius * 2 + 2), qRound(radius * 2 + 2), QImage::Format_ARGB32_Premultiplied);
cache->fill(0x00000000);
QPainter p(cache);
p.setRenderHint(QPainter::Antialiasing);
QPen pen(Qt::white);
pen.setWidth(2);
p.setPen(pen);
p.setBrush(brush);
p.drawEllipse(1, 1, int(2*radius), int(2*radius));
}
//! [0]
Bubble::~Bubble()
{
delete cache;
}
void Bubble::updateBrush()
{
QRadialGradient gradient(QPointF(radius, radius), radius,
QPointF(radius*0.5, radius*0.5));
gradient.setColorAt(0, QColor(255, 255, 255, 255));
gradient.setColorAt(0.25, innerColor);
gradient.setColorAt(1, outerColor);
brush = QBrush(gradient);
updateCache();
}
//! [1]
void Bubble::drawBubble(QPainter *painter)
{
painter->save();
painter->translate(position.x() - radius, position.y() - radius);
painter->setOpacity(0.8);
painter->drawImage(0, 0, *cache);
painter->restore();
}
//! [1]
QColor Bubble::randomColor()
{
int red = int(185 + QRandomGenerator::global()->bounded(70));
int green = int(185 + QRandomGenerator::global()->bounded(70));
int blue = int(205 + QRandomGenerator::global()->bounded(50));
int alpha = int(91 + QRandomGenerator::global()->bounded(100));
return QColor(red, green, blue, alpha);
}
void Bubble::move(const QRect &bbox)
{
position += vel;
qreal leftOverflow = position.x() - radius - bbox.left();
qreal rightOverflow = position.x() + radius - bbox.right();
qreal topOverflow = position.y() - radius - bbox.top();
qreal bottomOverflow = position.y() + radius - bbox.bottom();
if (leftOverflow < 0.0) {
position.setX(position.x() - 2 * leftOverflow);
vel.setX(-vel.x());
} else if (rightOverflow > 0.0) {
position.setX(position.x() - 2 * rightOverflow);
vel.setX(-vel.x());
}
if (topOverflow < 0.0) {
position.setY(position.y() - 2 * topOverflow);
vel.setY(-vel.y());
} else if (bottomOverflow > 0.0) {
position.setY(position.y() - 2 * bottomOverflow);
vel.setY(-vel.y());
}
}
QRectF Bubble::rect()
{
return QRectF(position.x() - radius, position.y() - radius,
2 * radius, 2 * radius);
}

View File

@ -0,0 +1,39 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef BUBBLE_H
#define BUBBLE_H
#include <QBrush>
#include <QColor>
#include <QPointF>
#include <QRect>
#include <QRectF>
QT_FORWARD_DECLARE_CLASS(QPainter)
class Bubble
{
public:
Bubble(const QPointF &position, qreal radius, const QPointF &velocity);
~Bubble();
void drawBubble(QPainter *painter);
void updateBrush();
void move(const QRect &bbox);
void updateCache();
QRectF rect();
private:
QColor randomColor();
QBrush brush;
QPointF position;
QPointF vel;
qreal radius;
QColor innerColor;
QColor outerColor;
QImage *cache = nullptr;
};
#endif

View File

@ -0,0 +1,540 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "glwidget.h"
#include <QPainter>
#include <QPaintEngine>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QRandomGenerator>
#include <QCoreApplication>
#include <qmath.h>
#include "mainwindow.h"
#include "bubble.h"
const int bubbleNum = 8;
#ifndef GL_SRGB8_ALPHA8
#define GL_SRGB8_ALPHA8 0x8C43
#endif
GLWidget::GLWidget(MainWindow *maybeMainWindow, const QColor &background)
: m_mainWindow(maybeMainWindow),
m_background(background)
{
setMinimumSize(300, 250);
if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
setTextureFormat(GL_SRGB8_ALPHA8);
}
GLWidget::~GLWidget()
{
reset();
}
void GLWidget::reset()
{
qDeleteAll(m_bubbles);
// Leave everything in a state suitable for a subsequent call to
// initialize(). This matters when coming from the context's
// aboutToBeDestroyed signal, would not matter when invoked from the
// destructor.
m_bubbles.clear();
// And now release all OpenGL resources.
makeCurrent();
delete m_texture;
m_texture = nullptr;
delete m_program1;
m_program1 = nullptr;
delete m_program2;
m_program2 = nullptr;
delete m_vshader1;
m_vshader1 = nullptr;
delete m_fshader1;
m_fshader1 = nullptr;
delete m_vshader2;
m_vshader2 = nullptr;
delete m_fshader2;
m_fshader2 = nullptr;
m_vbo1.destroy();
m_vbo2.destroy();
doneCurrent();
// We are done with the current QOpenGLContext, forget it. If there is a
// subsequent initialize(), that will then connect to the new context.
QObject::disconnect(m_contextWatchConnection);
}
void GLWidget::setScaling(int scale)
{
if (scale > 30)
m_fScale = 1 + qreal(scale - 30) / 30 * 0.25;
else if (scale < 30)
m_fScale = 1 - (qreal(30 - scale) / 30 * 0.25);
else
m_fScale = 1;
}
void GLWidget::setLogo()
{
m_qtLogo = true;
}
void GLWidget::setTexture()
{
m_qtLogo = false;
}
void GLWidget::setShowBubbles(bool bubbles)
{
m_showBubbles = bubbles;
}
void GLWidget::paintQtLogo()
{
m_program1->enableAttributeArray(m_vertexAttr1);
m_program1->enableAttributeArray(m_normalAttr1);
m_vbo1.bind();
// The data in the buffer is placed like this:
// vertex1.x, vertex1.y, vertex1.z, normal1.x, normal1.y, normal1.z, vertex2.x, ...
m_program1->setAttributeBuffer(m_vertexAttr1, GL_FLOAT, 0, 3, 6 * sizeof(GLfloat));
m_program1->setAttributeBuffer(m_normalAttr1, GL_FLOAT, 3 * sizeof(GLfloat), 3, 6 * sizeof(GLfloat));
m_vbo1.release();
glDrawArrays(GL_TRIANGLES, 0, m_vertices.size());
m_program1->disableAttributeArray(m_normalAttr1);
m_program1->disableAttributeArray(m_vertexAttr1);
}
void GLWidget::paintTexturedCube()
{
m_texture->bind();
if (!m_vbo2.isCreated()) {
static GLfloat afVertices[] = {
-0.5, 0.5, 0.5, 0.5,-0.5,0.5,-0.5,-0.5,0.5,
0.5, -0.5, 0.5, -0.5,0.5,0.5,0.5,0.5,0.5,
-0.5, -0.5, -0.5, 0.5,-0.5,-0.5,-0.5,0.5,-0.5,
0.5, 0.5, -0.5, -0.5,0.5,-0.5,0.5,-0.5,-0.5,
0.5, -0.5, -0.5, 0.5,-0.5,0.5,0.5,0.5,-0.5,
0.5, 0.5, 0.5, 0.5,0.5,-0.5,0.5,-0.5,0.5,
-0.5, 0.5, -0.5, -0.5,-0.5,0.5,-0.5,-0.5,-0.5,
-0.5, -0.5, 0.5, -0.5,0.5,-0.5,-0.5,0.5,0.5,
0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5,
-0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, 0.5,
-0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5,
0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5
};
static GLfloat afTexCoord[] = {
0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f,
1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f,
0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f,
1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f,
0.0f,0.0f, 0.0f,1.0f, 1.0f,0.0f,
0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
1.0f,1.0f, 0.0f,0.0f, 0.0f,1.0f,
0.0f,1.0f, 1.0f,0.0f, 1.0f,1.0f,
1.0f,0.0f, 0.0f,1.0f, 0.0f,0.0f,
1.0f,0.0f, 1.0f,1.0f, 0.0f,0.0f,
0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f
};
GLfloat afNormals[] = {
0,0,-1, 0,0,-1, 0,0,-1,
0,0,-1, 0,0,-1, 0,0,-1,
0,0,1, 0,0,1, 0,0,1,
0,0,1, 0,0,1, 0,0,1,
-1,0,0, -1,0,0, -1,0,0,
-1,0,0, -1,0,0, -1,0,0,
1,0,0, 1,0,0, 1,0,0,
1,0,0, 1,0,0, 1,0,0,
0,-1,0, 0,-1,0, 0,-1,0,
0,-1,0, 0,-1,0, 0,-1,0,
0,1,0, 0,1,0, 0,1,0,
0,1,0, 0,1,0, 0,1,0
};
m_vbo2.create();
m_vbo2.bind();
m_vbo2.allocate(36 * 8 * sizeof(GLfloat));
m_vbo2.write(0, afVertices, sizeof(afVertices));
m_vbo2.write(sizeof(afVertices), afTexCoord, sizeof(afTexCoord));
m_vbo2.write(sizeof(afVertices) + sizeof(afTexCoord), afNormals, sizeof(afNormals));
m_vbo2.release();
}
m_program2->setUniformValue(m_textureUniform2, 0); // use texture unit 0
m_program2->enableAttributeArray(m_vertexAttr2);
m_program2->enableAttributeArray(m_normalAttr2);
m_program2->enableAttributeArray(m_texCoordAttr2);
m_vbo2.bind();
// In the buffer we first have 36 vertices (3 floats for each), then 36 texture
// coordinates (2 floats for each), then 36 normals (3 floats for each).
m_program2->setAttributeBuffer(m_vertexAttr2, GL_FLOAT, 0, 3);
m_program2->setAttributeBuffer(m_texCoordAttr2, GL_FLOAT, 36 * 3 * sizeof(GLfloat), 2);
m_program2->setAttributeBuffer(m_normalAttr2, GL_FLOAT, 36 * 5 * sizeof(GLfloat), 3);
m_vbo2.release();
glDrawArrays(GL_TRIANGLES, 0, 36);
m_program2->disableAttributeArray(m_vertexAttr2);
m_program2->disableAttributeArray(m_normalAttr2);
m_program2->disableAttributeArray(m_texCoordAttr2);
}
void GLWidget::initializeGL()
{
initializeOpenGLFunctions();
m_texture = new QOpenGLTexture(QImage(":/qt.png"));
m_vshader1 = new QOpenGLShader(QOpenGLShader::Vertex);
const char *vsrc1 =
"attribute highp vec4 vertex;\n"
"attribute mediump vec3 normal;\n"
"uniform mediump mat4 matrix;\n"
"varying mediump vec4 color;\n"
"void main(void)\n"
"{\n"
" vec3 toLight = normalize(vec3(0.0, 0.3, 1.0));\n"
" float angle = max(dot(normal, toLight), 0.0);\n"
" vec3 col = vec3(0.40, 1.0, 0.0);\n"
" color = vec4(col * 0.2 + col * 0.8 * angle, 1.0);\n"
" color = clamp(color, 0.0, 1.0);\n"
" gl_Position = matrix * vertex;\n"
"}\n";
m_vshader1->compileSourceCode(vsrc1);
m_fshader1 = new QOpenGLShader(QOpenGLShader::Fragment);
const char *fsrc1 =
"varying mediump vec4 color;\n"
"void main(void)\n"
"{\n"
" gl_FragColor = color;\n"
"}\n";
m_fshader1->compileSourceCode(fsrc1);
m_program1 = new QOpenGLShaderProgram;
m_program1->addShader(m_vshader1);
m_program1->addShader(m_fshader1);
m_program1->link();
m_vertexAttr1 = m_program1->attributeLocation("vertex");
m_normalAttr1 = m_program1->attributeLocation("normal");
m_matrixUniform1 = m_program1->uniformLocation("matrix");
m_vshader2 = new QOpenGLShader(QOpenGLShader::Vertex);
const char *vsrc2 =
"attribute highp vec4 vertex;\n"
"attribute highp vec4 texCoord;\n"
"attribute mediump vec3 normal;\n"
"uniform mediump mat4 matrix;\n"
"varying highp vec4 texc;\n"
"varying mediump float angle;\n"
"void main(void)\n"
"{\n"
" vec3 toLight = normalize(vec3(0.0, 0.3, 1.0));\n"
" angle = max(dot(normal, toLight), 0.0);\n"
" gl_Position = matrix * vertex;\n"
" texc = texCoord;\n"
"}\n";
m_vshader2->compileSourceCode(vsrc2);
m_fshader2 = new QOpenGLShader(QOpenGLShader::Fragment);
const char *fsrc2 =
"varying highp vec4 texc;\n"
"uniform sampler2D tex;\n"
"varying mediump float angle;\n"
"void main(void)\n"
"{\n"
" highp vec3 color = texture2D(tex, texc.st).rgb;\n"
" color = color * 0.2 + color * 0.8 * angle;\n"
" gl_FragColor = vec4(clamp(color, 0.0, 1.0), 1.0);\n"
"}\n";
m_fshader2->compileSourceCode(fsrc2);
m_program2 = new QOpenGLShaderProgram;
m_program2->addShader(m_vshader2);
m_program2->addShader(m_fshader2);
m_program2->link();
m_vertexAttr2 = m_program2->attributeLocation("vertex");
m_normalAttr2 = m_program2->attributeLocation("normal");
m_texCoordAttr2 = m_program2->attributeLocation("texCoord");
m_matrixUniform2 = m_program2->uniformLocation("matrix");
m_textureUniform2 = m_program2->uniformLocation("tex");
m_fAngle = 0;
m_fScale = 1;
createGeometry();
// Use a vertex buffer object. Client-side pointers are old-school and should be avoided.
m_vbo1.create();
m_vbo1.bind();
// For the cube all the data belonging to the texture coordinates and
// normals is placed separately, after the vertices. Here, for the Qt logo,
// let's do something different and potentially more efficient: create a
// properly interleaved data set.
const int vertexCount = m_vertices.count();
QList<GLfloat> buf;
buf.resize(vertexCount * 3 * 2);
GLfloat *p = buf.data();
for (int i = 0; i < vertexCount; ++i) {
*p++ = m_vertices[i].x();
*p++ = m_vertices[i].y();
*p++ = m_vertices[i].z();
*p++ = m_normals[i].x();
*p++ = m_normals[i].y();
*p++ = m_normals[i].z();
}
m_vbo1.allocate(buf.constData(), buf.count() * sizeof(GLfloat));
m_vbo1.release();
createBubbles(bubbleNum - m_bubbles.count());
// A well-behaved QOpenGLWidget releases OpenGL resources not only upon
// destruction, but also when the associated OpenGL context disappears. If
// the widget continues to exist, the context's destruction will be
// followed by a call to initialize(). This is not strictly mandatory in
// widgets that never change their parents.
m_contextWatchConnection = QObject::connect(context(), &QOpenGLContext::aboutToBeDestroyed, context(), [this] { reset(); });
}
void GLWidget::paintGL()
{
createBubbles(bubbleNum - m_bubbles.count());
QPainter painter;
painter.begin(this);
painter.beginNativePainting();
glClearColor(m_background.redF(), m_background.greenF(), m_background.blueF(), m_transparent ? 0.0f : 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glFrontFace(GL_CW);
glCullFace(GL_FRONT);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
QMatrix4x4 modelview;
modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f);
modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f);
modelview.rotate(m_fAngle, 0.0f, 0.0f, 1.0f);
modelview.scale(m_fScale);
modelview.translate(0.0f, -0.2f, 0.0f);
if (m_qtLogo) {
m_program1->bind();
m_program1->setUniformValue(m_matrixUniform1, modelview);
paintQtLogo();
m_program1->release();
} else {
m_program2->bind();
m_program2->setUniformValue(m_matrixUniform2, modelview);
paintTexturedCube();
m_program2->release();
}
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
painter.endNativePainting();
if (m_showBubbles) {
for (Bubble *bubble : std::as_const(m_bubbles))
bubble->drawBubble(&painter);
}
if (const int elapsed = m_time.elapsed()) {
QString framesPerSecond;
framesPerSecond.setNum(m_frames /(elapsed / 1000.0), 'f', 2);
painter.setPen(m_transparent ? Qt::black : Qt::white);
painter.drawText(20, 40, framesPerSecond + " paintGL calls / s");
}
painter.end();
for (Bubble *bubble : std::as_const(m_bubbles))
bubble->move(rect());
if (!(m_frames % 100)) {
m_time.start();
m_frames = 0;
}
m_fAngle += 1.0f;
++m_frames;
// When requested, follow the ideal way to animate: Rely on
// blocking swap and just schedule updates continuously.
if (!m_mainWindow || !m_mainWindow->timerEnabled())
update();
}
void GLWidget::createBubbles(int number)
{
for (int i = 0; i < number; ++i) {
QPointF position(width()*(0.1 + QRandomGenerator::global()->bounded(0.8)),
height()*(0.1 + QRandomGenerator::global()->bounded(0.8)));
qreal radius = qMin(width(), height())*(0.0175 + QRandomGenerator::global()->bounded(0.0875));
QPointF velocity(width()*0.0175*(-0.5 + QRandomGenerator::global()->bounded(1.0)),
height()*0.0175*(-0.5 + QRandomGenerator::global()->bounded(1.0)));
m_bubbles.append(new Bubble(position, radius, velocity));
}
}
void GLWidget::createGeometry()
{
m_vertices.clear();
m_normals.clear();
qreal x1 = +0.06f;
qreal y1 = -0.14f;
qreal x2 = +0.14f;
qreal y2 = -0.06f;
qreal x3 = +0.08f;
qreal y3 = +0.00f;
qreal x4 = +0.30f;
qreal y4 = +0.22f;
quad(x1, y1, x2, y2, y2, x2, y1, x1);
quad(x3, y3, x4, y4, y4, x4, y3, x3);
extrude(x1, y1, x2, y2);
extrude(x2, y2, y2, x2);
extrude(y2, x2, y1, x1);
extrude(y1, x1, x1, y1);
extrude(x3, y3, x4, y4);
extrude(x4, y4, y4, x4);
extrude(y4, x4, y3, x3);
const int NumSectors = 100;
const qreal sectorAngle = 2 * qreal(M_PI) / NumSectors;
for (int i = 0; i < NumSectors; ++i) {
qreal angle = i * sectorAngle;
qreal x5 = 0.30 * sin(angle);
qreal y5 = 0.30 * cos(angle);
qreal x6 = 0.20 * sin(angle);
qreal y6 = 0.20 * cos(angle);
angle += sectorAngle;
qreal x7 = 0.20 * sin(angle);
qreal y7 = 0.20 * cos(angle);
qreal x8 = 0.30 * sin(angle);
qreal y8 = 0.30 * cos(angle);
quad(x5, y5, x6, y6, x7, y7, x8, y8);
extrude(x6, y6, x7, y7);
extrude(x8, y8, x5, y5);
}
for (int i = 0;i < m_vertices.size();i++)
m_vertices[i] *= 2.0f;
}
void GLWidget::quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4)
{
m_vertices << QVector3D(x1, y1, -0.05f);
m_vertices << QVector3D(x2, y2, -0.05f);
m_vertices << QVector3D(x4, y4, -0.05f);
m_vertices << QVector3D(x3, y3, -0.05f);
m_vertices << QVector3D(x4, y4, -0.05f);
m_vertices << QVector3D(x2, y2, -0.05f);
QVector3D n = QVector3D::normal
(QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(x4 - x1, y4 - y1, 0.0f));
m_normals << n;
m_normals << n;
m_normals << n;
m_normals << n;
m_normals << n;
m_normals << n;
m_vertices << QVector3D(x4, y4, 0.05f);
m_vertices << QVector3D(x2, y2, 0.05f);
m_vertices << QVector3D(x1, y1, 0.05f);
m_vertices << QVector3D(x2, y2, 0.05f);
m_vertices << QVector3D(x4, y4, 0.05f);
m_vertices << QVector3D(x3, y3, 0.05f);
n = QVector3D::normal
(QVector3D(x2 - x4, y2 - y4, 0.0f), QVector3D(x1 - x4, y1 - y4, 0.0f));
m_normals << n;
m_normals << n;
m_normals << n;
m_normals << n;
m_normals << n;
m_normals << n;
}
void GLWidget::extrude(qreal x1, qreal y1, qreal x2, qreal y2)
{
m_vertices << QVector3D(x1, y1, +0.05f);
m_vertices << QVector3D(x2, y2, +0.05f);
m_vertices << QVector3D(x1, y1, -0.05f);
m_vertices << QVector3D(x2, y2, -0.05f);
m_vertices << QVector3D(x1, y1, -0.05f);
m_vertices << QVector3D(x2, y2, +0.05f);
QVector3D n = QVector3D::normal
(QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(0.0f, 0.0f, -0.1f));
m_normals << n;
m_normals << n;
m_normals << n;
m_normals << n;
m_normals << n;
m_normals << n;
}
void GLWidget::setTransparent(bool transparent)
{
setAttribute(Qt::WA_AlwaysStackOnTop, transparent);
m_transparent = transparent;
// Call update() on the top-level window after toggling AlwayStackOnTop to make sure
// the entire backingstore is updated accordingly.
window()->update();
}
void GLWidget::resizeGL(int, int)
{
if (m_mainWindow) {
if (!m_btn) {
m_btn = new QPushButton("\nAdd widget\n", this);
connect(m_btn, &QPushButton::clicked, this, [this] { m_mainWindow->addNew(); });
}
m_btn->move(20, 80);
if (!m_btn2) {
m_btn2 = new QPushButton("\nI prefer tabbed widgets\n", this);
connect(m_btn2, &QPushButton::clicked, this, [this] { m_mainWindow->showNewWindow(); });
}
m_btn2->move(20, 160);
}
}

View File

@ -0,0 +1,85 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QVector3D>
#include <QMatrix4x4>
#include <QElapsedTimer>
#include <QList>
#include <QPushButton>
class Bubble;
class MainWindow;
QT_FORWARD_DECLARE_CLASS(QOpenGLTexture)
QT_FORWARD_DECLARE_CLASS(QOpenGLShader)
QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram)
class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
GLWidget(MainWindow *maybeMainWindow, const QColor &background);
~GLWidget();
public slots:
void setScaling(int scale);
void setLogo();
void setTexture();
void setShowBubbles(bool);
void setTransparent(bool transparent);
protected:
void resizeGL(int w, int h) override;
void paintGL() override;
void initializeGL() override;
private:
void paintTexturedCube();
void paintQtLogo();
void createGeometry();
void createBubbles(int number);
void quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4);
void extrude(qreal x1, qreal y1, qreal x2, qreal y2);
void reset();
MainWindow *m_mainWindow;
qreal m_fAngle = 0;
qreal m_fScale = 1;
bool m_showBubbles = true;
QList<QVector3D> m_vertices;
QList<QVector3D> m_normals;
bool m_qtLogo = true;
QList<Bubble *> m_bubbles;
int m_frames = 0;
QElapsedTimer m_time;
QOpenGLShader *m_vshader1 = nullptr;
QOpenGLShader *m_fshader1 = nullptr;
QOpenGLShader *m_vshader2 = nullptr;
QOpenGLShader *m_fshader2 = nullptr;
QOpenGLShaderProgram *m_program1 = nullptr;
QOpenGLShaderProgram *m_program2 = nullptr;
QOpenGLTexture *m_texture = nullptr;
QOpenGLBuffer m_vbo1;
QOpenGLBuffer m_vbo2;
int m_vertexAttr1 = 0;
int m_normalAttr1 = 0;
int m_matrixUniform1 = 0;
int m_vertexAttr2 = 0;
int m_normalAttr2 = 0;
int m_texCoordAttr2 = 0;
int m_matrixUniform2 = 0;
int m_textureUniform2 = 0;
bool m_transparent = false;
QPushButton *m_btn = nullptr;
QPushButton *m_btn2 = nullptr;
QColor m_background;
QMetaObject::Connection m_contextWatchConnection;
};
#endif

View File

@ -0,0 +1,42 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QMainWindow>
#include <QColorSpace>
#include <QSurfaceFormat>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include "mainwindow.h"
int main( int argc, char ** argv )
{
QApplication a( argc, argv );
QCoreApplication::setApplicationName("Qt QOpenGLWidget Example");
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCommandLineParser parser;
parser.setApplicationDescription(QCoreApplication::applicationName());
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption multipleSampleOption("multisample", "Multisampling");
parser.addOption(multipleSampleOption);
QCommandLineOption srgbOption("srgb", "Use sRGB Color Space");
parser.addOption(srgbOption);
parser.process(a);
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
if (parser.isSet(srgbOption))
format.setColorSpace(QColorSpace::SRgb);
if (parser.isSet(multipleSampleOption))
format.setSamples(4);
QSurfaceFormat::setDefaultFormat(format);
MainWindow mw;
mw.resize(1280, 720);
mw.show();
return a.exec();
}

View File

@ -0,0 +1,188 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QApplication>
#include <QMenuBar>
#include <QGroupBox>
#include <QSlider>
#include <QLabel>
#include <QCheckBox>
#include <QRandomGenerator>
#include <QSpinBox>
#include <QScrollArea>
#include <QTabWidget>
#include <QTabBar>
#include <QToolButton>
#include "glwidget.h"
MainWindow::MainWindow()
: m_nextX(1), m_nextY(1)
{
GLWidget *glwidget = new GLWidget(this, qRgb(20, 20, 50));
m_glWidgets << glwidget;
QLabel *label = new QLabel(this);
m_timer = new QTimer(this);
QSlider *slider = new QSlider(this);
slider->setOrientation(Qt::Horizontal);
QLabel *updateLabel = new QLabel("Update interval");
QSpinBox *updateInterval = new QSpinBox(this);
updateInterval->setSuffix(" ms");
updateInterval->setValue(10);
updateInterval->setToolTip("Interval for the timer that calls update().\n"
"Note that on most systems the swap will block to wait for vsync\n"
"and therefore an interval < 16 ms will likely lead to a 60 FPS update rate.");
QGroupBox *updateGroupBox = new QGroupBox(this);
QCheckBox *timerBased = new QCheckBox("Use timer", this);
timerBased->setChecked(false);
timerBased->setToolTip("Toggles using a timer to trigger update().\n"
"When not set, each paintGL() schedules the next update immediately,\n"
"expecting the blocking swap to throttle the thread.\n"
"This shows how unnecessary the timer is in most cases.");
QCheckBox *transparent = new QCheckBox("Transparent background", this);
transparent->setToolTip("Toggles Qt::WA_AlwaysStackOnTop and transparent clear color for glClear().\n"
"Note how the button on top stacks incorrectly when enabling this.");
QHBoxLayout *updateLayout = new QHBoxLayout;
updateLayout->addWidget(updateLabel);
updateLayout->addWidget(updateInterval);
updateLayout->addWidget(timerBased);
updateLayout->addWidget(transparent);
updateGroupBox->setLayout(updateLayout);
slider->setRange(0, 50);
slider->setSliderPosition(30);
m_timer->setInterval(10);
label->setText("A scrollable QOpenGLWidget");
label->setAlignment(Qt::AlignHCenter);
QGroupBox * groupBox = new QGroupBox(this);
setCentralWidget(groupBox);
groupBox->setTitle("QOpenGLWidget Example");
m_layout = new QGridLayout(groupBox);
QScrollArea *scrollArea = new QScrollArea;
scrollArea->setWidget(glwidget);
m_layout->addWidget(scrollArea,1,0,8,1);
m_layout->addWidget(label,9,0,1,1);
m_layout->addWidget(updateGroupBox, 10, 0, 1, 1);
m_layout->addWidget(slider, 11,0,1,1);
groupBox->setLayout(m_layout);
QMenu *fileMenu = menuBar()->addMenu("&File");
fileMenu->addAction("E&xit", this, &QWidget::close);
QMenu *showMenu = menuBar()->addMenu("&Show");
showMenu->addAction("Show 3D Logo", glwidget, &GLWidget::setLogo);
showMenu->addAction("Show 2D Texture", glwidget, &GLWidget::setTexture);
QAction *showBubbles = showMenu->addAction("Show bubbles", glwidget, &GLWidget::setShowBubbles);
showBubbles->setCheckable(true);
showBubbles->setChecked(true);
showMenu->addAction("Open tab window", this, &MainWindow::showNewWindow);
QMenu *helpMenu = menuBar()->addMenu("&Help");
helpMenu->addAction("About Qt", qApp, &QApplication::aboutQt);
connect(m_timer, &QTimer::timeout, glwidget, QOverload<>::of(&QWidget::update));
connect(slider, &QAbstractSlider::valueChanged, glwidget, &GLWidget::setScaling);
connect(transparent, &QCheckBox::toggled, glwidget, &GLWidget::setTransparent);
connect(updateInterval, &QSpinBox::valueChanged,
this, &MainWindow::updateIntervalChanged);
connect(timerBased, &QCheckBox::toggled, this, &MainWindow::timerUsageChanged);
connect(timerBased, &QCheckBox::toggled, updateInterval, &QWidget::setEnabled);
if (timerBased->isChecked())
m_timer->start();
else
updateInterval->setEnabled(false);
}
void MainWindow::updateIntervalChanged(int value)
{
m_timer->setInterval(value);
if (m_timer->isActive())
m_timer->start();
}
void MainWindow::addNew()
{
if (m_nextY == 4)
return;
GLWidget *w = new GLWidget(nullptr, qRgb(QRandomGenerator::global()->bounded(256),
QRandomGenerator::global()->bounded(256),
QRandomGenerator::global()->bounded(256)));
m_glWidgets << w;
connect(m_timer, &QTimer::timeout, w, QOverload<>::of(&QWidget::update));
m_layout->addWidget(w, m_nextY, m_nextX, 1, 1);
if (m_nextX == 3) {
m_nextX = 1;
++m_nextY;
} else {
++m_nextX;
}
}
void MainWindow::timerUsageChanged(bool enabled)
{
if (enabled) {
m_timer->start();
} else {
m_timer->stop();
for (QOpenGLWidget *w : std::as_const(m_glWidgets))
w->update();
}
}
void MainWindow::resizeEvent(QResizeEvent *)
{
m_glWidgets[0]->setMinimumSize(size() + QSize(128, 128));
}
void MainWindow::showNewWindow()
{
QTabWidget *tabs = new QTabWidget;
tabs->resize(800, 600);
QToolButton *tb = new QToolButton;
tb->setText(QLatin1String("+"));
tabs->addTab(new QLabel(QLatin1String("Add OpenGL widgets with +")), QString());
tabs->setTabEnabled(0, false);
tabs->tabBar()->setTabButton(0, QTabBar::RightSide, tb);
tabs->tabBar()->setTabsClosable(true);
QObject::connect(tabs->tabBar(), &QTabBar::tabCloseRequested, tabs, [tabs](int index) {
tabs->widget(index)->deleteLater();
});
const QString msgToTopLevel = QLatin1String("Break out to top-level window");
const QString msgFromTopLevel = QLatin1String("Move back under tab widget");
QObject::connect(tb, &QAbstractButton::clicked, tabs, [=] {
GLWidget *glwidget = new GLWidget(nullptr, Qt::blue);
glwidget->resize(tabs->size());
glwidget->setWindowTitle(QString::asprintf("QOpenGLWidget %p", glwidget));
QPushButton *btn = new QPushButton(msgToTopLevel, glwidget);
connect(btn, &QPushButton::clicked, glwidget, [=] {
if (glwidget->parent()) {
glwidget->setAttribute(Qt::WA_DeleteOnClose, true);
glwidget->setParent(nullptr);
glwidget->show();
btn->setText(msgFromTopLevel);
} else {
glwidget->setAttribute(Qt::WA_DeleteOnClose, false);
tabs->addTab(glwidget, glwidget->windowTitle());
btn->setText(msgToTopLevel);
}
});
tabs->setCurrentIndex(tabs->addTab(glwidget, glwidget->windowTitle()));
});
tabs->setAttribute(Qt::WA_DeleteOnClose);
tabs->show();
}

View File

@ -0,0 +1,39 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
#include <QGridLayout>
QT_FORWARD_DECLARE_CLASS(QOpenGLWidget)
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
void addNew();
bool timerEnabled() const { return m_timer->isActive(); }
void resizeEvent(QResizeEvent *);
public slots:
void showNewWindow();
private slots:
void updateIntervalChanged(int value);
void timerUsageChanged(bool enabled);
private:
QTimer *m_timer;
QGridLayout *m_layout;
int m_nextX;
int m_nextY;
QList<QOpenGLWidget *> m_glWidgets;
};
#endif

View File

@ -0,0 +1,15 @@
QT += widgets opengl openglwidgets
SOURCES += main.cpp \
glwidget.cpp \
mainwindow.cpp \
bubble.cpp
HEADERS += glwidget.h \
mainwindow.h \
bubble.h
RESOURCES += texture.qrc
target.path = $$[QT_INSTALL_EXAMPLES]/opengl/qopenglwidget
INSTALLS += target

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>qt.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,8 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
if(NOT TARGET Qt6::Gui)
return()
endif()
qt_internal_add_example(windows)
qt_internal_add_example(qrasterwindow)

View File

@ -0,0 +1,5 @@
requires(qtHaveModule(gui))
TEMPLATE = subdirs
SUBDIRS = windows \
qrasterwindow

View File

@ -0,0 +1,35 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(qrasterwindow LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/qpa/qrasterwindow")
find_package(Qt6 REQUIRED COMPONENTS Core Gui)
qt_standard_project_setup()
qt_add_executable(qrasterwindow
main.cpp
)
set_target_properties(qrasterwindow PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(qrasterwindow PRIVATE
Qt6::Core
Qt6::Gui
)
install(TARGETS qrasterwindow
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,91 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QRasterWindow>
#include <QPainter>
#include <QPainterPath>
#include <QGuiApplication>
#include <QMatrix4x4>
#include <QTimer>
static QPainterPath painterPathForTriangle()
{
static const QPointF bottomLeft(-1.0, -1.0);
static const QPointF top(0.0, 1.0);
static const QPointF bottomRight(1.0, -1.0);
QPainterPath path(bottomLeft);
path.lineTo(top);
path.lineTo(bottomRight);
path.closeSubpath();
return path;
}
class PaintedWindow : public QRasterWindow
{
Q_OBJECT
public:
PaintedWindow()
{
m_view.lookAt(QVector3D(3,1,1),
QVector3D(0,0,0),
QVector3D(0,1,0));
m_timer.setInterval(16);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(update()));
m_timer.start();
}
protected:
void paintEvent(QPaintEvent *)
{
QPainter p(this);
p.fillRect(QRect(0,0,width(),height()),Qt::gray);
p.setWorldTransform(m_window_matrix.toTransform());
QMatrix4x4 mvp = m_projection * m_view * m_model;
p.setTransform(mvp.toTransform(), true);
p.fillPath(painterPathForTriangle(), m_brush);
m_model.rotate(1, 0, 1, 0);
}
void resizeEvent(QResizeEvent *)
{
m_window_matrix = QTransform();
m_window_matrix.translate(width() / 2.0, height() / 2.0);
m_window_matrix.scale(width() / 2.0, -height() / 2.0);
m_projection.setToIdentity();
m_projection.perspective(45.f, qreal(width()) / qreal(height()), 0.1f, 100.f);
QLinearGradient gradient(QPointF(-1,-1), QPointF(1,1));
gradient.setColorAt(0, Qt::red);
gradient.setColorAt(1, Qt::green);
m_brush = QBrush(gradient);
}
private:
QMatrix4x4 m_window_matrix;
QMatrix4x4 m_projection;
QMatrix4x4 m_view;
QMatrix4x4 m_model;
QBrush m_brush;
QTimer m_timer;
};
int main (int argc, char **argv)
{
QGuiApplication app(argc, argv);
PaintedWindow window;
window.create();
window.show();
return app.exec();
}
#include "main.moc"

View File

@ -0,0 +1,4 @@
SOURCES += main.cpp
target.path = $$[QT_INSTALL_EXAMPLES]/qpa/qrasterwindow
INSTALLS += target

View File

@ -0,0 +1,38 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(windows LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/qpa/windows")
find_package(Qt6 REQUIRED COMPONENTS Core Gui)
qt_standard_project_setup()
qt_add_executable(windows
main.cpp
window.cpp window.h
)
set_target_properties(windows PROPERTIES
WIN32_EXECUTABLE FALSE
MACOSX_BUNDLE TRUE
)
target_link_libraries(windows PRIVATE
Qt6::Core
Qt6::CorePrivate
Qt6::Gui
Qt6::GuiPrivate
)
install(TARGETS windows
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,50 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QGuiApplication>
#include <QScreen>
#include <QRect>
#include <QSharedPointer>
#include "window.h"
int main(int argc, char **argv)
{
typedef QSharedPointer<QWindow> WindowPtr;
QGuiApplication app(argc, argv);
Window a;
a.setFramePosition(QPoint(10, 10));
a.setTitle(QStringLiteral("Window A"));
a.setObjectName(a.title());
a.setVisible(true);
Window b;
b.setFramePosition(QPoint(100, 100));
b.setTitle(QStringLiteral("Window B"));
b.setObjectName(b.title());
b.setVisible(true);
Window child(&b);
child.setObjectName(QStringLiteral("ChildOfB"));
child.setVisible(true);
// create one window on each additional screen as well
QList<WindowPtr> windows;
const QList<QScreen *> screens = app.screens();
for (QScreen *screen : screens) {
if (screen == app.primaryScreen())
continue;
WindowPtr window(new Window(screen));
QRect geometry = window->geometry();
geometry.moveCenter(screen->availableGeometry().center());
window->setGeometry(geometry);
window->setVisible(true);
window->setTitle(screen->name());
window->setObjectName(window->title());
windows.push_back(window);
}
return app.exec();
}

View File

@ -0,0 +1,164 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "window.h"
#include <private/qguiapplication_p.h>
#include <QBackingStore>
#include <QPainter>
static int colorIndexId = 0;
QColor colorTable[] =
{
QColor("#f09f8f"),
QColor("#a2bff2"),
QColor("#c0ef8f")
};
Window::Window(QScreen *screen)
: QWindow(screen)
, m_backgroundColorIndex(colorIndexId++)
{
initialize();
}
Window::Window(QWindow *parent)
: QWindow(parent)
, m_backgroundColorIndex(colorIndexId++)
{
initialize();
}
void Window::initialize()
{
if (parent())
setGeometry(QRect(160, 120, 320, 240));
else {
setFlags(flags() | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
| Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);
const QSize baseSize = QSize(640, 480);
setGeometry(QRect(geometry().topLeft(), baseSize));
setSizeIncrement(QSize(10, 10));
setBaseSize(baseSize);
setMinimumSize(QSize(240, 160));
setMaximumSize(QSize(800, 600));
}
create();
m_backingStore = new QBackingStore(this);
m_image = QImage(geometry().size(), QImage::Format_RGB32);
m_image.fill(colorTable[m_backgroundColorIndex % (sizeof(colorTable) / sizeof(colorTable[0]))].rgba());
m_lastPos = QPoint(-1, -1);
m_renderTimer = 0;
}
void Window::mousePressEvent(QMouseEvent *event)
{
m_lastPos = event->position().toPoint();
}
void Window::mouseMoveEvent(QMouseEvent *event)
{
if (m_lastPos != QPoint(-1, -1)) {
QPainter p(&m_image);
p.setRenderHint(QPainter::Antialiasing);
p.drawLine(m_lastPos, event->position().toPoint());
m_lastPos = event->position().toPoint();
scheduleRender();
}
}
void Window::mouseReleaseEvent(QMouseEvent *event)
{
if (m_lastPos != QPoint(-1, -1)) {
QPainter p(&m_image);
p.setRenderHint(QPainter::Antialiasing);
p.drawLine(m_lastPos, event->position().toPoint());
m_lastPos = QPoint(-1, -1);
scheduleRender();
}
}
void Window::exposeEvent(QExposeEvent *)
{
scheduleRender();
}
void Window::resizeEvent(QResizeEvent *)
{
QImage old = m_image;
int width = qMax(geometry().width(), old.width());
int height = qMax(geometry().height(), old.height());
if (width > old.width() || height > old.height()) {
m_image = QImage(width, height, QImage::Format_RGB32);
m_image.fill(colorTable[(m_backgroundColorIndex) % (sizeof(colorTable) / sizeof(colorTable[0]))].rgba());
QPainter p(&m_image);
p.drawImage(0, 0, old);
}
scheduleRender();
}
void Window::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Backspace:
m_text.chop(1);
break;
case Qt::Key_Enter:
case Qt::Key_Return:
m_text.append('\n');
break;
default:
m_text.append(event->text());
break;
}
scheduleRender();
}
void Window::scheduleRender()
{
if (!m_renderTimer)
m_renderTimer = startTimer(1);
}
void Window::timerEvent(QTimerEvent *)
{
if (isExposed())
render();
killTimer(m_renderTimer);
m_renderTimer = 0;
}
void Window::render()
{
QRect rect(QPoint(), geometry().size());
m_backingStore->resize(rect.size());
m_backingStore->beginPaint(rect);
QPaintDevice *device = m_backingStore->paintDevice();
QPainter p(device);
p.drawImage(0, 0, m_image);
QFont font;
font.setPixelSize(32);
p.setFont(font);
p.drawText(rect, 0, m_text);
m_backingStore->endPaint();
m_backingStore->flush(rect);
}

View File

@ -0,0 +1,41 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
#include <QWindow>
#include <QImage>
class Window : public QWindow
{
public:
Window(QWindow *parent = nullptr);
Window(QScreen *screen);
protected:
void mousePressEvent(QMouseEvent *) override;
void mouseMoveEvent(QMouseEvent *) override;
void mouseReleaseEvent(QMouseEvent *) override;
void keyPressEvent(QKeyEvent *) override;
void exposeEvent(QExposeEvent *) override;
void resizeEvent(QResizeEvent *) override;
void timerEvent(QTimerEvent *) override;
private:
void render();
void scheduleRender();
void initialize();
QString m_text;
QImage m_image;
QPoint m_lastPos;
int m_backgroundColorIndex;
QBackingStore *m_backingStore;
int m_renderTimer;
};
#endif // WINDOW_H

View File

@ -0,0 +1,9 @@
CONFIG += console
QT += gui-private core-private
HEADERS += window.h
SOURCES += window.cpp main.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/qpa/windows
INSTALLS += target

View File

@ -0,0 +1,54 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(application LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/mainwindows/application")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(application
main.cpp
mainwindow.cpp mainwindow.h
)
set_target_properties(application PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(application PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(application_resource_files
"images/copy.png"
"images/cut.png"
"images/new.png"
"images/open.png"
"images/paste.png"
"images/save.png"
)
qt_add_resources(application "application"
PREFIX
"/"
FILES
${application_resource_files}
)
install(TARGETS application
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,13 @@
QT += widgets
requires(qtConfig(filedialog))
HEADERS = mainwindow.h
SOURCES = main.cpp \
mainwindow.cpp
#! [0]
RESOURCES = application.qrc
#! [0]
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/mainwindows/application
INSTALLS += target

View File

@ -0,0 +1,10 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/copy.png</file>
<file>images/cut.png</file>
<file>images/new.png</file>
<file>images/open.png</file>
<file>images/paste.png</file>
<file>images/save.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,28 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setApplicationName("Application Example");
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCommandLineParser parser;
parser.setApplicationDescription(QCoreApplication::applicationName());
parser.addHelpOption();
parser.addVersionOption();
parser.addPositionalArgument("file", "The file to open.");
parser.process(app);
MainWindow mainWin;
if (!parser.positionalArguments().isEmpty())
mainWin.loadFile(parser.positionalArguments().first());
mainWin.show();
return app.exec();
}

View File

@ -0,0 +1,306 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include "mainwindow.h"
MainWindow::MainWindow()
: textEdit(new QPlainTextEdit)
{
setCentralWidget(textEdit);
createActions();
createStatusBar();
readSettings();
connect(textEdit->document(), &QTextDocument::contentsChanged,
this, &MainWindow::documentWasModified);
#ifndef QT_NO_SESSIONMANAGER
connect(qApp, &QGuiApplication::commitDataRequest,
this, &MainWindow::commitData);
#endif
setCurrentFile(QString());
setUnifiedTitleAndToolBarOnMac(true);
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if (maybeSave()) {
writeSettings();
event->accept();
} else {
event->ignore();
}
}
void MainWindow::newFile()
{
if (maybeSave()) {
textEdit->clear();
setCurrentFile(QString());
}
}
void MainWindow::open()
{
if (maybeSave()) {
QString fileName = QFileDialog::getOpenFileName(this);
if (!fileName.isEmpty())
loadFile(fileName);
}
}
bool MainWindow::save()
{
if (curFile.isEmpty()) {
return saveAs();
} else {
return saveFile(curFile);
}
}
bool MainWindow::saveAs()
{
QFileDialog dialog(this);
dialog.setWindowModality(Qt::WindowModal);
dialog.setAcceptMode(QFileDialog::AcceptSave);
if (dialog.exec() != QDialog::Accepted)
return false;
return saveFile(dialog.selectedFiles().first());
}
void MainWindow::about()
{
QMessageBox::about(this, tr("About Application"),
tr("The <b>Application</b> example demonstrates how to "
"write modern GUI applications using Qt, with a menu bar, "
"toolbars, and a status bar."));
}
void MainWindow::documentWasModified()
{
setWindowModified(textEdit->document()->isModified());
}
void MainWindow::createActions()
{
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
QToolBar *fileToolBar = addToolBar(tr("File"));
const QIcon newIcon = QIcon::fromTheme("document-new", QIcon(":/images/new.png"));
QAction *newAct = new QAction(newIcon, tr("&New"), this);
newAct->setShortcuts(QKeySequence::New);
newAct->setStatusTip(tr("Create a new file"));
connect(newAct, &QAction::triggered, this, &MainWindow::newFile);
fileMenu->addAction(newAct);
fileToolBar->addAction(newAct);
const QIcon openIcon = QIcon::fromTheme("document-open", QIcon(":/images/open.png"));
QAction *openAct = new QAction(openIcon, tr("&Open..."), this);
openAct->setShortcuts(QKeySequence::Open);
openAct->setStatusTip(tr("Open an existing file"));
connect(openAct, &QAction::triggered, this, &MainWindow::open);
fileMenu->addAction(openAct);
fileToolBar->addAction(openAct);
const QIcon saveIcon = QIcon::fromTheme("document-save", QIcon(":/images/save.png"));
QAction *saveAct = new QAction(saveIcon, tr("&Save"), this);
saveAct->setShortcuts(QKeySequence::Save);
saveAct->setStatusTip(tr("Save the document to disk"));
connect(saveAct, &QAction::triggered, this, &MainWindow::save);
fileMenu->addAction(saveAct);
fileToolBar->addAction(saveAct);
const QIcon saveAsIcon = QIcon::fromTheme("document-save-as");
QAction *saveAsAct = fileMenu->addAction(saveAsIcon, tr("Save &As..."), this, &MainWindow::saveAs);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
saveAsAct->setStatusTip(tr("Save the document under a new name"));
fileMenu->addSeparator();
const QIcon exitIcon = QIcon::fromTheme("application-exit");
QAction *exitAct = fileMenu->addAction(exitIcon, tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
exitAct->setStatusTip(tr("Exit the application"));
QMenu *editMenu = menuBar()->addMenu(tr("&Edit"));
QToolBar *editToolBar = addToolBar(tr("Edit"));
#ifndef QT_NO_CLIPBOARD
const QIcon cutIcon = QIcon::fromTheme("edit-cut", QIcon(":/images/cut.png"));
QAction *cutAct = new QAction(cutIcon, tr("Cu&t"), this);
cutAct->setShortcuts(QKeySequence::Cut);
cutAct->setStatusTip(tr("Cut the current selection's contents to the "
"clipboard"));
connect(cutAct, &QAction::triggered, textEdit, &QPlainTextEdit::cut);
editMenu->addAction(cutAct);
editToolBar->addAction(cutAct);
const QIcon copyIcon = QIcon::fromTheme("edit-copy", QIcon(":/images/copy.png"));
QAction *copyAct = new QAction(copyIcon, tr("&Copy"), this);
copyAct->setShortcuts(QKeySequence::Copy);
copyAct->setStatusTip(tr("Copy the current selection's contents to the "
"clipboard"));
connect(copyAct, &QAction::triggered, textEdit, &QPlainTextEdit::copy);
editMenu->addAction(copyAct);
editToolBar->addAction(copyAct);
const QIcon pasteIcon = QIcon::fromTheme("edit-paste", QIcon(":/images/paste.png"));
QAction *pasteAct = new QAction(pasteIcon, tr("&Paste"), this);
pasteAct->setShortcuts(QKeySequence::Paste);
pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
"selection"));
connect(pasteAct, &QAction::triggered, textEdit, &QPlainTextEdit::paste);
editMenu->addAction(pasteAct);
editToolBar->addAction(pasteAct);
menuBar()->addSeparator();
#endif // !QT_NO_CLIPBOARD
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &MainWindow::about);
aboutAct->setStatusTip(tr("Show the application's About box"));
QAction *aboutQtAct = helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
#ifndef QT_NO_CLIPBOARD
cutAct->setEnabled(false);
copyAct->setEnabled(false);
connect(textEdit, &QPlainTextEdit::copyAvailable, cutAct, &QAction::setEnabled);
connect(textEdit, &QPlainTextEdit::copyAvailable, copyAct, &QAction::setEnabled);
#endif // !QT_NO_CLIPBOARD
}
void MainWindow::createStatusBar()
{
statusBar()->showMessage(tr("Ready"));
}
void MainWindow::readSettings()
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray();
if (geometry.isEmpty()) {
const QRect availableGeometry = screen()->availableGeometry();
resize(availableGeometry.width() / 3, availableGeometry.height() / 2);
move((availableGeometry.width() - width()) / 2,
(availableGeometry.height() - height()) / 2);
} else {
restoreGeometry(geometry);
}
}
void MainWindow::writeSettings()
{
QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName());
settings.setValue("geometry", saveGeometry());
}
bool MainWindow::maybeSave()
{
if (!textEdit->document()->isModified())
return true;
const QMessageBox::StandardButton ret
= QMessageBox::warning(this, tr("Application"),
tr("The document has been modified.\n"
"Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
switch (ret) {
case QMessageBox::Save:
return save();
case QMessageBox::Cancel:
return false;
default:
break;
}
return true;
}
void MainWindow::loadFile(const QString &fileName)
{
QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("Application"),
tr("Cannot read file %1:\n%2.")
.arg(QDir::toNativeSeparators(fileName), file.errorString()));
return;
}
QTextStream in(&file);
#ifndef QT_NO_CURSOR
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
#endif
textEdit->setPlainText(in.readAll());
#ifndef QT_NO_CURSOR
QGuiApplication::restoreOverrideCursor();
#endif
setCurrentFile(fileName);
statusBar()->showMessage(tr("File loaded"), 2000);
}
bool MainWindow::saveFile(const QString &fileName)
{
QString errorMessage;
QGuiApplication::setOverrideCursor(Qt::WaitCursor);
QSaveFile file(fileName);
if (file.open(QFile::WriteOnly | QFile::Text)) {
QTextStream out(&file);
out << textEdit->toPlainText();
if (!file.commit()) {
errorMessage = tr("Cannot write file %1:\n%2.")
.arg(QDir::toNativeSeparators(fileName), file.errorString());
}
} else {
errorMessage = tr("Cannot open file %1 for writing:\n%2.")
.arg(QDir::toNativeSeparators(fileName), file.errorString());
}
QGuiApplication::restoreOverrideCursor();
if (!errorMessage.isEmpty()) {
QMessageBox::warning(this, tr("Application"), errorMessage);
return false;
}
setCurrentFile(fileName);
statusBar()->showMessage(tr("File saved"), 2000);
return true;
}
void MainWindow::setCurrentFile(const QString &fileName)
{
curFile = fileName;
textEdit->document()->setModified(false);
setWindowModified(false);
QString shownName = curFile;
if (curFile.isEmpty())
shownName = "untitled.txt";
setWindowFilePath(shownName);
}
QString MainWindow::strippedName(const QString &fullFileName)
{
return QFileInfo(fullFileName).fileName();
}
#ifndef QT_NO_SESSIONMANAGER
void MainWindow::commitData(QSessionManager &manager)
{
if (manager.allowsInteraction()) {
if (!maybeSave())
manager.cancel();
} else {
// Non-interactive: save without asking
if (textEdit->document()->isModified())
save();
}
}
#endif

View File

@ -0,0 +1,53 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
class QAction;
class QMenu;
class QPlainTextEdit;
class QSessionManager;
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
void loadFile(const QString &fileName);
protected:
void closeEvent(QCloseEvent *event) override;
private slots:
void newFile();
void open();
bool save();
bool saveAs();
void about();
void documentWasModified();
#ifndef QT_NO_SESSIONMANAGER
void commitData(QSessionManager &);
#endif
private:
void createActions();
void createStatusBar();
void readSettings();
void writeSettings();
bool maybeSave();
bool saveFile(const QString &fileName);
void setCurrentFile(const QString &fileName);
QString strippedName(const QString &fullFileName);
QPlainTextEdit *textEdit;
QString curFile;
};
#endif

View File

@ -0,0 +1,55 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(classwizard LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/dialogs/classwizard")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(classwizard
classwizard.cpp classwizard.h
main.cpp
)
set_target_properties(classwizard PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(classwizard PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(classwizard_resource_files
"images/background.png"
"images/banner.png"
"images/logo1.png"
"images/logo2.png"
"images/logo3.png"
"images/watermark1.png"
"images/watermark2.png"
)
qt_add_resources(classwizard "classwizard"
PREFIX
"/"
FILES
${classwizard_resource_files}
)
install(TARGETS classwizard
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,394 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include "classwizard.h"
//! [0] //! [1]
ClassWizard::ClassWizard(QWidget *parent)
: QWizard(parent)
{
addPage(new IntroPage);
addPage(new ClassInfoPage);
addPage(new CodeStylePage);
addPage(new OutputFilesPage);
addPage(new ConclusionPage);
//! [0]
setPixmap(QWizard::BannerPixmap, QPixmap(":/images/banner.png"));
setPixmap(QWizard::BackgroundPixmap, QPixmap(":/images/background.png"));
setWindowTitle(tr("Class Wizard"));
//! [2]
}
//! [1] //! [2]
//! [3]
void ClassWizard::accept()
//! [3] //! [4]
{
QByteArray className = field("className").toByteArray();
QByteArray baseClass = field("baseClass").toByteArray();
QByteArray macroName = field("macroName").toByteArray();
QByteArray baseInclude = field("baseInclude").toByteArray();
QString outputDir = field("outputDir").toString();
QString header = field("header").toString();
QString implementation = field("implementation").toString();
//! [4]
QByteArray block;
if (field("comment").toBool()) {
block += "/*\n";
block += " " + header.toLatin1() + '\n';
block += "*/\n";
block += '\n';
}
if (field("protect").toBool()) {
block += "#ifndef " + macroName + '\n';
block += "#define " + macroName + '\n';
block += '\n';
}
if (field("includeBase").toBool()) {
block += "#include " + baseInclude + '\n';
block += '\n';
}
block += "class " + className;
if (!baseClass.isEmpty())
block += " : public " + baseClass;
block += '\n';
block += "{\n";
/* qmake ignore Q_OBJECT */
if (field("qobjectMacro").toBool()) {
block += " Q_OBJECT\n";
block += '\n';
}
block += "public:\n";
if (field("qobjectCtor").toBool()) {
block += " " + className + "(QObject *parent = nullptr);\n";
} else if (field("qwidgetCtor").toBool()) {
block += " " + className + "(QWidget *parent = nullptr);\n";
} else if (field("defaultCtor").toBool()) {
block += " " + className + "();\n";
if (field("copyCtor").toBool()) {
block += " " + className + "(const " + className + " &other);\n";
block += '\n';
block += " " + className + " &operator=" + "(const " + className
+ " &other);\n";
}
}
block += "};\n";
if (field("protect").toBool()) {
block += '\n';
block += "#endif\n";
}
QFile headerFile(outputDir + '/' + header);
if (!headerFile.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(nullptr, QObject::tr("Simple Wizard"),
QObject::tr("Cannot write file %1:\n%2")
.arg(headerFile.fileName())
.arg(headerFile.errorString()));
return;
}
headerFile.write(block);
block.clear();
if (field("comment").toBool()) {
block += "/*\n";
block += " " + implementation.toLatin1() + '\n';
block += "*/\n";
block += '\n';
}
block += "#include \"" + header.toLatin1() + "\"\n";
block += '\n';
if (field("qobjectCtor").toBool()) {
block += className + "::" + className + "(QObject *parent)\n";
block += " : " + baseClass + "(parent)\n";
block += "{\n";
block += "}\n";
} else if (field("qwidgetCtor").toBool()) {
block += className + "::" + className + "(QWidget *parent)\n";
block += " : " + baseClass + "(parent)\n";
block += "{\n";
block += "}\n";
} else if (field("defaultCtor").toBool()) {
block += className + "::" + className + "()\n";
block += "{\n";
block += " // missing code\n";
block += "}\n";
if (field("copyCtor").toBool()) {
block += "\n";
block += className + "::" + className + "(const " + className
+ " &other)\n";
block += "{\n";
block += " *this = other;\n";
block += "}\n";
block += '\n';
block += className + " &" + className + "::operator=(const "
+ className + " &other)\n";
block += "{\n";
if (!baseClass.isEmpty())
block += " " + baseClass + "::operator=(other);\n";
block += " // missing code\n";
block += " return *this;\n";
block += "}\n";
}
}
QFile implementationFile(outputDir + '/' + implementation);
if (!implementationFile.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(nullptr, QObject::tr("Simple Wizard"),
QObject::tr("Cannot write file %1:\n%2")
.arg(implementationFile.fileName())
.arg(implementationFile.errorString()));
return;
}
implementationFile.write(block);
//! [5]
QDialog::accept();
//! [5] //! [6]
}
//! [6]
//! [7]
IntroPage::IntroPage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Introduction"));
setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark1.png"));
label = new QLabel(tr("This wizard will generate a skeleton C++ class "
"definition, including a few functions. You simply "
"need to specify the class name and set a few "
"options to produce a header file and an "
"implementation file for your new C++ class."));
label->setWordWrap(true);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(label);
setLayout(layout);
}
//! [7]
//! [8] //! [9]
ClassInfoPage::ClassInfoPage(QWidget *parent)
: QWizardPage(parent)
{
//! [8]
setTitle(tr("Class Information"));
setSubTitle(tr("Specify basic information about the class for which you "
"want to generate skeleton source code files."));
setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo1.png"));
//! [10]
classNameLabel = new QLabel(tr("&Class name:"));
classNameLineEdit = new QLineEdit;
classNameLabel->setBuddy(classNameLineEdit);
baseClassLabel = new QLabel(tr("B&ase class:"));
baseClassLineEdit = new QLineEdit;
baseClassLabel->setBuddy(baseClassLineEdit);
qobjectMacroCheckBox = new QCheckBox(tr("Generate Q_OBJECT &macro"));
//! [10]
groupBox = new QGroupBox(tr("C&onstructor"));
//! [9]
qobjectCtorRadioButton = new QRadioButton(tr("&QObject-style constructor"));
qwidgetCtorRadioButton = new QRadioButton(tr("Q&Widget-style constructor"));
defaultCtorRadioButton = new QRadioButton(tr("&Default constructor"));
copyCtorCheckBox = new QCheckBox(tr("&Generate copy constructor and "
"operator="));
defaultCtorRadioButton->setChecked(true);
connect(defaultCtorRadioButton, &QAbstractButton::toggled,
copyCtorCheckBox, &QWidget::setEnabled);
//! [11] //! [12]
registerField("className*", classNameLineEdit);
registerField("baseClass", baseClassLineEdit);
registerField("qobjectMacro", qobjectMacroCheckBox);
//! [11]
registerField("qobjectCtor", qobjectCtorRadioButton);
registerField("qwidgetCtor", qwidgetCtorRadioButton);
registerField("defaultCtor", defaultCtorRadioButton);
registerField("copyCtor", copyCtorCheckBox);
QVBoxLayout *groupBoxLayout = new QVBoxLayout;
//! [12]
groupBoxLayout->addWidget(qobjectCtorRadioButton);
groupBoxLayout->addWidget(qwidgetCtorRadioButton);
groupBoxLayout->addWidget(defaultCtorRadioButton);
groupBoxLayout->addWidget(copyCtorCheckBox);
groupBox->setLayout(groupBoxLayout);
QGridLayout *layout = new QGridLayout;
layout->addWidget(classNameLabel, 0, 0);
layout->addWidget(classNameLineEdit, 0, 1);
layout->addWidget(baseClassLabel, 1, 0);
layout->addWidget(baseClassLineEdit, 1, 1);
layout->addWidget(qobjectMacroCheckBox, 2, 0, 1, 2);
layout->addWidget(groupBox, 3, 0, 1, 2);
setLayout(layout);
//! [13]
}
//! [13]
//! [14]
CodeStylePage::CodeStylePage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Code Style Options"));
setSubTitle(tr("Choose the formatting of the generated code."));
setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo2.png"));
commentCheckBox = new QCheckBox(tr("&Start generated files with a "
//! [14]
"comment"));
commentCheckBox->setChecked(true);
protectCheckBox = new QCheckBox(tr("&Protect header file against multiple "
"inclusions"));
protectCheckBox->setChecked(true);
macroNameLabel = new QLabel(tr("&Macro name:"));
macroNameLineEdit = new QLineEdit;
macroNameLabel->setBuddy(macroNameLineEdit);
includeBaseCheckBox = new QCheckBox(tr("&Include base class definition"));
baseIncludeLabel = new QLabel(tr("Base class include:"));
baseIncludeLineEdit = new QLineEdit;
baseIncludeLabel->setBuddy(baseIncludeLineEdit);
connect(protectCheckBox, &QAbstractButton::toggled,
macroNameLabel, &QWidget::setEnabled);
connect(protectCheckBox, &QAbstractButton::toggled,
macroNameLineEdit, &QWidget::setEnabled);
connect(includeBaseCheckBox, &QAbstractButton::toggled,
baseIncludeLabel, &QWidget::setEnabled);
connect(includeBaseCheckBox, &QAbstractButton::toggled,
baseIncludeLineEdit, &QWidget::setEnabled);
registerField("comment", commentCheckBox);
registerField("protect", protectCheckBox);
registerField("macroName", macroNameLineEdit);
registerField("includeBase", includeBaseCheckBox);
registerField("baseInclude", baseIncludeLineEdit);
QGridLayout *layout = new QGridLayout;
layout->setColumnMinimumWidth(0, 20);
layout->addWidget(commentCheckBox, 0, 0, 1, 3);
layout->addWidget(protectCheckBox, 1, 0, 1, 3);
layout->addWidget(macroNameLabel, 2, 1);
layout->addWidget(macroNameLineEdit, 2, 2);
layout->addWidget(includeBaseCheckBox, 3, 0, 1, 3);
layout->addWidget(baseIncludeLabel, 4, 1);
layout->addWidget(baseIncludeLineEdit, 4, 2);
//! [15]
setLayout(layout);
}
//! [15]
//! [16]
void CodeStylePage::initializePage()
{
QString className = field("className").toString();
macroNameLineEdit->setText(className.toUpper() + "_H");
QString baseClass = field("baseClass").toString();
includeBaseCheckBox->setChecked(!baseClass.isEmpty());
includeBaseCheckBox->setEnabled(!baseClass.isEmpty());
baseIncludeLabel->setEnabled(!baseClass.isEmpty());
baseIncludeLineEdit->setEnabled(!baseClass.isEmpty());
QRegularExpression rx("Q[A-Z].*");
if (baseClass.isEmpty()) {
baseIncludeLineEdit->clear();
} else if (rx.match(baseClass).hasMatch()) {
baseIncludeLineEdit->setText('<' + baseClass + '>');
} else {
baseIncludeLineEdit->setText('"' + baseClass.toLower() + ".h\"");
}
}
//! [16]
OutputFilesPage::OutputFilesPage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Output Files"));
setSubTitle(tr("Specify where you want the wizard to put the generated "
"skeleton code."));
setPixmap(QWizard::LogoPixmap, QPixmap(":/images/logo3.png"));
outputDirLabel = new QLabel(tr("&Output directory:"));
outputDirLineEdit = new QLineEdit;
outputDirLabel->setBuddy(outputDirLineEdit);
headerLabel = new QLabel(tr("&Header file name:"));
headerLineEdit = new QLineEdit;
headerLabel->setBuddy(headerLineEdit);
implementationLabel = new QLabel(tr("&Implementation file name:"));
implementationLineEdit = new QLineEdit;
implementationLabel->setBuddy(implementationLineEdit);
registerField("outputDir*", outputDirLineEdit);
registerField("header*", headerLineEdit);
registerField("implementation*", implementationLineEdit);
QGridLayout *layout = new QGridLayout;
layout->addWidget(outputDirLabel, 0, 0);
layout->addWidget(outputDirLineEdit, 0, 1);
layout->addWidget(headerLabel, 1, 0);
layout->addWidget(headerLineEdit, 1, 1);
layout->addWidget(implementationLabel, 2, 0);
layout->addWidget(implementationLineEdit, 2, 1);
setLayout(layout);
}
//! [17]
void OutputFilesPage::initializePage()
{
QString className = field("className").toString();
headerLineEdit->setText(className.toLower() + ".h");
implementationLineEdit->setText(className.toLower() + ".cpp");
outputDirLineEdit->setText(QDir::toNativeSeparators(QDir::tempPath()));
}
//! [17]
ConclusionPage::ConclusionPage(QWidget *parent)
: QWizardPage(parent)
{
setTitle(tr("Conclusion"));
setPixmap(QWizard::WatermarkPixmap, QPixmap(":/images/watermark2.png"));
label = new QLabel;
label->setWordWrap(true);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(label);
setLayout(layout);
}
void ConclusionPage::initializePage()
{
QString finishText = wizard()->buttonText(QWizard::FinishButton);
finishText.remove('&');
label->setText(tr("Click %1 to generate the class skeleton.")
.arg(finishText));
}

View File

@ -0,0 +1,119 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef CLASSWIZARD_H
#define CLASSWIZARD_H
#include <QWizard>
QT_BEGIN_NAMESPACE
class QCheckBox;
class QGroupBox;
class QLabel;
class QLineEdit;
class QRadioButton;
QT_END_NAMESPACE
//! [0]
class ClassWizard : public QWizard
{
Q_OBJECT
public:
ClassWizard(QWidget *parent = nullptr);
void accept() override;
};
//! [0]
//! [1]
class IntroPage : public QWizardPage
{
Q_OBJECT
public:
IntroPage(QWidget *parent = nullptr);
private:
QLabel *label;
};
//! [1]
//! [2]
class ClassInfoPage : public QWizardPage
{
Q_OBJECT
public:
ClassInfoPage(QWidget *parent = nullptr);
private:
QLabel *classNameLabel;
QLabel *baseClassLabel;
QLineEdit *classNameLineEdit;
QLineEdit *baseClassLineEdit;
QCheckBox *qobjectMacroCheckBox;
QGroupBox *groupBox;
QRadioButton *qobjectCtorRadioButton;
QRadioButton *qwidgetCtorRadioButton;
QRadioButton *defaultCtorRadioButton;
QCheckBox *copyCtorCheckBox;
};
//! [2]
//! [3]
class CodeStylePage : public QWizardPage
{
Q_OBJECT
public:
CodeStylePage(QWidget *parent = nullptr);
protected:
void initializePage() override;
private:
QCheckBox *commentCheckBox;
QCheckBox *protectCheckBox;
QCheckBox *includeBaseCheckBox;
QLabel *macroNameLabel;
QLabel *baseIncludeLabel;
QLineEdit *macroNameLineEdit;
QLineEdit *baseIncludeLineEdit;
};
//! [3]
class OutputFilesPage : public QWizardPage
{
Q_OBJECT
public:
OutputFilesPage(QWidget *parent = nullptr);
protected:
void initializePage() override;
private:
QLabel *outputDirLabel;
QLabel *headerLabel;
QLabel *implementationLabel;
QLineEdit *outputDirLineEdit;
QLineEdit *headerLineEdit;
QLineEdit *implementationLineEdit;
};
class ConclusionPage : public QWizardPage
{
Q_OBJECT
public:
ConclusionPage(QWidget *parent = nullptr);
protected:
void initializePage() override;
private:
QLabel *label;
};
#endif

View File

@ -0,0 +1,10 @@
QT += widgets
HEADERS = classwizard.h
SOURCES = classwizard.cpp \
main.cpp
RESOURCES = classwizard.qrc
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/dialogs/classwizard
INSTALLS += target

View File

@ -0,0 +1,11 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>images/background.png</file>
<file>images/banner.png</file>
<file>images/logo1.png</file>
<file>images/logo2.png</file>
<file>images/logo3.png</file>
<file>images/watermark1.png</file>
<file>images/watermark2.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,26 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include <QTranslator>
#include <QLocale>
#include <QLibraryInfo>
#include "classwizard.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
#ifndef QT_NO_TRANSLATION
QString translatorFileName = QLatin1String("qtbase_");
translatorFileName += QLocale::system().name();
QTranslator *translator = new QTranslator(&app);
if (translator->load(translatorFileName, QLibraryInfo::path(QLibraryInfo::TranslationsPath)))
app.installTranslator(translator);
#endif
ClassWizard wizard;
wizard.show();
return app.exec();
}

View File

@ -0,0 +1,37 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(extension LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/dialogs/extension")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(extension
finddialog.cpp finddialog.h
main.cpp
)
set_target_properties(extension PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(extension PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
install(TARGETS extension
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,9 @@
QT += widgets
HEADERS = finddialog.h
SOURCES = finddialog.cpp \
main.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/dialogs/extension
INSTALLS += target

View File

@ -0,0 +1,77 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtWidgets>
#include "finddialog.h"
//! [0]
FindDialog::FindDialog(QWidget *parent)
: QDialog(parent)
{
label = new QLabel(tr("Find &what:"));
lineEdit = new QLineEdit;
label->setBuddy(lineEdit);
caseCheckBox = new QCheckBox(tr("Match &case"));
fromStartCheckBox = new QCheckBox(tr("Search from &start"));
fromStartCheckBox->setChecked(true);
//! [1]
findButton = new QPushButton(tr("&Find"));
findButton->setDefault(true);
moreButton = new QPushButton(tr("&More"));
moreButton->setCheckable(true);
//! [0]
moreButton->setAutoDefault(false);
//! [1]
//! [2]
extension = new QWidget;
wholeWordsCheckBox = new QCheckBox(tr("&Whole words"));
backwardCheckBox = new QCheckBox(tr("Search &backward"));
searchSelectionCheckBox = new QCheckBox(tr("Search se&lection"));
//! [2]
//! [3]
buttonBox = new QDialogButtonBox(Qt::Vertical);
buttonBox->addButton(findButton, QDialogButtonBox::ActionRole);
buttonBox->addButton(moreButton, QDialogButtonBox::ActionRole);
connect(moreButton, &QAbstractButton::toggled, extension, &QWidget::setVisible);
QVBoxLayout *extensionLayout = new QVBoxLayout;
extensionLayout->setContentsMargins(QMargins());
extensionLayout->addWidget(wholeWordsCheckBox);
extensionLayout->addWidget(backwardCheckBox);
extensionLayout->addWidget(searchSelectionCheckBox);
extension->setLayout(extensionLayout);
//! [3]
//! [4]
QHBoxLayout *topLeftLayout = new QHBoxLayout;
topLeftLayout->addWidget(label);
topLeftLayout->addWidget(lineEdit);
QVBoxLayout *leftLayout = new QVBoxLayout;
leftLayout->addLayout(topLeftLayout);
leftLayout->addWidget(caseCheckBox);
leftLayout->addWidget(fromStartCheckBox);
QGridLayout *mainLayout = new QGridLayout;
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
mainLayout->addLayout(leftLayout, 0, 0);
mainLayout->addWidget(buttonBox, 0, 1);
mainLayout->addWidget(extension, 1, 0, 1, 2);
mainLayout->setRowStretch(2, 1);
setLayout(mainLayout);
setWindowTitle(tr("Extension"));
//! [4] //! [5]
extension->hide();
}
//! [5]

View File

@ -0,0 +1,41 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef FINDDIALOG_H
#define FINDDIALOG_H
#include <QDialog>
QT_BEGIN_NAMESPACE
class QCheckBox;
class QDialogButtonBox;
class QGroupBox;
class QLabel;
class QLineEdit;
class QPushButton;
QT_END_NAMESPACE
//! [0]
class FindDialog : public QDialog
{
Q_OBJECT
public:
FindDialog(QWidget *parent = nullptr);
private:
QLabel *label;
QLineEdit *lineEdit;
QCheckBox *caseCheckBox;
QCheckBox *fromStartCheckBox;
QCheckBox *wholeWordsCheckBox;
QCheckBox *searchSelectionCheckBox;
QCheckBox *backwardCheckBox;
QDialogButtonBox *buttonBox;
QPushButton *findButton;
QPushButton *moreButton;
QWidget *extension;
};
//! [0]
#endif

View File

@ -0,0 +1,16 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include "finddialog.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
FindDialog dialog;
dialog.show();
return app.exec();
}

View File

@ -0,0 +1,50 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(fridgemagnets LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/draganddrop/fridgemagnets")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(fridgemagnets
draglabel.cpp draglabel.h
dragwidget.cpp dragwidget.h
main.cpp
)
set_target_properties(fridgemagnets PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(fridgemagnets PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(fridgemagnets_resource_files
"words.txt"
)
qt_add_resources(fridgemagnets "fridgemagnets"
PREFIX
"/dictionary"
FILES
${fridgemagnets_resource_files}
)
install(TARGETS fridgemagnets
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,51 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "draglabel.h"
#include <QtWidgets>
//! [0]
DragLabel::DragLabel(const QString &text, QWidget *parent)
: QLabel(parent)
{
QFontMetrics metric(font());
QSize size = metric.size(Qt::TextSingleLine, text);
QImage image(size.width() + 12, size.height() + 12, QImage::Format_ARGB32_Premultiplied);
image.fill(qRgba(0, 0, 0, 0));
QFont font;
font.setStyleStrategy(QFont::ForceOutline);
//! [0]
//! [1]
QLinearGradient gradient(0, 0, 0, image.height()-1);
gradient.setColorAt(0.0, Qt::white);
gradient.setColorAt(0.2, QColor(200, 200, 255));
gradient.setColorAt(0.8, QColor(200, 200, 255));
gradient.setColorAt(1.0, QColor(127, 127, 200));
QPainter painter;
painter.begin(&image);
painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(gradient);
painter.drawRoundedRect(QRectF(0.5, 0.5, image.width()-1, image.height()-1),
25, 25, Qt::RelativeSize);
painter.setFont(font);
painter.setBrush(Qt::black);
painter.drawText(QRect(QPoint(6, 6), size), Qt::AlignCenter, text);
painter.end();
//! [1]
//! [2]
setPixmap(QPixmap::fromImage(image));
m_labelText = text;
}
//! [2]
QString DragLabel::labelText() const
{
return m_labelText;
}

View File

@ -0,0 +1,27 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef DRAGLABEL_H
#define DRAGLABEL_H
#include <QLabel>
QT_BEGIN_NAMESPACE
class QDragEnterEvent;
class QDragMoveEvent;
class QFrame;
QT_END_NAMESPACE
//! [0]
class DragLabel : public QLabel
{
public:
DragLabel(const QString &text, QWidget *parent);
QString labelText() const;
private:
QString m_labelText;
};
//! [0]
#endif // DRAGLABEL_H

View File

@ -0,0 +1,176 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "draglabel.h"
#include "dragwidget.h"
#include <QtWidgets>
static inline QString fridgetMagnetsMimeType() { return QStringLiteral("application/x-fridgemagnet"); }
//! [0]
DragWidget::DragWidget(QWidget *parent)
: QWidget(parent)
{
QFile dictionaryFile(QStringLiteral(":/dictionary/words.txt"));
dictionaryFile.open(QFile::ReadOnly);
QTextStream inputStream(&dictionaryFile);
//! [0]
//! [1]
int x = 5;
int y = 5;
while (!inputStream.atEnd()) {
QString word;
inputStream >> word;
if (!word.isEmpty()) {
DragLabel *wordLabel = new DragLabel(word, this);
wordLabel->move(x, y);
wordLabel->show();
wordLabel->setAttribute(Qt::WA_DeleteOnClose);
x += wordLabel->width() + 2;
if (x >= 245) {
x = 5;
y += wordLabel->height() + 2;
}
}
}
//! [1]
//! [2]
QPalette newPalette = palette();
newPalette.setColor(QPalette::Window, Qt::white);
setPalette(newPalette);
setMinimumSize(400, qMax(200, y));
setWindowTitle(tr("Fridge Magnets"));
//! [2] //! [3]
setAcceptDrops(true);
}
//! [3]
//! [4]
void DragWidget::dragEnterEvent(QDragEnterEvent *event)
{
//! [4] //! [5]
if (event->mimeData()->hasFormat(fridgetMagnetsMimeType())) {
if (children().contains(event->source())) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
//! [5] //! [6]
}
//! [6] //! [7]
} else if (event->mimeData()->hasText()) {
event->acceptProposedAction();
} else {
event->ignore();
}
}
//! [7]
//! [8]
void DragWidget::dragMoveEvent(QDragMoveEvent *event)
{
if (event->mimeData()->hasFormat(fridgetMagnetsMimeType())) {
if (children().contains(event->source())) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
}
} else if (event->mimeData()->hasText()) {
event->acceptProposedAction();
} else {
event->ignore();
}
}
//! [8]
//! [9]
void DragWidget::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat(fridgetMagnetsMimeType())) {
const QMimeData *mime = event->mimeData();
//! [9] //! [10]
QByteArray itemData = mime->data(fridgetMagnetsMimeType());
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
QString text;
QPoint offset;
dataStream >> text >> offset;
//! [10]
//! [11]
DragLabel *newLabel = new DragLabel(text, this);
newLabel->move(event->position().toPoint() - offset);
newLabel->show();
newLabel->setAttribute(Qt::WA_DeleteOnClose);
if (event->source() == this) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
}
//! [11] //! [12]
} else if (event->mimeData()->hasText()) {
QStringList pieces = event->mimeData()->text().split(
QRegularExpression(QStringLiteral("\\s+")), Qt::SkipEmptyParts);
QPoint position = event->position().toPoint();
for (const QString &piece : pieces) {
DragLabel *newLabel = new DragLabel(piece, this);
newLabel->move(position);
newLabel->show();
newLabel->setAttribute(Qt::WA_DeleteOnClose);
position += QPoint(newLabel->width(), 0);
}
event->acceptProposedAction();
} else {
event->ignore();
}
}
//! [12]
//! [13]
void DragWidget::mousePressEvent(QMouseEvent *event)
{
//! [13]
//! [14]
DragLabel *child = static_cast<DragLabel*>(childAt(event->position().toPoint()));
if (!child)
return;
QPoint hotSpot = event->position().toPoint() - child->pos();
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << child->labelText() << QPoint(hotSpot);
//! [14]
//! [15]
QMimeData *mimeData = new QMimeData;
mimeData->setData(fridgetMagnetsMimeType(), itemData);
mimeData->setText(child->labelText());
//! [15]
//! [16]
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setPixmap(child->pixmap());
drag->setHotSpot(hotSpot);
child->hide();
//! [16]
//! [17]
if (drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::CopyAction) == Qt::MoveAction)
child->close();
else
child->show();
}
//! [17]

View File

@ -0,0 +1,28 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef DRAGWIDGET_H
#define DRAGWIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QDragEnterEvent;
class QDropEvent;
QT_END_NAMESPACE
//! [0]
class DragWidget : public QWidget
{
public:
explicit DragWidget(QWidget *parent = nullptr);
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
void dropEvent(QDropEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
};
//! [0]
#endif // DRAGWIDGET_H

View File

@ -0,0 +1,12 @@
QT += widgets
HEADERS = draglabel.h \
dragwidget.h
RESOURCES = fridgemagnets.qrc
SOURCES = draglabel.cpp \
dragwidget.cpp \
main.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/draganddrop/fridgemagnets
INSTALLS += target

View File

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/dictionary">
<file>words.txt</file>
</qresource>
</RCC>

View File

@ -0,0 +1,23 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include "dragwidget.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
#ifdef QT_KEYPAD_NAVIGATION
QApplication::setNavigationMode(Qt::NavigationModeCursorAuto);
#endif
DragWidget window;
bool smallScreen = QApplication::arguments().contains(QStringLiteral("-small-screen"));
if (smallScreen)
window.showFullScreen();
else
window.show();
return app.exec();
}

View File

@ -0,0 +1,48 @@
Colorless
green
ideas
sleep
furiously
A
colorless
green
idea
is
a
new
untried
idea
that
is
without
vividness
dull
and
unexciting
To
sleep
furiously
may
seem
a
puzzling
turn
of
phrase
but
the
mind
in
sleep
often
indeed
moves
furiously
with
ideas
and
images
flickering
in
and
out

View File

@ -0,0 +1,51 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(puzzle LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/draganddrop_puzzle")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(draganddrop_puzzle
main.cpp
mainwindow.cpp mainwindow.h
pieceslist.cpp pieceslist.h
puzzlewidget.cpp puzzlewidget.h
)
set_target_properties(draganddrop_puzzle PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(draganddrop_puzzle PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(puzzle_resource_files
"example.jpg"
)
qt_add_resources(draganddrop_puzzle "puzzle"
PREFIX
"/images"
FILES
${puzzle_resource_files}
)
install(TARGETS draganddrop_puzzle
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -0,0 +1,15 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow window;
window.loadImage(QStringLiteral(":/images/example.jpg"));
window.show();
return app.exec();
}

View File

@ -0,0 +1,118 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "mainwindow.h"
#include "pieceslist.h"
#include "puzzlewidget.h"
#include <QtWidgets>
#include <stdlib.h>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setupMenus();
setupWidgets();
setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
setWindowTitle(tr("Puzzle"));
}
void MainWindow::openImage()
{
const QString directory =
QStandardPaths::standardLocations(QStandardPaths::PicturesLocation).value(0, QDir::homePath());
QFileDialog dialog(this, tr("Open Image"), directory);
dialog.setAcceptMode(QFileDialog::AcceptOpen);
dialog.setFileMode(QFileDialog::ExistingFile);
QStringList mimeTypeFilters;
for (const QByteArray &mimeTypeName : QImageReader::supportedMimeTypes())
mimeTypeFilters.append(mimeTypeName);
mimeTypeFilters.sort();
dialog.setMimeTypeFilters(mimeTypeFilters);
dialog.selectMimeTypeFilter("image/jpeg");
if (dialog.exec() == QDialog::Accepted)
loadImage(dialog.selectedFiles().constFirst());
}
void MainWindow::loadImage(const QString &fileName)
{
QPixmap newImage;
if (!newImage.load(fileName)) {
QMessageBox::warning(this, tr("Open Image"),
tr("The image file could not be loaded."),
QMessageBox::Close);
return;
}
puzzleImage = newImage;
setupPuzzle();
}
void MainWindow::setCompleted()
{
QMessageBox::information(this, tr("Puzzle Completed"),
tr("Congratulations! You have completed the puzzle!\n"
"Click OK to start again."),
QMessageBox::Ok);
setupPuzzle();
}
void MainWindow::setupPuzzle()
{
int size = qMin(puzzleImage.width(), puzzleImage.height());
puzzleImage = puzzleImage.copy((puzzleImage.width() - size) / 2,
(puzzleImage.height() - size) / 2, size, size).scaled(puzzleWidget->width(),
puzzleWidget->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
piecesList->clear();
for (int y = 0; y < 5; ++y) {
for (int x = 0; x < 5; ++x) {
int pieceSize = puzzleWidget->pieceSize();
QPixmap pieceImage = puzzleImage.copy(x * pieceSize, y * pieceSize, pieceSize, pieceSize);
piecesList->addPiece(pieceImage, QPoint(x, y));
}
}
for (int i = 0; i < piecesList->count(); ++i) {
if (QRandomGenerator::global()->bounded(2) == 1) {
QListWidgetItem *item = piecesList->takeItem(i);
piecesList->insertItem(0, item);
}
}
puzzleWidget->clear();
}
void MainWindow::setupMenus()
{
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
QAction *openAction = fileMenu->addAction(tr("&Open..."), this, &MainWindow::openImage);
openAction->setShortcuts(QKeySequence::Open);
QAction *exitAction = fileMenu->addAction(tr("E&xit"), qApp, &QCoreApplication::quit);
exitAction->setShortcuts(QKeySequence::Quit);
QMenu *gameMenu = menuBar()->addMenu(tr("&Game"));
gameMenu->addAction(tr("&Restart"), this, &MainWindow::setupPuzzle);
}
void MainWindow::setupWidgets()
{
QFrame *frame = new QFrame;
QHBoxLayout *frameLayout = new QHBoxLayout(frame);
puzzleWidget = new PuzzleWidget(400);
piecesList = new PiecesList(puzzleWidget->pieceSize(), this);
connect(puzzleWidget, &PuzzleWidget::puzzleCompleted,
this, &MainWindow::setCompleted, Qt::QueuedConnection);
frameLayout->addWidget(piecesList);
frameLayout->addWidget(puzzleWidget);
setCentralWidget(frame);
}

View File

@ -0,0 +1,40 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPixmap>
class PiecesList;
class PuzzleWidget;
QT_BEGIN_NAMESPACE
class QListWidgetItem;
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
void loadImage(const QString &path);
public slots:
void openImage();
void setupPuzzle();
private slots:
void setCompleted();
private:
void setupMenus();
void setupWidgets();
QPixmap puzzleImage;
PiecesList *piecesList;
PuzzleWidget *puzzleWidget;
};
#endif // MAINWINDOW_H

View File

@ -0,0 +1,87 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "pieceslist.h"
#include <QDrag>
#include <QDragEnterEvent>
#include <QMimeData>
PiecesList::PiecesList(int pieceSize, QWidget *parent)
: QListWidget(parent), m_PieceSize(pieceSize)
{
setDragEnabled(true);
setViewMode(QListView::IconMode);
setIconSize(QSize(m_PieceSize, m_PieceSize));
setSpacing(10);
setAcceptDrops(true);
setDropIndicatorShown(true);
}
void PiecesList::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType()))
event->accept();
else
event->ignore();
}
void PiecesList::dragMoveEvent(QDragMoveEvent *event)
{
if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType())) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->ignore();
}
}
void PiecesList::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType())) {
QByteArray pieceData = event->mimeData()->data(PiecesList::puzzleMimeType());
QDataStream dataStream(&pieceData, QIODevice::ReadOnly);
QPixmap pixmap;
QPoint location;
dataStream >> pixmap >> location;
addPiece(pixmap, location);
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->ignore();
}
}
void PiecesList::addPiece(const QPixmap &pixmap, const QPoint &location)
{
QListWidgetItem *pieceItem = new QListWidgetItem(this);
pieceItem->setIcon(QIcon(pixmap));
pieceItem->setData(Qt::UserRole, QVariant(pixmap));
pieceItem->setData(Qt::UserRole+1, location);
pieceItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
}
void PiecesList::startDrag(Qt::DropActions /*supportedActions*/)
{
QListWidgetItem *item = currentItem();
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
QPixmap pixmap = qvariant_cast<QPixmap>(item->data(Qt::UserRole));
QPoint location = item->data(Qt::UserRole+1).toPoint();
dataStream << pixmap << location;
QMimeData *mimeData = new QMimeData;
mimeData->setData(PiecesList::puzzleMimeType(), itemData);
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setHotSpot(QPoint(pixmap.width()/2, pixmap.height()/2));
drag->setPixmap(pixmap);
if (drag->exec(Qt::MoveAction) == Qt::MoveAction)
delete takeItem(row(item));
}

View File

@ -0,0 +1,28 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef PIECESLIST_H
#define PIECESLIST_H
#include <QListWidget>
class PiecesList : public QListWidget
{
Q_OBJECT
public:
explicit PiecesList(int pieceSize, QWidget *parent = nullptr);
void addPiece(const QPixmap &pixmap, const QPoint &location);
static QString puzzleMimeType() { return QStringLiteral("image/x-puzzle-piece"); }
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
void dropEvent(QDropEvent *event) override;
void startDrag(Qt::DropActions supportedActions) override;
int m_PieceSize;
};
#endif // PIECESLIST_H

View File

@ -0,0 +1,17 @@
QT += widgets
requires(qtConfig(filedialog))
HEADERS = mainwindow.h \
pieceslist.h \
puzzlewidget.h
RESOURCES = puzzle.qrc
SOURCES = main.cpp \
mainwindow.cpp \
pieceslist.cpp \
puzzlewidget.cpp
QMAKE_PROJECT_NAME = dndpuzzle
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/draganddrop/puzzle
INSTALLS += target

View File

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/images">
<file>example.jpg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,167 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "puzzlewidget.h"
#include "pieceslist.h"
#include <QDrag>
#include <QDragEnterEvent>
#include <QMimeData>
#include <QPainter>
PuzzleWidget::PuzzleWidget(int imageSize, QWidget *parent)
: QWidget(parent), m_ImageSize(imageSize)
{
setAcceptDrops(true);
setMinimumSize(m_ImageSize, m_ImageSize);
setMaximumSize(m_ImageSize, m_ImageSize);
}
void PuzzleWidget::clear()
{
pieces.clear();
highlightedRect = QRect();
inPlace = 0;
update();
}
void PuzzleWidget::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType()))
event->accept();
else
event->ignore();
}
void PuzzleWidget::dragLeaveEvent(QDragLeaveEvent *event)
{
QRect updateRect = highlightedRect;
highlightedRect = QRect();
update(updateRect);
event->accept();
}
void PuzzleWidget::dragMoveEvent(QDragMoveEvent *event)
{
QRect updateRect = highlightedRect.united(targetSquare(event->position().toPoint()));
if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType())
&& findPiece(targetSquare(event->position().toPoint())) == -1) {
highlightedRect = targetSquare(event->position().toPoint());
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
highlightedRect = QRect();
event->ignore();
}
update(updateRect);
}
void PuzzleWidget::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat(PiecesList::puzzleMimeType())
&& findPiece(targetSquare(event->position().toPoint())) == -1) {
QByteArray pieceData = event->mimeData()->data(PiecesList::puzzleMimeType());
QDataStream dataStream(&pieceData, QIODevice::ReadOnly);
Piece piece;
piece.rect = targetSquare(event->position().toPoint());
dataStream >> piece.pixmap >> piece.location;
pieces.append(piece);
highlightedRect = QRect();
update(piece.rect);
event->setDropAction(Qt::MoveAction);
event->accept();
if (piece.location == piece.rect.topLeft() / pieceSize()) {
inPlace++;
if (inPlace == 25)
emit puzzleCompleted();
}
} else {
highlightedRect = QRect();
event->ignore();
}
}
int PuzzleWidget::findPiece(const QRect &pieceRect) const
{
for (int i = 0, size = pieces.size(); i < size; ++i) {
if (pieces.at(i).rect == pieceRect)
return i;
}
return -1;
}
void PuzzleWidget::mousePressEvent(QMouseEvent *event)
{
QRect square = targetSquare(event->position().toPoint());
const int found = findPiece(square);
if (found == -1)
return;
Piece piece = pieces.takeAt(found);
if (piece.location == square.topLeft() / pieceSize())
inPlace--;
update(square);
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream << piece.pixmap << piece.location;
QMimeData *mimeData = new QMimeData;
mimeData->setData(PiecesList::puzzleMimeType(), itemData);
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->setHotSpot(event->position().toPoint() - square.topLeft());
drag->setPixmap(piece.pixmap);
if (drag->exec(Qt::MoveAction) != Qt::MoveAction) {
pieces.insert(found, piece);
update(targetSquare(event->position().toPoint()));
if (piece.location == square.topLeft() / pieceSize())
inPlace++;
}
}
void PuzzleWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.fillRect(event->rect(), Qt::white);
if (highlightedRect.isValid()) {
painter.setBrush(QColor("#ffcccc"));
painter.setPen(Qt::NoPen);
painter.drawRect(highlightedRect.adjusted(0, 0, -1, -1));
}
for (const Piece &piece : pieces)
painter.drawPixmap(piece.rect, piece.pixmap);
}
const QRect PuzzleWidget::targetSquare(const QPoint &position) const
{
QPoint topLeft = QPoint(position.x() / pieceSize(), position.y() / pieceSize()) * pieceSize();
return QRect(topLeft, QSize(pieceSize(), pieceSize()));
}
int PuzzleWidget::pieceSize() const
{
return m_ImageSize / 5;
}
int PuzzleWidget::imageSize() const
{
return m_ImageSize;
}

View File

@ -0,0 +1,56 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef PUZZLEWIDGET_H
#define PUZZLEWIDGET_H
#include <QPoint>
#include <QPixmap>
#include <QList>
#include <QWidget>
QT_BEGIN_NAMESPACE
class QDragEnterEvent;
class QDropEvent;
class QMouseEvent;
QT_END_NAMESPACE
class PuzzleWidget : public QWidget
{
Q_OBJECT
public:
explicit PuzzleWidget(int imageSize, QWidget *parent = nullptr);
void clear();
int pieceSize() const;
int imageSize() const;
signals:
void puzzleCompleted();
protected:
void dragEnterEvent(QDragEnterEvent *event) override;
void dragLeaveEvent(QDragLeaveEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
void dropEvent(QDropEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *event) override;
private:
struct Piece {
QPixmap pixmap;
QRect rect;
QPoint location;
};
int findPiece(const QRect &pieceRect) const;
const QRect targetSquare(const QPoint &position) const;
QList<Piece> pieces;
QRect highlightedRect;
int inPlace;
int m_ImageSize;
};
#endif // PUZZLEWIDGET_H

View File

@ -0,0 +1,49 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(fademessage LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/effects/fademessage")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(fademessage
fademessage.cpp fademessage.h
main.cpp
)
set_target_properties(fademessage PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(fademessage PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(fademessage_resource_files
"background.jpg"
)
qt_add_resources(fademessage "fademessage"
PREFIX
"/"
FILES
${fademessage_resource_files}
)
install(TARGETS fademessage
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,2 @@
The background is taken from a public domain photo at:
http://www.photos8.com/view/windows_problem_blue-800x600.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

View File

@ -0,0 +1,91 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "fademessage.h"
#include <QtWidgets>
FadeMessage::FadeMessage(QWidget *parent): QGraphicsView(parent)
{
setScene(&m_scene);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setupScene();
m_animation = new QPropertyAnimation(m_effect, "strength", this);
m_animation->setDuration(500);
m_animation->setEasingCurve(QEasingCurve::InOutSine);
m_animation->setStartValue(0);
m_animation->setEndValue(1);
setRenderHint(QPainter::Antialiasing, true);
setFrameStyle(QFrame::NoFrame);
}
void FadeMessage::togglePopup()
{
if (m_message->isVisible()) {
m_message->setVisible(false);
m_animation->setDirection(QAbstractAnimation::Backward);
} else {
m_message->setVisible(true);
m_animation->setDirection(QAbstractAnimation::Forward);
}
m_animation->start();
}
void FadeMessage::setupScene()
{
QGraphicsRectItem *parent = m_scene.addRect(0, 0, 800, 600);
parent->setPen(Qt::NoPen);
parent->setZValue(0);
QGraphicsPixmapItem *bg = m_scene.addPixmap(QPixmap(":/background.jpg"));
bg->setParentItem(parent);
bg->setZValue(-1);
for (int i = 1; i < 5; ++i)
for (int j = 2; j < 5; ++j) {
QGraphicsRectItem *item = m_scene.addRect(i * 50, (j - 1) * 50, 38, 38);
item->setParentItem(parent);
item->setZValue(1);
int hue = 12 * (i * 5 + j);
item->setBrush(QColor::fromHsv(hue, 128, 128));
}
QFont font;
font.setPointSize(font.pointSize() * 2);
font.setBold(true);
QFontMetrics fontMetrics(font);
int fh = fontMetrics.height();
QString sceneText = "Qt Everywhere!";
int sceneTextWidth = fontMetrics.horizontalAdvance(sceneText);
QGraphicsRectItem *block = m_scene.addRect(50, 300, sceneTextWidth, fh + 3);
block->setPen(Qt::NoPen);
block->setBrush(QColor(102, 153, 51));
QGraphicsTextItem *text = m_scene.addText(sceneText, font);
text->setDefaultTextColor(Qt::white);
text->setPos(50, 300);
block->setZValue(2);
block->hide();
text->setParentItem(block);
m_message = block;
m_effect = new QGraphicsColorizeEffect;
m_effect->setColor(QColor(122, 193, 66));
m_effect->setStrength(0);
m_effect->setEnabled(true);
parent->setGraphicsEffect(m_effect);
QPushButton *press = new QPushButton;
press->setText(tr("Press me"));
connect(press, &QAbstractButton::clicked, this, &FadeMessage::togglePopup);
m_scene.addWidget(press);
press->move(300, 500);
}

View File

@ -0,0 +1,33 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef FADEMESSAGE_H
#define FADEMESSAGE_H
#include <QGraphicsEffect>
#include <QGraphicsView>
#include <QPropertyAnimation>
#include "fademessage.h"
class FadeMessage: public QGraphicsView
{
Q_OBJECT
public:
FadeMessage(QWidget *parent = nullptr);
private:
void setupScene();
private slots:
void togglePopup();
private:
QGraphicsScene m_scene;
QGraphicsColorizeEffect *m_effect;
QGraphicsItem *m_message;
QPropertyAnimation *m_animation;
};
#endif // FADEMESSAGE_H

View File

@ -0,0 +1,9 @@
QT += widgets
SOURCES += main.cpp fademessage.cpp
HEADERS += fademessage.h
RESOURCES += fademessage.qrc
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/effects/fademessage
INSTALLS += target

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/" >
<file>background.jpg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,18 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QApplication>
#include "fademessage.h"
int main(int argc, char **argv)
{
QApplication app(argc, argv);
FadeMessage widget;
widget.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Popup Message with Effect"));
widget.setFixedSize(400, 600);
widget.show();
return app.exec();
}

View File

@ -0,0 +1,50 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(embeddeddialogs LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview/embeddeddialogs")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(embeddeddialogs
customproxy.cpp customproxy.h
embeddeddialog.cpp embeddeddialog.h embeddeddialog.ui
main.cpp
)
set_target_properties(embeddeddialogs PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(embeddeddialogs PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
# Resources:
set(embeddeddialogs_resource_files
"No-Ones-Laughing-3.jpg"
)
qt_add_resources(embeddeddialogs "embeddeddialogs"
PREFIX
"/"
FILES
${embeddeddialogs_resource_files}
)
install(TARGETS embeddeddialogs
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,133 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "customproxy.h"
#include <QGraphicsScene>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
CustomProxy::CustomProxy(QGraphicsItem *parent, Qt::WindowFlags wFlags)
: QGraphicsProxyWidget(parent, wFlags), timeLine(new QTimeLine(250, this))
{
connect(timeLine, &QTimeLine::valueChanged,
this, &CustomProxy::updateStep);
connect(timeLine, &QTimeLine::stateChanged,
this, &CustomProxy::stateChanged);
}
QRectF CustomProxy::boundingRect() const
{
return QGraphicsProxyWidget::boundingRect().adjusted(0, 0, 10, 10);
}
void CustomProxy::paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
const QColor color(0, 0, 0, 64);
QRectF r = windowFrameRect();
QRectF right(r.right(), r.top() + 10, 10, r.height() - 10);
QRectF bottom(r.left() + 10, r.bottom(), r.width(), 10);
bool intersectsRight = right.intersects(option->exposedRect);
bool intersectsBottom = bottom.intersects(option->exposedRect);
if (intersectsRight && intersectsBottom) {
QPainterPath path;
path.addRect(right);
path.addRect(bottom);
painter->setPen(Qt::NoPen);
painter->setBrush(color);
painter->drawPath(path);
} else if (intersectsBottom) {
painter->fillRect(bottom, color);
} else if (intersectsRight) {
painter->fillRect(right, color);
}
QGraphicsProxyWidget::paintWindowFrame(painter, option, widget);
}
void CustomProxy::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
QGraphicsProxyWidget::hoverEnterEvent(event);
scene()->setActiveWindow(this);
if (qFuzzyCompare(timeLine->currentValue(), 1))
zoomIn();
}
void CustomProxy::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
QGraphicsProxyWidget::hoverLeaveEvent(event);
if (!popupShown
&& (timeLine->direction() != QTimeLine::Backward || qFuzzyIsNull(timeLine->currentValue()))) {
zoomOut();
}
}
bool CustomProxy::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
if (watched->isWindow()
&& (event->type() == QEvent::UngrabMouse || event->type() == QEvent::GrabMouse)) {
popupShown = watched->isVisible();
if (!popupShown && !isUnderMouse())
zoomOut();
}
return QGraphicsProxyWidget::sceneEventFilter(watched, event);
}
QVariant CustomProxy::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemChildAddedChange || change == ItemChildRemovedChange) {
if (change == ItemChildAddedChange) {
currentPopup = qvariant_cast<QGraphicsItem *>(value);
currentPopup->setCacheMode(ItemCoordinateCache);
if (scene())
currentPopup->installSceneEventFilter(this);
} else if (scene()) {
currentPopup->removeSceneEventFilter(this);
currentPopup = nullptr;
}
} else if (currentPopup && change == ItemSceneHasChanged) {
currentPopup->installSceneEventFilter(this);
}
return QGraphicsProxyWidget::itemChange(change, value);
}
void CustomProxy::updateStep(qreal step)
{
QRectF r = boundingRect();
setTransform(QTransform()
.translate(r.width() / 2, r.height() / 2)
.rotate(step * 30, Qt::XAxis)
.rotate(step * 10, Qt::YAxis)
.rotate(step * 5, Qt::ZAxis)
.scale(1 + 1.5 * step, 1 + 1.5 * step)
.translate(-r.width() / 2, -r.height() / 2));
}
void CustomProxy::stateChanged(QTimeLine::State state)
{
if (state == QTimeLine::Running) {
if (timeLine->direction() == QTimeLine::Forward)
setCacheMode(ItemCoordinateCache);
} else if (state == QTimeLine::NotRunning) {
if (timeLine->direction() == QTimeLine::Backward)
setCacheMode(DeviceCoordinateCache);
}
}
void CustomProxy::zoomIn()
{
if (timeLine->direction() != QTimeLine::Forward)
timeLine->setDirection(QTimeLine::Forward);
if (timeLine->state() == QTimeLine::NotRunning)
timeLine->start();
}
void CustomProxy::zoomOut()
{
if (timeLine->direction() != QTimeLine::Backward)
timeLine->setDirection(QTimeLine::Backward);
if (timeLine->state() == QTimeLine::NotRunning)
timeLine->start();
}

View File

@ -0,0 +1,39 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef CUSTOMPROXY_H
#define CUSTOMPROXY_H
#include <QTimeLine>
#include <QGraphicsProxyWidget>
class CustomProxy : public QGraphicsProxyWidget
{
Q_OBJECT
public:
explicit CustomProxy(QGraphicsItem *parent = nullptr, Qt::WindowFlags wFlags = { });
QRectF boundingRect() const override;
void paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget) override;
protected:
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override;
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
private slots:
void updateStep(qreal step);
void stateChanged(QTimeLine::State);
void zoomIn();
void zoomOut();
private:
QTimeLine *timeLine;
QGraphicsItem *currentPopup = nullptr;
bool popupShown = false;
};
#endif // CUSTOMPROXY_H

View File

@ -0,0 +1,70 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "embeddeddialog.h"
#include "ui_embeddeddialog.h"
#include <QStyleFactory>
EmbeddedDialog::EmbeddedDialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::EmbeddedDialog)
{
ui->setupUi(this);
ui->layoutDirection->setCurrentIndex(layoutDirection() != Qt::LeftToRight);
const QStringList styleKeys = QStyleFactory::keys();
for (const QString &styleName : styleKeys) {
ui->style->addItem(styleName);
if (style()->objectName().toLower() == styleName.toLower())
ui->style->setCurrentIndex(ui->style->count() - 1);
}
connect(ui->layoutDirection, &QComboBox::activated,
this, &EmbeddedDialog::layoutDirectionChanged);
connect(ui->spacing, &QSlider::valueChanged,
this, &EmbeddedDialog::spacingChanged);
connect(ui->fontComboBox, &QFontComboBox::currentFontChanged,
this, &EmbeddedDialog::fontChanged);
connect(ui->style, &QComboBox::textActivated,
this, &EmbeddedDialog::styleChanged);
}
EmbeddedDialog::~EmbeddedDialog()
{
delete ui;
}
void EmbeddedDialog::layoutDirectionChanged(int index)
{
setLayoutDirection(index == 0 ? Qt::LeftToRight : Qt::RightToLeft);
}
void EmbeddedDialog::spacingChanged(int spacing)
{
layout()->setSpacing(spacing);
adjustSize();
}
void EmbeddedDialog::fontChanged(const QFont &font)
{
setFont(font);
}
static void setStyleHelper(QWidget *widget, QStyle *style)
{
widget->setStyle(style);
widget->setPalette(style->standardPalette());
const QObjectList children = widget->children();
for (QObject *child : children) {
if (QWidget *childWidget = qobject_cast<QWidget *>(child))
setStyleHelper(childWidget, style);
}
}
void EmbeddedDialog::styleChanged(const QString &styleName)
{
QStyle *style = QStyleFactory::create(styleName);
if (style)
setStyleHelper(this, style);
}

View File

@ -0,0 +1,33 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef EMBEDDEDDIALOG_H
#define EMBEDDEDDIALOG_H
#include <QDialog>
QT_BEGIN_NAMESPACE
namespace Ui {
class EmbeddedDialog;
}
QT_END_NAMESPACE
class EmbeddedDialog : public QDialog
{
Q_OBJECT
public:
EmbeddedDialog(QWidget *parent = nullptr);
~EmbeddedDialog();
private slots:
void layoutDirectionChanged(int index);
void spacingChanged(int spacing);
void fontChanged(const QFont &font);
void styleChanged(const QString &styleName);
private:
Ui::EmbeddedDialog *ui;
};
#endif // EMBEDDEDDIALOG_H

View File

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EmbeddedDialog</class>
<widget class="QDialog" name="EmbeddedDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>407</width>
<height>134</height>
</rect>
</property>
<property name="windowTitle">
<string>Embedded Dialog</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Layout Direction:</string>
</property>
<property name="buddy">
<cstring>layoutDirection</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="layoutDirection">
<item>
<property name="text">
<string>Left to Right</string>
</property>
</item>
<item>
<property name="text">
<string>Right to Left</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Select Font:</string>
</property>
<property name="buddy">
<cstring>fontComboBox</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QFontComboBox" name="fontComboBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Style:</string>
</property>
<property name="buddy">
<cstring>style</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="style"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Layout spacing:</string>
</property>
<property name="buddy">
<cstring>spacing</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSlider" name="spacing">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,18 @@
QT += widgets
requires(qtConfig(fontcombobox))
SOURCES += main.cpp
SOURCES += customproxy.cpp embeddeddialog.cpp
HEADERS += customproxy.h embeddeddialog.h
FORMS += embeddeddialog.ui
RESOURCES += embeddeddialogs.qrc
build_all:!build_pass {
CONFIG -= build_all
CONFIG += release
}
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/graphicsview/embeddeddialogs
INSTALLS += target

View File

@ -0,0 +1,5 @@
<RCC>
<qresource>
<file>No-Ones-Laughing-3.jpg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,42 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "customproxy.h"
#include "embeddeddialog.h"
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsScene scene;
scene.setStickyFocus(true);
const int gridSize = 10;
for (int y = 0; y < gridSize; ++y) {
for (int x = 0; x < gridSize; ++x) {
CustomProxy *proxy = new CustomProxy(nullptr, Qt::Window);
proxy->setWidget(new EmbeddedDialog);
QRectF rect = proxy->boundingRect();
proxy->setPos(x * rect.width() * 1.05, y * rect.height() * 1.05);
proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
scene.addItem(proxy);
}
}
scene.setSceneRect(scene.itemsBoundingRect());
QGraphicsView view(&scene);
view.scale(0.5, 0.5);
view.setRenderHints(view.renderHints() | QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
view.setBackgroundBrush(QPixmap(":/No-Ones-Laughing-3.jpg"));
view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
view.show();
view.setWindowTitle("Embedded Dialogs Example");
return app.exec();
}

View File

@ -0,0 +1,38 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
project(flowlayout LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/graphicsview_flowlayout")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
qt_standard_project_setup()
qt_add_executable(graphicsview_flowlayout
flowlayout.cpp flowlayout.h
main.cpp
window.cpp window.h
)
set_target_properties(graphicsview_flowlayout PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(graphicsview_flowlayout PRIVATE
Qt6::Core
Qt6::Gui
Qt6::Widgets
)
install(TARGETS graphicsview_flowlayout
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
)

View File

@ -0,0 +1,170 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "flowlayout.h"
#include <QtMath>
FlowLayout::FlowLayout(QGraphicsLayoutItem *parent) : QGraphicsLayout(parent)
{
QSizePolicy sp = sizePolicy();
sp.setHeightForWidth(true);
setSizePolicy(sp);
}
void FlowLayout::insertItem(int index, QGraphicsLayoutItem *item)
{
item->setParentLayoutItem(this);
if (index > m_items.count() || index < 0)
index = m_items.count();
m_items.insert(index, item);
invalidate();
}
int FlowLayout::count() const
{
return m_items.count();
}
QGraphicsLayoutItem *FlowLayout::itemAt(int index) const
{
return m_items.value(index);
}
void FlowLayout::removeAt(int index)
{
m_items.removeAt(index);
invalidate();
}
qreal FlowLayout::spacing(Qt::Orientation o) const
{
return m_spacing[int(o) - 1];
}
void FlowLayout::setSpacing(Qt::Orientations o, qreal spacing)
{
if (o & Qt::Horizontal)
m_spacing[0] = spacing;
if (o & Qt::Vertical)
m_spacing[1] = spacing;
}
void FlowLayout::setGeometry(const QRectF &geom)
{
QGraphicsLayout::setGeometry(geom);
doLayout(geom, true);
}
qreal FlowLayout::doLayout(const QRectF &geom, bool applyNewGeometry) const
{
qreal left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
const qreal maxw = geom.width() - left - right;
qreal x = 0;
qreal y = 0;
qreal maxRowHeight = 0;
QSizeF pref;
for (QGraphicsLayoutItem *item : m_items) {
pref = item->effectiveSizeHint(Qt::PreferredSize);
maxRowHeight = qMax(maxRowHeight, pref.height());
qreal next_x;
next_x = x + pref.width();
if (next_x > maxw) {
if (qFuzzyIsNull(x)) {
pref.setWidth(maxw);
} else {
x = 0;
next_x = pref.width();
}
y += maxRowHeight + spacing(Qt::Vertical);
maxRowHeight = 0;
}
if (applyNewGeometry)
item->setGeometry(QRectF(QPointF(left + x, top + y), pref));
x = next_x + spacing(Qt::Horizontal);
}
maxRowHeight = qMax(maxRowHeight, pref.height());
return top + y + maxRowHeight + bottom;
}
QSizeF FlowLayout::minSize(const QSizeF &constraint) const
{
QSizeF size(0, 0);
qreal left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
if (constraint.width() >= 0) { // height for width
const qreal height = doLayout(QRectF(QPointF(0,0), constraint), false);
size = QSizeF(constraint.width(), height);
} else if (constraint.height() >= 0) { // width for height?
// not supported
} else {
for (const QGraphicsLayoutItem *item : std::as_const(m_items))
size = size.expandedTo(item->effectiveSizeHint(Qt::MinimumSize));
size += QSizeF(left + right, top + bottom);
}
return size;
}
QSizeF FlowLayout::prefSize() const
{
qreal left, right;
getContentsMargins(&left, nullptr, &right, nullptr);
qreal maxh = 0;
qreal totalWidth = 0;
for (const QGraphicsLayoutItem *item : std::as_const(m_items)) {
if (totalWidth > 0)
totalWidth += spacing(Qt::Horizontal);
QSizeF pref = item->effectiveSizeHint(Qt::PreferredSize);
totalWidth += pref.width();
maxh = qMax(maxh, pref.height());
}
maxh += spacing(Qt::Vertical);
const qreal goldenAspectRatio = 1.61803399;
qreal w = qSqrt(totalWidth * maxh * goldenAspectRatio) + left + right;
return minSize(QSizeF(w, -1));
}
QSizeF FlowLayout::maxSize() const
{
qreal totalWidth = 0;
qreal totalHeight = 0;
for (const QGraphicsLayoutItem *item : std::as_const(m_items)) {
if (totalWidth > 0)
totalWidth += spacing(Qt::Horizontal);
if (totalHeight > 0)
totalHeight += spacing(Qt::Vertical);
QSizeF pref = item->effectiveSizeHint(Qt::PreferredSize);
totalWidth += pref.width();
totalHeight += pref.height();
}
qreal left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
return QSizeF(left + totalWidth + right, top + totalHeight + bottom);
}
QSizeF FlowLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
QSizeF sh = constraint;
switch (which) {
case Qt::PreferredSize:
sh = prefSize();
break;
case Qt::MinimumSize:
sh = minSize(constraint);
break;
case Qt::MaximumSize:
sh = maxSize();
break;
default:
break;
}
return sh;
}

View File

@ -0,0 +1,44 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef FLOWLAYOUT_H
#define FLOWLAYOUT_H
#include <QGraphicsLayout>
class FlowLayout : public QGraphicsLayout
{
public:
FlowLayout(QGraphicsLayoutItem *parent = nullptr);
inline void addItem(QGraphicsLayoutItem *item);
void insertItem(int index, QGraphicsLayoutItem *item);
void setSpacing(Qt::Orientations o, qreal spacing);
qreal spacing(Qt::Orientation o) const;
// inherited functions
void setGeometry(const QRectF &geom) override;
int count() const override;
QGraphicsLayoutItem *itemAt(int index) const override;
void removeAt(int index) override;
protected:
QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const override;
private:
qreal doLayout(const QRectF &geom, bool applyNewGeometry) const;
QSizeF minSize(const QSizeF &constraint) const;
QSizeF prefSize() const;
QSizeF maxSize() const;
QList<QGraphicsLayoutItem *> m_items;
qreal m_spacing[2] = {6, 6};
};
inline void FlowLayout::addItem(QGraphicsLayoutItem *item)
{
insertItem(-1, item);
}
#endif // FLOWLAYOUT_H

View File

@ -0,0 +1,10 @@
QT += widgets
QMAKE_PROJECT_NAME = flowlayout_graphicsview
HEADERS += flowlayout.h window.h
SOURCES += flowlayout.cpp main.cpp window.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/graphicsview/flowlayout
INSTALLS += target

View File

@ -0,0 +1,24 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
//! [1]
#include "window.h"
#include <QApplication>
#include <QGraphicsView>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsScene scene;
QGraphicsView view(&scene);
Window *w = new Window;
scene.addItem(w);
view.resize(400, 300);
view.show();
return app.exec();
}
//! [1]

View File

@ -0,0 +1,24 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include "window.h"
#include "flowlayout.h"
#include <QGraphicsProxyWidget>
#include <QLabel>
Window::Window(QGraphicsItem *parent) : QGraphicsWidget(parent, Qt::Window)
{
FlowLayout *lay = new FlowLayout;
const QString sentence(QLatin1String("I am not bothered by the fact that I am unknown."
" I am bothered when I do not know others. (Confucius)"));
const QList<QStringView> words = QStringView{ sentence }.split(QLatin1Char(' '), Qt::SkipEmptyParts);
for (const QStringView &word : words) {
QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(this);
QLabel *label = new QLabel(word.toString());
label->setFrameStyle(QFrame::Box | QFrame::Plain);
proxy->setWidget(label);
lay->addItem(proxy);
}
setLayout(lay);
}

View File

@ -0,0 +1,16 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#ifndef WINDOW_H
#define WINDOW_H
#include <QGraphicsWidget>
class Window : public QGraphicsWidget
{
Q_OBJECT
public:
Window(QGraphicsItem *parent = nullptr);
};
#endif // WINDOW_H

Some files were not shown because too many files have changed in this diff Show More