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 | |
60 | MainWindow::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 | |
120 | void 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 | |
128 | void 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 | |
139 | void 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 | |
196 | void 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 | |
219 | void 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 | |
242 | void 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 | |