|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the examples of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "spectrograph.h" |
|
43 #include <QPainter> |
|
44 #include <QMouseEvent> |
|
45 #include <QDebug> |
|
46 #include <QTimerEvent> |
|
47 |
|
48 const int NullTimerId = -1; |
|
49 const int NullIndex = -1; |
|
50 const int BarSelectionInterval = 2000; |
|
51 |
|
52 Spectrograph::Spectrograph(QWidget *parent) |
|
53 : QWidget(parent) |
|
54 , m_barSelected(NullIndex) |
|
55 , m_timerId(NullTimerId) |
|
56 , m_lowFreq(0.0) |
|
57 , m_highFreq(0.0) |
|
58 { |
|
59 setMinimumHeight(100); |
|
60 } |
|
61 |
|
62 Spectrograph::~Spectrograph() |
|
63 { |
|
64 |
|
65 } |
|
66 |
|
67 void Spectrograph::setParams(int numBars, qreal lowFreq, qreal highFreq) |
|
68 { |
|
69 Q_ASSERT(numBars > 0); |
|
70 Q_ASSERT(highFreq > lowFreq); |
|
71 m_bars.resize(numBars); |
|
72 m_lowFreq = lowFreq; |
|
73 m_highFreq = highFreq; |
|
74 updateBars(); |
|
75 } |
|
76 |
|
77 void Spectrograph::timerEvent(QTimerEvent *event) |
|
78 { |
|
79 Q_ASSERT(event->timerId() == m_timerId); |
|
80 Q_UNUSED(event) // suppress warnings in release builds |
|
81 killTimer(m_timerId); |
|
82 m_timerId = NullTimerId; |
|
83 m_barSelected = NullIndex; |
|
84 update(); |
|
85 } |
|
86 |
|
87 void Spectrograph::paintEvent(QPaintEvent *event) |
|
88 { |
|
89 Q_UNUSED(event) |
|
90 |
|
91 QPainter painter(this); |
|
92 painter.fillRect(rect(), Qt::black); |
|
93 |
|
94 const int numBars = m_bars.count(); |
|
95 |
|
96 // Highlight region of selected bar |
|
97 if (m_barSelected != NullIndex && numBars) { |
|
98 QRect regionRect = rect(); |
|
99 regionRect.setLeft(m_barSelected * rect().width() / numBars); |
|
100 regionRect.setWidth(rect().width() / numBars); |
|
101 QColor regionColor(202, 202, 64); |
|
102 painter.setBrush(Qt::DiagCrossPattern); |
|
103 painter.fillRect(regionRect, regionColor); |
|
104 painter.setBrush(Qt::NoBrush); |
|
105 } |
|
106 |
|
107 QColor barColor(51, 204, 102); |
|
108 QColor clipColor(255, 255, 0); |
|
109 |
|
110 // Draw the outline |
|
111 const QColor gridColor = barColor.darker(); |
|
112 QPen gridPen(gridColor); |
|
113 painter.setPen(gridPen); |
|
114 painter.drawLine(rect().topLeft(), rect().topRight()); |
|
115 painter.drawLine(rect().topRight(), rect().bottomRight()); |
|
116 painter.drawLine(rect().bottomRight(), rect().bottomLeft()); |
|
117 painter.drawLine(rect().bottomLeft(), rect().topLeft()); |
|
118 |
|
119 QVector<qreal> dashes; |
|
120 dashes << 2 << 2; |
|
121 gridPen.setDashPattern(dashes); |
|
122 painter.setPen(gridPen); |
|
123 |
|
124 // Draw vertical lines between bars |
|
125 if (numBars) { |
|
126 const int numHorizontalSections = numBars; |
|
127 QLine line(rect().topLeft(), rect().bottomLeft()); |
|
128 for (int i=1; i<numHorizontalSections; ++i) { |
|
129 line.translate(rect().width()/numHorizontalSections, 0); |
|
130 painter.drawLine(line); |
|
131 } |
|
132 } |
|
133 |
|
134 // Draw horizontal lines |
|
135 const int numVerticalSections = 10; |
|
136 QLine line(rect().topLeft(), rect().topRight()); |
|
137 for (int i=1; i<numVerticalSections; ++i) { |
|
138 line.translate(0, rect().height()/numVerticalSections); |
|
139 painter.drawLine(line); |
|
140 } |
|
141 |
|
142 barColor = barColor.lighter(); |
|
143 barColor.setAlphaF(0.75); |
|
144 clipColor.setAlphaF(0.75); |
|
145 |
|
146 // Draw the bars |
|
147 if (numBars) { |
|
148 // Calculate width of bars and gaps |
|
149 const int widgetWidth = rect().width(); |
|
150 const int barPlusGapWidth = widgetWidth / numBars; |
|
151 const int barWidth = 0.8 * barPlusGapWidth; |
|
152 const int gapWidth = barPlusGapWidth - barWidth; |
|
153 const int paddingWidth = widgetWidth - numBars * (barWidth + gapWidth); |
|
154 const int leftPaddingWidth = (paddingWidth + gapWidth) / 2; |
|
155 const int barHeight = rect().height() - 2 * gapWidth; |
|
156 |
|
157 for (int i=0; i<numBars; ++i) { |
|
158 const qreal value = m_bars[i].value; |
|
159 Q_ASSERT(value >= 0.0 && value <= 1.0); |
|
160 QRect bar = rect(); |
|
161 bar.setLeft(rect().left() + leftPaddingWidth + (i * (gapWidth + barWidth))); |
|
162 bar.setWidth(barWidth); |
|
163 bar.setTop(rect().top() + gapWidth + (1.0 - value) * barHeight); |
|
164 bar.setBottom(rect().bottom() - gapWidth); |
|
165 |
|
166 QColor color = barColor; |
|
167 if (m_bars[i].clipped) |
|
168 color = clipColor; |
|
169 |
|
170 painter.fillRect(bar, color); |
|
171 } |
|
172 } |
|
173 } |
|
174 |
|
175 void Spectrograph::mousePressEvent(QMouseEvent *event) |
|
176 { |
|
177 const QPoint pos = event->pos(); |
|
178 const int index = m_bars.count() * (pos.x() - rect().left()) / rect().width(); |
|
179 selectBar(index); |
|
180 } |
|
181 |
|
182 void Spectrograph::reset() |
|
183 { |
|
184 m_spectrum.reset(); |
|
185 spectrumChanged(m_spectrum); |
|
186 } |
|
187 |
|
188 void Spectrograph::spectrumChanged(const FrequencySpectrum &spectrum) |
|
189 { |
|
190 m_spectrum = spectrum; |
|
191 updateBars(); |
|
192 } |
|
193 |
|
194 int Spectrograph::barIndex(qreal frequency) const |
|
195 { |
|
196 Q_ASSERT(frequency >= m_lowFreq && frequency < m_highFreq); |
|
197 const qreal bandWidth = (m_highFreq - m_lowFreq) / m_bars.count(); |
|
198 const int index = (frequency - m_lowFreq) / bandWidth; |
|
199 if(index <0 || index >= m_bars.count()) |
|
200 Q_ASSERT(false); |
|
201 return index; |
|
202 } |
|
203 |
|
204 QPair<qreal, qreal> Spectrograph::barRange(int index) const |
|
205 { |
|
206 Q_ASSERT(index >= 0 && index < m_bars.count()); |
|
207 const qreal bandWidth = (m_highFreq - m_lowFreq) / m_bars.count(); |
|
208 return QPair<qreal, qreal>(index * bandWidth, (index+1) * bandWidth); |
|
209 } |
|
210 |
|
211 void Spectrograph::updateBars() |
|
212 { |
|
213 m_bars.fill(Bar()); |
|
214 FrequencySpectrum::const_iterator i = m_spectrum.begin(); |
|
215 const FrequencySpectrum::const_iterator end = m_spectrum.end(); |
|
216 for ( ; i != end; ++i) { |
|
217 const FrequencySpectrum::Element e = *i; |
|
218 if (e.frequency >= m_lowFreq && e.frequency < m_highFreq) { |
|
219 Bar &bar = m_bars[barIndex(e.frequency)]; |
|
220 bar.value = qMax(bar.value, e.amplitude); |
|
221 bar.clipped |= e.clipped; |
|
222 } |
|
223 } |
|
224 update(); |
|
225 } |
|
226 |
|
227 void Spectrograph::selectBar(int index) { |
|
228 const QPair<qreal, qreal> frequencyRange = barRange(index); |
|
229 const QString message = QString("%1 - %2 Hz") |
|
230 .arg(frequencyRange.first) |
|
231 .arg(frequencyRange.second); |
|
232 emit infoMessage(message, BarSelectionInterval); |
|
233 |
|
234 if (NullTimerId != m_timerId) |
|
235 killTimer(m_timerId); |
|
236 m_timerId = startTimer(BarSelectionInterval); |
|
237 |
|
238 m_barSelected = index; |
|
239 update(); |
|
240 } |
|
241 |
|
242 |