1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the examples of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include "mainwindow.h"
52#include "fbitem.h"
53#include <QVBoxLayout>
54#include <QGroupBox>
55#include <QRadioButton>
56#include <QCheckBox>
57#include <QLabel>
58#include <QQuickItem>
59
60MainWindow::MainWindow(bool transparency, bool noRenderAlpha)
61 : m_currentView(nullptr),
62 m_currentRootObject(nullptr),
63 m_transparent(transparency),
64 m_noRenderAlpha(noRenderAlpha)
65{
66 QVBoxLayout *layout = new QVBoxLayout;
67
68 QGroupBox *groupBox = new QGroupBox(tr(s: "Type"));
69 QVBoxLayout *vbox = new QVBoxLayout;
70 m_radioView = new QRadioButton(tr(s: "QQuickView in a window container (direct)"));
71 m_radioWidget = new QRadioButton(tr(s: "QQuickWidget (indirect through framebuffer objects)"));
72 vbox->addWidget(m_radioWidget);
73 vbox->addWidget(m_radioView);
74 m_radioWidget->setChecked(true);
75 m_state = Unknown;
76 connect(sender: m_radioWidget, signal: &QRadioButton::toggled, receiver: this, slot: &MainWindow::updateView);
77 connect(sender: m_radioView, signal: &QRadioButton::toggled, receiver: this, slot: &MainWindow::updateView);
78 groupBox->setLayout(vbox);
79
80 layout->addWidget(groupBox);
81
82 m_checkboxMultiSample = new QCheckBox(tr(s: "Multisample (4x)"));
83 connect(sender: m_checkboxMultiSample, signal: &QCheckBox::toggled, receiver: this, slot: &MainWindow::updateView);
84 layout->addWidget(m_checkboxMultiSample);
85
86 m_labelStatus = new QLabel;
87 layout->addWidget(m_labelStatus);
88
89 QWidget *quickContainer = new QWidget;
90 layout->addWidget(quickContainer);
91 layout->setStretchFactor(w: quickContainer, stretch: 8);
92 m_containerLayout = new QVBoxLayout;
93 quickContainer->setLayout(m_containerLayout);
94
95 // Add an overlay widget to demonstrate that it will _not_ work with
96 // QQuickView, whereas it is perfectly fine with QQuickWidget.
97 QPalette semiTransparent(QColor(255,0,0,128));
98 semiTransparent.setBrush(acr: QPalette::Text, abrush: Qt::white);
99 semiTransparent.setBrush(acr: QPalette::WindowText, abrush: Qt::white);
100
101 m_overlayLabel = new QLabel("This is a\nsemi-transparent\n overlay widget\nwhich is placed\non top\n of the Quick\ncontent.", this);
102 m_overlayLabel->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
103 m_overlayLabel->setAutoFillBackground(true);
104 m_overlayLabel->setPalette(semiTransparent);
105 QFont f = font();
106 f.setPixelSize(QFontInfo(f).pixelSize()*2);
107 f.setWeight(QFont::Bold);
108 m_overlayLabel->setFont(f);
109 m_overlayLabel->hide();
110
111 m_checkboxOverlayVisible = new QCheckBox(tr(s: "Show widget overlay"));
112 connect(sender: m_checkboxOverlayVisible, signal: &QCheckBox::toggled, receiver: m_overlayLabel, slot: &QWidget::setVisible);
113 layout->addWidget(m_checkboxOverlayVisible);
114
115 setLayout(layout);
116
117 updateView();
118}
119
120void MainWindow::resizeEvent(QResizeEvent*)
121{
122 int margin = width() / 10;
123 int top = m_checkboxMultiSample->y();
124 int bottom = m_checkboxOverlayVisible->geometry().bottom();
125 m_overlayLabel->setGeometry(ax: margin, ay: top, aw: width() - 2 * margin, ah: bottom - top);
126}
127
128void MainWindow::switchTo(QWidget *view)
129{
130 if (m_containerLayout->count())
131 m_containerLayout->takeAt(index: 0);
132
133 delete m_currentView;
134 m_currentView = view;
135 m_containerLayout->addWidget(w: m_currentView);
136 m_currentView->setFocus();
137}
138
139void MainWindow::updateView()
140{
141 QSurfaceFormat format;
142 format.setDepthBufferSize(16);
143 format.setStencilBufferSize(8);
144 if (m_transparent)
145 format.setAlphaBufferSize(8);
146 if (m_checkboxMultiSample->isChecked())
147 format.setSamples(4);
148
149 State state = m_radioView->isChecked() ? UseWindow : UseWidget;
150
151 if (m_format == format && m_state == state)
152 return;
153
154 m_format = format;
155 m_state = state;
156
157 QString text = m_currentRootObject
158 ? m_currentRootObject->property(name: "currentText").toString()
159 : QStringLiteral("Hello Qt");
160
161 QUrl source("qrc:qquickviewcomparison/test.qml");
162
163 if (m_state == UseWindow) {
164 QQuickView *quickView = new QQuickView;
165 // m_transparent is not supported here since many systems have problems with semi-transparent child windows
166 quickView->setFormat(m_format);
167 quickView->setResizeMode(QQuickView::SizeRootObjectToView);
168 connect(sender: quickView, signal: &QQuickView::statusChanged, receiver: this, slot: &MainWindow::onStatusChangedView);
169 connect(sender: quickView, signal: &QQuickView::sceneGraphError, receiver: this, slot: &MainWindow::onSceneGraphError);
170 quickView->setSource(source);
171 m_currentRootObject = quickView->rootObject();
172 switchTo(view: QWidget::createWindowContainer(window: quickView));
173 } else if (m_state == UseWidget) {
174 QQuickWidget *quickWidget = new QQuickWidget;
175 if (m_transparent)
176 quickWidget->setClearColor(Qt::transparent);
177 quickWidget->setFormat(m_format);
178 quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
179 connect(sender: quickWidget, signal: &QQuickWidget::statusChanged, receiver: this, slot: &MainWindow::onStatusChangedWidget);
180 connect(sender: quickWidget, signal: &QQuickWidget::sceneGraphError, receiver: this, slot: &MainWindow::onSceneGraphError);
181 quickWidget->setSource(source);
182 m_currentRootObject = quickWidget->rootObject();
183 switchTo(view: quickWidget);
184 }
185
186 if (m_currentRootObject) {
187 m_currentRootObject->setProperty(name: "currentText", value: text);
188 m_currentRootObject->setProperty(name: "multisample", value: m_checkboxMultiSample->isChecked());
189 if (!m_noRenderAlpha)
190 m_currentRootObject->setProperty(name: "translucency", value: m_transparent);
191 }
192
193 m_overlayLabel->raise();
194}
195
196void MainWindow::onStatusChangedView(QQuickView::Status status)
197{
198 QString s;
199 switch (status) {
200 case QQuickView::Null:
201 s = tr(s: "Null");
202 break;
203 case QQuickView::Ready:
204 s = tr(s: "Ready");
205 break;
206 case QQuickView::Loading:
207 s = tr(s: "Loading");
208 break;
209 case QQuickView::Error:
210 s = tr(s: "Error");
211 break;
212 default:
213 s = tr(s: "Unknown");
214 break;
215 }
216 m_labelStatus->setText(tr(s: "QQuickView status: %1").arg(a: s));
217}
218
219void MainWindow::onStatusChangedWidget(QQuickWidget::Status status)
220{
221 QString s;
222 switch (status) {
223 case QQuickWidget::Null:
224 s = tr(s: "Null");
225 break;
226 case QQuickWidget::Ready:
227 s = tr(s: "Ready");
228 break;
229 case QQuickWidget::Loading:
230 s = tr(s: "Loading");
231 break;
232 case QQuickWidget::Error:
233 s = tr(s: "Error");
234 break;
235 default:
236 s = tr(s: "Unknown");
237 break;
238 }
239 m_labelStatus->setText(tr(s: "QQuickWidget status: %1").arg(a: s));
240}
241
242void MainWindow::onSceneGraphError(QQuickWindow::SceneGraphError error, const QString &message)
243{
244 m_labelStatus->setText(tr(s: "Scenegraph error %1: %2").arg(a: error).arg(a: message));
245}
246

source code of qtdeclarative/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp