1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 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 | |
53 | #include <QApplication> |
54 | #include <QMenuBar> |
55 | #include <QGroupBox> |
56 | #include <QSlider> |
57 | #include <QLabel> |
58 | #include <QCheckBox> |
59 | #include <QRandomGenerator> |
60 | #include <QSpinBox> |
61 | #include <QScrollArea> |
62 | |
63 | #include "glwidget.h" |
64 | |
65 | MainWindow::MainWindow() |
66 | : m_nextX(1), m_nextY(1) |
67 | { |
68 | GLWidget *glwidget = new GLWidget(this, true, qRgb(r: 20, g: 20, b: 50)); |
69 | m_glWidgets << glwidget; |
70 | QLabel *label = new QLabel(this); |
71 | m_timer = new QTimer(this); |
72 | QSlider *slider = new QSlider(this); |
73 | slider->setOrientation(Qt::Horizontal); |
74 | |
75 | QLabel *updateLabel = new QLabel("Update interval" ); |
76 | QSpinBox *updateInterval = new QSpinBox(this); |
77 | updateInterval->setSuffix(" ms" ); |
78 | updateInterval->setValue(10); |
79 | updateInterval->setToolTip("Interval for the timer that calls update().\n" |
80 | "Note that on most systems the swap will block to wait for vsync\n" |
81 | "and therefore an interval < 16 ms will likely lead to a 60 FPS update rate." ); |
82 | QGroupBox *updateGroupBox = new QGroupBox(this); |
83 | QCheckBox *timerBased = new QCheckBox("Use timer" , this); |
84 | timerBased->setChecked(false); |
85 | timerBased->setToolTip("Toggles using a timer to trigger update().\n" |
86 | "When not set, each paintGL() schedules the next update immediately,\n" |
87 | "expecting the blocking swap to throttle the thread.\n" |
88 | "This shows how unnecessary the timer is in most cases." ); |
89 | QCheckBox *transparent = new QCheckBox("Transparent background" , this); |
90 | transparent->setToolTip("Toggles Qt::WA_AlwaysStackOnTop and transparent clear color for glClear().\n" |
91 | "Note how the button on top stacks incorrectly when enabling this." ); |
92 | QHBoxLayout *updateLayout = new QHBoxLayout; |
93 | updateLayout->addWidget(updateLabel); |
94 | updateLayout->addWidget(updateInterval); |
95 | updateLayout->addWidget(timerBased); |
96 | updateLayout->addWidget(transparent); |
97 | updateGroupBox->setLayout(updateLayout); |
98 | |
99 | slider->setRange(min: 0, max: 50); |
100 | slider->setSliderPosition(30); |
101 | m_timer->setInterval(10); |
102 | label->setText("A scrollable QOpenGLWidget" ); |
103 | label->setAlignment(Qt::AlignHCenter); |
104 | |
105 | QGroupBox * groupBox = new QGroupBox(this); |
106 | setCentralWidget(groupBox); |
107 | groupBox->setTitle("QOpenGLWidget Example" ); |
108 | |
109 | m_layout = new QGridLayout(groupBox); |
110 | |
111 | QScrollArea *scrollArea = new QScrollArea; |
112 | scrollArea->setWidget(glwidget); |
113 | |
114 | m_layout->addWidget(scrollArea,row: 1,column: 0,rowSpan: 8,columnSpan: 1); |
115 | m_layout->addWidget(label,row: 9,column: 0,rowSpan: 1,columnSpan: 1); |
116 | m_layout->addWidget(updateGroupBox, row: 10, column: 0, rowSpan: 1, columnSpan: 1); |
117 | m_layout->addWidget(slider, row: 11,column: 0,rowSpan: 1,columnSpan: 1); |
118 | |
119 | groupBox->setLayout(m_layout); |
120 | |
121 | |
122 | QMenu * = menuBar()->addMenu(title: "&File" ); |
123 | fileMenu->addAction(text: "E&xit" , object: this, slot: &QWidget::close); |
124 | QMenu * = menuBar()->addMenu(title: "&Show" ); |
125 | showMenu->addAction(text: "Show 3D Logo" , object: glwidget, slot: &GLWidget::setLogo); |
126 | showMenu->addAction(text: "Show 2D Texture" , object: glwidget, slot: &GLWidget::setTexture); |
127 | QAction *showBubbles = showMenu->addAction(text: "Show bubbles" , object: glwidget, slot: &GLWidget::setShowBubbles); |
128 | showBubbles->setCheckable(true); |
129 | showBubbles->setChecked(true); |
130 | QMenu * = menuBar()->addMenu(title: "&Help" ); |
131 | helpMenu->addAction(text: "About Qt" , qApp, slot: &QApplication::aboutQt); |
132 | |
133 | connect(sender: m_timer, signal: &QTimer::timeout, receiver: glwidget, slot: QOverload<>::of(ptr: &QWidget::update)); |
134 | |
135 | connect(sender: slider, signal: &QAbstractSlider::valueChanged, receiver: glwidget, slot: &GLWidget::setScaling); |
136 | connect(sender: transparent, signal: &QCheckBox::toggled, receiver: glwidget, slot: &GLWidget::setTransparent); |
137 | connect(sender: updateInterval, signal: QOverload<int>::of(ptr: &QSpinBox::valueChanged), |
138 | receiver: this, slot: &MainWindow::updateIntervalChanged); |
139 | connect(sender: timerBased, signal: &QCheckBox::toggled, receiver: this, slot: &MainWindow::timerUsageChanged); |
140 | connect(sender: timerBased, signal: &QCheckBox::toggled, receiver: updateInterval, slot: &QWidget::setEnabled); |
141 | |
142 | if (timerBased->isChecked()) |
143 | m_timer->start(); |
144 | else |
145 | updateInterval->setEnabled(false); |
146 | } |
147 | |
148 | void MainWindow::updateIntervalChanged(int value) |
149 | { |
150 | m_timer->setInterval(value); |
151 | if (m_timer->isActive()) |
152 | m_timer->start(); |
153 | } |
154 | |
155 | void MainWindow::addNew() |
156 | { |
157 | if (m_nextY == 4) |
158 | return; |
159 | GLWidget *w = new GLWidget(this, false, qRgb(r: QRandomGenerator::global()->bounded(highest: 256), |
160 | g: QRandomGenerator::global()->bounded(highest: 256), |
161 | b: QRandomGenerator::global()->bounded(highest: 256))); |
162 | m_glWidgets << w; |
163 | connect(sender: m_timer, signal: &QTimer::timeout, receiver: w, slot: QOverload<>::of(ptr: &QWidget::update)); |
164 | m_layout->addWidget(w, row: m_nextY, column: m_nextX, rowSpan: 1, columnSpan: 1); |
165 | if (m_nextX == 3) { |
166 | m_nextX = 1; |
167 | ++m_nextY; |
168 | } else { |
169 | ++m_nextX; |
170 | } |
171 | } |
172 | |
173 | void MainWindow::timerUsageChanged(bool enabled) |
174 | { |
175 | if (enabled) { |
176 | m_timer->start(); |
177 | } else { |
178 | m_timer->stop(); |
179 | for (QOpenGLWidget *w : qAsConst(t&: m_glWidgets)) |
180 | w->update(); |
181 | } |
182 | } |
183 | |
184 | void MainWindow::resizeEvent(QResizeEvent *) |
185 | { |
186 | m_glWidgets[0]->setMinimumSize(size() + QSize(128, 128)); |
187 | } |
188 | |