summaryrefslogtreecommitdiffstats
path: root/sdrbase/gui
diff options
context:
space:
mode:
authorChristian Daniel <cd@maintech.de>2013-09-23 21:31:54 +0200
committerChristian Daniel <cd@maintech.de>2013-09-23 21:31:54 +0200
commit9fd7152f13157f88136a386779919ce57ac59e2b (patch)
tree749ea73a56a062b2893a181d5b99fa5dc766033e /sdrbase/gui
parent69673c7a642ee532d43a40c9cd273c2015323d5e (diff)
major rewrite and changes... far too many to put into individual commits
Diffstat (limited to 'sdrbase/gui')
-rw-r--r--sdrbase/gui/aboutdialog.ui26
-rw-r--r--sdrbase/gui/buttonswitch.cpp21
-rw-r--r--sdrbase/gui/channelwindow.cpp36
-rw-r--r--sdrbase/gui/glscope.cpp16
-rw-r--r--sdrbase/gui/glspectrum.cpp86
-rw-r--r--sdrbase/gui/glspectrumgui.cpp20
-rw-r--r--sdrbase/gui/glspectrumgui.ui27
-rw-r--r--sdrbase/gui/indicator.cpp1
-rw-r--r--sdrbase/gui/preferencesdialog.ui2
-rw-r--r--sdrbase/gui/rollupwidget.cpp231
-rw-r--r--sdrbase/gui/scopewindow.cpp4
-rw-r--r--sdrbase/gui/scopewindow.ui5
12 files changed, 411 insertions, 64 deletions
diff --git a/sdrbase/gui/aboutdialog.ui b/sdrbase/gui/aboutdialog.ui
index ff5a4e4..0e0c182 100644
--- a/sdrbase/gui/aboutdialog.ui
+++ b/sdrbase/gui/aboutdialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>476</width>
- <height>499</height>
+ <width>484</width>
+ <height>503</height>
</rect>
</property>
<property name="windowTitle">
@@ -78,19 +78,15 @@
<item>
<widget class="QLabel" name="label_2">
<property name="text">
- <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
-&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
-p, li { white-space: pre-wrap; }
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:8pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Höchberg, Germany&lt;br /&gt;Written by Christian Daniel.&lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Many thanks to the osmocom developer team - especially horizon, Hoernchen &amp;amp; tnt.&lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;SDRangelove itself is licensed as &amp;quot;GPL2+&amp;quot; with the added exception, that plugins using only header files from the &amp;quot;include&amp;quot;-subdirectory and not from the &amp;quot;include-gpl&amp;quot;-subdirectory do not count as derived works.&lt;/p&gt;
-&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The following rules apply to the SDRangelove main application and libsdrbase:&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;You should have received a copy of the GNU General Public License along with this program. If not, see &lt;a href=&quot;http://www.gnu.org/licenses/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#502878;&quot;&gt;http://www.gnu.org/licenses/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
-&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; text-decoration: underline; color:#502878;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;For the license of installed plugins, look into the plugin list.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ <string>&lt;p&gt;Copyright (C) 2013 maintech GmbH, Otto-Hahn-Str. 15, 97204 Höchberg, Germany&lt;br&gt;
+Written by Christian Daniel.&lt;/p&gt;
+&lt;p&gt;Many thanks to the osmocom developer team - especially horizon, Hoernchen &amp;amp; tnt.&lt;/p&gt;
+&lt;p&gt;SDRangelove itself is licensed as &quot;GPL2+&quot; with the added exception, that plugins using only header files from the &quot;include&quot;-subdirectory and not from the &quot;include-gpl&quot;-subdirectory do not count as derived works.&lt;/p&gt;
+&lt;p&gt;The following rules apply to the SDRangelove main application and libsdrbase:&lt;br&gt;
+This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+You should have received a copy of the GNU General Public License along with this program. If not, see &lt;a href=&quot;http://www.gnu.org/licenses/&quot;&gt;http://www.gnu.org/licenses/&lt;/a&gt;.&lt;/p&gt;
+&lt;p&gt;For the license of installed plugins, look into the plugin list.&lt;/p&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
diff --git a/sdrbase/gui/buttonswitch.cpp b/sdrbase/gui/buttonswitch.cpp
new file mode 100644
index 0000000..88d0bd5
--- /dev/null
+++ b/sdrbase/gui/buttonswitch.cpp
@@ -0,0 +1,21 @@
+#include <QPainter>
+#include "gui/buttonswitch.h"
+
+ButtonSwitch::ButtonSwitch(QWidget* parent) :
+ QToolButton(parent)
+{
+ setCheckable(true);
+ m_originalPalette = palette();
+ connect(this, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool)));
+}
+
+void ButtonSwitch::onToggled(bool checked)
+{
+ if(checked) {
+ QPalette p = m_originalPalette;
+ p.setColor(QPalette::Button, QColor(0x80, 0x46, 0x00));
+ setPalette(p);
+ } else {
+ setPalette(m_originalPalette);
+ }
+}
diff --git a/sdrbase/gui/channelwindow.cpp b/sdrbase/gui/channelwindow.cpp
new file mode 100644
index 0000000..2849bf7
--- /dev/null
+++ b/sdrbase/gui/channelwindow.cpp
@@ -0,0 +1,36 @@
+#include <QBoxLayout>
+#include <QSpacerItem>
+#include <QPainter>
+#include <QResizeEvent>
+#include "gui/channelwindow.h"
+#include "gui/rollupwidget.h"
+
+ChannelWindow::ChannelWindow(QWidget* parent) :
+ QScrollArea(parent)
+{
+ m_container = new QWidget(this);
+ m_layout = new QBoxLayout(QBoxLayout::TopToBottom, m_container);
+ setWidget(m_container);
+ setWidgetResizable(true);
+ setBackgroundRole(QPalette::Base);
+ m_layout->setMargin(3);
+ m_layout->setSpacing(3);
+}
+
+void ChannelWindow::addRollupWidget(QWidget* rollupWidget)
+{
+ rollupWidget->setParent(m_container);
+ m_container->layout()->addWidget(rollupWidget);
+}
+
+void ChannelWindow::resizeEvent(QResizeEvent* event)
+{
+ if(event->size().height() > event->size().width()) {
+ m_layout->setDirection(QBoxLayout::TopToBottom);
+ m_layout->setAlignment(Qt::AlignTop);
+ } else {
+ m_layout->setDirection(QBoxLayout::LeftToRight);
+ m_layout->setAlignment(Qt::AlignLeft);
+ }
+ QScrollArea::resizeEvent(event);
+}
diff --git a/sdrbase/gui/glscope.cpp b/sdrbase/gui/glscope.cpp
index 5f4ebb7..73c0d62 100644
--- a/sdrbase/gui/glscope.cpp
+++ b/sdrbase/gui/glscope.cpp
@@ -419,6 +419,22 @@ void GLScope::handleMode()
}
break;
}
+
+ case ModeCyclostationary: {
+ if(m_rawTrace.size() > 2) {
+ m_mathTrace.resize(m_rawTrace.size() - 2);
+ std::vector<Complex>::iterator dst = m_mathTrace.begin();
+ for(uint i = 2; i < m_rawTrace.size() ; i++)
+ *dst++ = Complex(abs(m_rawTrace[i] - conj(m_rawTrace[i - 1])), 0);
+ m_displayTrace = &m_mathTrace;
+ m_amp1 = m_amp;
+ m_amp2 = m_amp;
+ m_ofs1 = -1.0 / m_amp1;
+ m_ofs2 = 0.0;
+ }
+ break;
+ }
+
}
}
diff --git a/sdrbase/gui/glspectrum.cpp b/sdrbase/gui/glspectrum.cpp
index 912d732..d9e33be 100644
--- a/sdrbase/gui/glspectrum.cpp
+++ b/sdrbase/gui/glspectrum.cpp
@@ -29,8 +29,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) :
m_sampleRate(500000),
m_fftSize(512),
m_invertedWaterfall(false),
- m_displayLiveSpectrum(false),
- m_liveSpectrumChanged(false),
+ m_displayMaxHold(false),
m_leftMarginTextureAllocated(false),
m_frequencyTextureAllocated(false),
m_waterfallBuffer(NULL),
@@ -51,7 +50,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) :
setMinimumSize(200, 200);
- m_waterfallShare = 0.5;
+ m_waterfallShare = 0.66;
for(int i = 0; i <= 239; i++) {
QColor c;
@@ -182,9 +181,9 @@ void GLSpectrum::setInvertedWaterfall(bool inv)
update();
}
-void GLSpectrum::setDisplayLiveSpectrum(bool display)
+void GLSpectrum::setDisplayMaxHold(bool display)
{
- m_displayLiveSpectrum = display;
+ m_displayMaxHold = display;
m_changesPending = true;
stopDrag();
update();
@@ -245,11 +244,6 @@ void GLSpectrum::newSpectrum(const std::vector<Real>& spectrum, int fftSize)
updateWaterfall(spectrum);
updateHistogram(spectrum);
-
- if(!m_liveSpectrumChanged) {
- std::copy(spectrum.begin(), spectrum.begin() + m_fftSize, m_liveSpectrum.begin());
- m_liveSpectrumChanged = true;
- }
}
void GLSpectrum::updateWaterfall(const std::vector<Real>& spectrum)
@@ -440,7 +434,7 @@ void GLSpectrum::paintGL()
}
// paint histogram
- if(m_displayHistogram || m_displayLiveSpectrum) {
+ if(m_displayHistogram || m_displayMaxHold) {
glPushMatrix();
glTranslatef(m_glHistogramRect.x(), m_glHistogramRect.y(), 0);
glScalef(m_glHistogramRect.width(), m_glHistogramRect.height(), 1);
@@ -522,7 +516,7 @@ void GLSpectrum::paintGL()
}
// paint left scales (time and power)
- if(m_displayWaterfall || m_displayLiveSpectrum || m_displayHistogram ) {
+ if(m_displayWaterfall || m_displayMaxHold || m_displayHistogram ) {
glBindTexture(GL_TEXTURE_2D, m_leftMarginTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -549,7 +543,7 @@ void GLSpectrum::paintGL()
}
// paint frequency scale
- if(m_displayWaterfall || m_displayLiveSpectrum || m_displayHistogram ) {
+ if(m_displayWaterfall || m_displayMaxHold || m_displayHistogram ) {
glBindTexture(GL_TEXTURE_2D, m_frequencyTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -575,10 +569,48 @@ void GLSpectrum::paintGL()
glEnd();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
+
+ // paint channels
+ glPushMatrix();
+ glTranslatef(m_glWaterfallRect.x(), m_glFrequencyScaleRect.y(), 0);
+ glScalef(m_glWaterfallRect.width(), m_glFrequencyScaleRect.height(), 1);
+ for(int i = 0; i < m_channelMarkerStates.size(); ++i) {
+ ChannelMarkerState* dv = m_channelMarkerStates[i];
+ if(dv->m_channelMarker->getVisible()) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4f(dv->m_channelMarker->getColor().redF(), dv->m_channelMarker->getColor().greenF(), dv->m_channelMarker->getColor().blueF(), 0.3f);
+ glPushMatrix();
+ glTranslatef(dv->m_glRect.x(), dv->m_glRect.y(), 0);
+ glScalef(dv->m_glRect.width(), dv->m_glRect.height(), 1);
+ glBegin(GL_QUADS);
+ glVertex2f(0, 0);
+ glVertex2f(1, 0);
+ glVertex2f(1, 1);
+ glVertex2f(0, 1);
+ glEnd();
+ glDisable(GL_BLEND);
+ glPopMatrix();
+ }
+ }
+ glPopMatrix();
}
- // paint live spectrum lines on top of histogram
- if(m_displayLiveSpectrum) {
+ // paint max hold lines on top of histogram
+ if(m_displayMaxHold) {
+ if(m_maxHold.size() < m_fftSize)
+ m_maxHold.resize(m_fftSize);
+ for(int i = 0; i < m_fftSize; i++) {
+ int j;
+ quint8* bs = m_histogram + i * 100;
+ for(j = 99; j > 0; j--) {
+ if(bs[j] > 0)
+ break;
+ }
+ j = j - 99;
+ m_maxHold[i] = (j * m_powerRange) / 99.0 + m_referenceLevel;
+ }
+
glPushMatrix();
glTranslatef(m_glHistogramRect.x(), m_glHistogramRect.y(), 0);
glScalef(m_glHistogramRect.width() / (float)(m_fftSize - 1), -m_glHistogramRect.height() / m_powerRange, 1);
@@ -586,11 +618,11 @@ void GLSpectrum::paintGL()
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glLineWidth(1.0f);
- glColor4f(1, 1, 1, 0.75f);
+ glColor3f(1, 0, 0);
Real bottom = -m_powerRange;
glBegin(GL_LINE_STRIP);
for(int i = 0; i < m_fftSize; i++) {
- Real v = m_liveSpectrum[i] - m_referenceLevel;
+ Real v = m_maxHold[i] - m_referenceLevel;
if(v > 0)
v = 0;
else if(v < bottom)
@@ -601,7 +633,6 @@ void GLSpectrum::paintGL()
glDisable(GL_LINE_SMOOTH);
glPopMatrix();
}
- m_liveSpectrumChanged = false;
// paint waterfall grid
if(m_displayWaterfall) {
@@ -649,7 +680,7 @@ void GLSpectrum::paintGL()
}
// paint histogram grid
- if(m_displayHistogram || m_displayLiveSpectrum) {
+ if(m_displayHistogram || m_displayMaxHold) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLineWidth(1.0f);
@@ -718,8 +749,6 @@ void GLSpectrum::applyChanges()
QFontMetrics fm(font());
int M = fm.width("-");
- m_liveSpectrum.resize(m_fftSize);
-
int topMargin = fm.ascent() * 1.5;
int bottomMargin = fm.ascent() * 1.5;
@@ -732,7 +761,7 @@ void GLSpectrum::applyChanges()
int leftMargin;
int rightMargin = fm.width("000");
- if(m_displayWaterfall && (m_displayHistogram | m_displayLiveSpectrum)) {
+ if(m_displayWaterfall && (m_displayHistogram | m_displayMaxHold)) {
waterfallHeight = height() * m_waterfallShare - 1;
if(waterfallHeight < 0)
waterfallHeight = 0;
@@ -848,7 +877,7 @@ void GLSpectrum::applyChanges()
(float)(leftMargin - 1) / (float)width(),
(float)1
);
- } else if(m_displayHistogram || m_displayLiveSpectrum) {
+ } else if(m_displayHistogram || m_displayMaxHold) {
bottomMargin = frequencyScaleHeight;
frequencyScaleTop = height() - bottomMargin;
histogramTop = topMargin - 1;
@@ -902,7 +931,7 @@ void GLSpectrum::applyChanges()
0,
(dv->m_channelMarker->getBandwidth() / (float)m_sampleRate),
1);
- if(m_displayHistogram || m_displayLiveSpectrum || m_displayWaterfall) {
+ if(m_displayHistogram || m_displayMaxHold || m_displayWaterfall) {
dv->m_rect.setRect(m_frequencyScale.getPosFromValue(m_centerFrequency + dv->m_channelMarker->getCenterFrequency()) + leftMargin - 1,
topMargin,
5,
@@ -929,7 +958,7 @@ void GLSpectrum::applyChanges()
}
}
}
- if(m_displayHistogram || m_displayLiveSpectrum) {
+ if(m_displayHistogram || m_displayMaxHold) {
tickList = &m_powerScale.getTickList();
for(int i = 0; i < tickList->count(); i++) {
tick = &(*tickList)[i];
@@ -950,13 +979,14 @@ void GLSpectrum::applyChanges()
m_leftMarginTextureAllocated = true;
}
// prepare frequency scale
- if(m_displayWaterfall || m_displayHistogram || m_displayLiveSpectrum){
+ if(m_displayWaterfall || m_displayHistogram || m_displayMaxHold){
m_frequencyPixmap = QPixmap(width(), frequencyScaleHeight);
m_frequencyPixmap.fill(Qt::transparent);
{
QPainter painter(&m_frequencyPixmap);
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::black);
+ painter.setBrush(Qt::transparent);
painter.drawRect(leftMargin, 0, width() - leftMargin, frequencyScaleHeight);
painter.setPen(QColor(0xf0, 0xf0, 0xff));
const ScaleEngine::TickList* tickList = &m_frequencyScale.getTickList();
@@ -1056,7 +1086,7 @@ void GLSpectrum::applyChanges()
void GLSpectrum::mouseMoveEvent(QMouseEvent* event)
{
- if(m_displayWaterfall && (m_displayWaterfall || m_displayHistogram || m_displayLiveSpectrum)) {
+ if(m_displayWaterfall && (m_displayWaterfall || m_displayHistogram || m_displayMaxHold)) {
if(m_frequencyScaleRect.contains(event->pos())) {
if(m_cursorState == CSNormal) {
setCursor(Qt::SizeVerCursor);
@@ -1090,7 +1120,7 @@ void GLSpectrum::mouseMoveEvent(QMouseEvent* event)
m_channelMarkerStates[m_cursorChannel]->m_channelMarker->setCenterFrequency(freq);
}
- if(m_displayWaterfall || m_displayHistogram || m_displayLiveSpectrum) {
+ if(m_displayWaterfall || m_displayHistogram || m_displayMaxHold) {
for(int i = 0; i < m_channelMarkerStates.size(); ++i) {
if(m_channelMarkerStates[i]->m_rect.contains(event->pos())) {
if(m_cursorState == CSNormal) {
diff --git a/sdrbase/gui/glspectrumgui.cpp b/sdrbase/gui/glspectrumgui.cpp
index 6feaffd..52dd40d 100644
--- a/sdrbase/gui/glspectrumgui.cpp
+++ b/sdrbase/gui/glspectrumgui.cpp
@@ -2,8 +2,8 @@
#include "dsp/fftwindow.h"
#include "dsp/spectrumvis.h"
#include "gui/glspectrum.h"
-#include "ui_glspectrumgui.h"
#include "util/simpleserializer.h"
+#include "ui_glspectrumgui.h"
GLSpectrumGUI::GLSpectrumGUI(QWidget* parent) :
QWidget(parent),
@@ -18,7 +18,7 @@ GLSpectrumGUI::GLSpectrumGUI(QWidget* parent) :
m_powerRange(100),
m_displayWaterfall(true),
m_invertedWaterfall(false),
- m_displayLiveSpectrum(false),
+ m_displayMaxHold(false),
m_displayHistogram(true)
{
ui->setupUi(this);
@@ -46,7 +46,7 @@ void GLSpectrumGUI::resetToDefaults()
m_powerRange = 100;
m_displayWaterfall = true;
m_invertedWaterfall = false;
- m_displayLiveSpectrum = false;
+ m_displayMaxHold = false;
m_displayHistogram = true;
applySettings();
}
@@ -61,7 +61,7 @@ QByteArray GLSpectrumGUI::serialize() const
s.writeReal(5, m_powerRange);
s.writeBool(6, m_displayWaterfall);
s.writeBool(7, m_invertedWaterfall);
- s.writeBool(8, m_displayLiveSpectrum);
+ s.writeBool(8, m_displayMaxHold);
s.writeBool(9, m_displayHistogram);
return s.final();
}
@@ -83,7 +83,7 @@ bool GLSpectrumGUI::deserialize(const QByteArray& data)
d.readReal(5, &m_powerRange, 100);
d.readBool(6, &m_displayWaterfall, true);
d.readBool(7, &m_invertedWaterfall, false);
- d.readBool(8, &m_displayLiveSpectrum, false);
+ d.readBool(8, &m_displayMaxHold, false);
d.readBool(9, &m_displayHistogram, true);
applySettings();
return true;
@@ -105,8 +105,8 @@ void GLSpectrumGUI::applySettings()
ui->waterfall->setChecked(m_displayWaterfall);
m_glSpectrum->setDisplayWaterfall(m_displayWaterfall);
m_glSpectrum->setInvertedWaterfall(m_invertedWaterfall);
- ui->liveSpectrum->setChecked(m_displayLiveSpectrum);
- m_glSpectrum->setDisplayLiveSpectrum(m_displayLiveSpectrum);
+ ui->maxHold->setChecked(m_displayMaxHold);
+ m_glSpectrum->setDisplayMaxHold(m_displayMaxHold);
ui->histogram->setChecked(m_displayHistogram);
m_glSpectrum->setDisplayHistogram(m_displayHistogram);
ui->refLevel->setValue((int)(m_refLevel / 10.0));
@@ -158,8 +158,8 @@ void GLSpectrumGUI::on_histogram_toggled(bool checked)
m_glSpectrum->setDisplayHistogram(m_displayHistogram);
}
-void GLSpectrumGUI::on_liveSpectrum_toggled(bool checked)
+void GLSpectrumGUI::on_maxHold_toggled(bool checked)
{
- m_displayLiveSpectrum = checked;
- m_glSpectrum->setDisplayLiveSpectrum(m_displayLiveSpectrum);
+ m_displayMaxHold = checked;
+ m_glSpectrum->setDisplayMaxHold(m_displayMaxHold);
}
diff --git a/sdrbase/gui/glspectrumgui.ui b/sdrbase/gui/glspectrumgui.ui
index 5c67ba6..048b3f6 100644
--- a/sdrbase/gui/glspectrumgui.ui
+++ b/sdrbase/gui/glspectrumgui.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>203</width>
- <height>136</height>
+ <height>137</height>
</rect>
</property>
<property name="windowTitle">
@@ -48,7 +48,7 @@
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
- <enum>QSlider::TicksAbove</enum>
+ <enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>1</number>
@@ -85,7 +85,7 @@
</widget>
</item>
<item row="1" column="4">
- <widget class="QToolButton" name="waterfall">
+ <widget class="ButtonSwitch" name="waterfall">
<property name="minimumSize">
<size>
<width>24</width>
@@ -144,7 +144,7 @@
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
- <enum>QSlider::TicksAbove</enum>
+ <enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>1</number>
@@ -174,7 +174,7 @@
</widget>
</item>
<item row="2" column="4">
- <widget class="QToolButton" name="histogram">
+ <widget class="ButtonSwitch" name="histogram">
<property name="minimumSize">
<size>
<width>24</width>
@@ -233,7 +233,7 @@
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
- <enum>QSlider::TicksAbove</enum>
+ <enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>10</number>
@@ -263,7 +263,7 @@
</widget>
</item>
<item row="3" column="4">
- <widget class="QToolButton" name="liveSpectrum">
+ <widget class="ButtonSwitch" name="maxHold">
<property name="minimumSize">
<size>
<width>24</width>
@@ -278,7 +278,7 @@
</property>
<property name="icon">
<iconset resource="../resources/res.qrc">
- <normaloff>:/livespectrum.png</normaloff>:/livespectrum.png</iconset>
+ <normaloff>:/maxhold.png</normaloff>:/maxhold.png</iconset>
</property>
<property name="iconSize">
<size>
@@ -390,7 +390,7 @@
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
- <enum>QSlider::TicksAbove</enum>
+ <enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>1</number>
@@ -401,6 +401,13 @@
</item>
</layout>
</widget>
+ <customwidgets>
+ <customwidget>
+ <class>ButtonSwitch</class>
+ <extends>QToolButton</extends>
+ <header>gui/buttonswitch.h</header>
+ </customwidget>
+ </customwidgets>
<tabstops>
<tabstop>fftSize</tabstop>
<tabstop>fftWindow</tabstop>
@@ -409,7 +416,7 @@
<tabstop>decay</tabstop>
<tabstop>waterfall</tabstop>
<tabstop>histogram</tabstop>
- <tabstop>liveSpectrum</tabstop>
+ <tabstop>maxHold</tabstop>
</tabstops>
<resources>
<include location="../resources/res.qrc"/>
diff --git a/sdrbase/gui/indicator.cpp b/sdrbase/gui/indicator.cpp
index 184197d..d303578 100644
--- a/sdrbase/gui/indicator.cpp
+++ b/sdrbase/gui/indicator.cpp
@@ -42,6 +42,7 @@ Indicator::Indicator(const QString& text, QWidget* parent) :
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QFont f = font();
+ f.setBold(true);
f.setPixelSize(8);
setFont(f);
}
diff --git a/sdrbase/gui/preferencesdialog.ui b/sdrbase/gui/preferencesdialog.ui
index 69f5d7d..0545931 100644
--- a/sdrbase/gui/preferencesdialog.ui
+++ b/sdrbase/gui/preferencesdialog.ui
@@ -17,7 +17,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
- <number>1</number>
+ <number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
diff --git a/sdrbase/gui/rollupwidget.cpp b/sdrbase/gui/rollupwidget.cpp
new file mode 100644
index 0000000..010c88c
--- /dev/null
+++ b/sdrbase/gui/rollupwidget.cpp
@@ -0,0 +1,231 @@
+#include <QEvent>
+#include <QPainter>
+#include <QMouseEvent>
+#include "gui/rollupwidget.h"
+#include "ui_glspectrumgui.h"
+
+RollupWidget::RollupWidget(QWidget* parent) :
+ QWidget(parent)
+{
+ setMinimumSize(250, 150);
+ setMaximumSize(400, 200);
+ setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+ setBackgroundRole(QPalette::Window);
+
+ setAutoFillBackground(false);
+ setAttribute(Qt::WA_OpaquePaintEvent, true);
+}
+
+void RollupWidget::addRollup(QWidget* rollup)
+{
+ rollup->setParent(this);
+ installEventFilter(rollup);
+ arrangeRollups();
+ repaint();
+}
+
+int RollupWidget::arrangeRollups()
+{
+ QFontMetrics fm(font());
+ int pos = fm.height() + 4;
+
+ for(int i = 0; i < children().count(); ++i) {
+ pos += fm.height() + 2;
+ QWidget* r = qobject_cast<QWidget*>(children()[i]);
+ if(r != NULL) {
+ if(!r->isHidden()) {
+ r->move(2, pos + 3);
+ int h = 0;
+ if(r->hasHeightForWidth())
+ h = r->heightForWidth(width() - 4);
+ else h = r->sizeHint().height();
+ r->resize(width() - 4, h);
+ pos += r->height() + 5;
+ }
+ }
+ }
+ setMinimumHeight(pos);
+ setMaximumHeight(pos);
+ return pos;
+}
+
+void RollupWidget::paintEvent(QPaintEvent*)
+{
+ QPainter p(this);
+ QColor frame = palette().highlight().color();
+
+ // Eigenbau
+ QFontMetrics fm(font());
+
+ p.setRenderHint(QPainter::Antialiasing, true);
+
+ // Ecken
+ p.setPen(Qt::NoPen);
+ p.setBrush(palette().base());
+ p.drawRect(0, 0, 5, 5);
+ p.drawRect(width() - 5, 0, 5, 5);
+ p.drawRect(0, height() - 5, 5, 5);
+ p.drawRect(width() - 5, height() - 5, 5, 5);
+
+ // Rahmen
+ p.setPen(frame);
+ p.setBrush(palette().window());
+ QRectF r(rect());
+ r.adjust(0.5, 0.5, -0.5, -0.5);
+ p.drawRoundedRect(r, 3.0, 3.0, Qt::AbsoluteSize);
+
+ // Titel-Hintergrund
+ p.setPen(Qt::NoPen);
+ p.setBrush(palette().highlight());
+ QPainterPath path;
+ path.moveTo(1.5, fm.height() + 2.5);
+ path.lineTo(width() - 1.5, fm.height() + 2.5);
+ path.lineTo(width() - 1.5, 3.5);
+ path.arcTo(QRectF(width() - 3.5, 0, 2.5, 2.5), 270, -90);
+ path.lineTo(3.5, 1.5);
+ path.arcTo(QRectF(1.5, 2.5, 2.5, 2.5), 90, 90);
+ p.drawPath(path);
+
+ // Titel-Abschlusslinie
+ p.setPen(frame);
+ p.drawLine(QPointF(0.5, 2 + fm.height() + 1.5), QPointF(width() - 1.5, 2 + fm.height() + 1.5));
+
+ // Aktiv-Button links
+ p.setPen(QPen(palette().windowText().color(), 1.0));
+ p.setBrush(palette().light());
+ p.drawRoundedRect(QRectF(3.5, 3.5, fm.ascent(), fm.ascent()), 2.0, 2.0, Qt::AbsoluteSize);
+
+ // Schließen-Button rechts
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.setPen(QPen(palette().windowText().color(), 1.0));
+ p.setBrush(palette().light());
+ r = QRectF(width() - 3.5 - fm.ascent(), 3.5, fm.ascent(), fm.ascent());
+ p.drawRoundedRect(r, 2.0, 2.0, Qt::AbsoluteSize);
+ p.setPen(QPen(palette().windowText().color(), 1.5));
+ p.drawLine(r.topLeft() + QPointF(1, 1), r.bottomRight() + QPointF(-1, -1));
+ p.drawLine(r.bottomLeft() + QPointF(1, -1), r.topRight() + QPointF(-1, 1));
+
+ // Titel
+ p.setPen(palette().highlightedText().color());
+ p.drawText(QRect(2 + fm.height(), 2, width() - 4 - 2 * fm.height(), fm.height()),
+ fm.elidedText(windowTitle(), Qt::ElideMiddle, width() - 4 - 2 * fm.height(), 0));
+
+ // Rollups
+ int pos = fm.height() + 4;
+ for(int i = 0; i < children().count(); ++i) {
+ QWidget* r = qobject_cast<QWidget*>(children()[i]);
+ if(r != NULL)
+ pos += paintRollup(r, pos, &p, i == children().count() - 1, frame);
+ }
+}
+
+int RollupWidget::paintRollup(QWidget* rollup, int pos, QPainter* p, bool last, const QColor& frame)
+{
+ QFontMetrics fm(font());
+ int height = 1;
+
+ // Titel-Abschlusslinie
+ if(!rollup->isHidden()) {
+ p->setPen(palette().dark().color());
+ p->drawLine(QPointF(1.5, pos + fm.height() + 1.5), QPointF(width() - 1.5, pos + fm.height() + 1.5));
+ p->setPen(palette().light().color());
+ p->drawLine(QPointF(1.5, pos + fm.height() + 2.5), QPointF(width() - 1.5, pos + fm.height() + 2.5));
+ height += 2;
+ } else {
+ if(!last) {
+ p->setPen(frame);
+ p->drawLine(QPointF(1.5, pos + fm.height() + 1.5), QPointF(width() - 1.5, pos + fm.height() + 1.5));
+ height++;
+ }
+ }
+
+ // Titel
+ p->setPen(palette().windowText().color());
+ p->drawText(QRect(2 + fm.height(), pos, width() - 4 - fm.height(), fm.height()),
+ fm.elidedText(rollup->windowTitle(), Qt::ElideMiddle, width() - 4 - fm.height(), 0));
+ height += fm.height();
+
+ // Ausklapp-Icon
+ p->setPen(palette().windowText().color());
+ p->setBrush(palette().windowText());
+ if(!rollup->isHidden()) {
+ QPolygonF a;
+ a.append(QPointF(3.5, pos + 2));
+ a.append(QPointF(3.5 + fm.ascent(), pos + 2));
+ a.append(QPointF(3.5 + fm.ascent() / 2.0, pos + fm.height() - 2));
+ p->drawPolygon(a);
+ } else {
+ QPolygonF a;
+ a.append(QPointF(3.5, pos + 2));
+ a.append(QPointF(3.5, pos + fm.height() - 2));
+ a.append(QPointF(3.5 + fm.ascent(), pos + fm.height() / 2));
+ p->drawPolygon(a);
+ }
+
+ // Inhalt
+ if(!rollup->isHidden() && (!last)) {
+ // Rollup-Abschlusslinie
+ p->setPen(frame);
+ p->drawLine(QPointF(1.5, pos + fm.height() + rollup->height() + 6.5),
+ QPointF(width() - 1.5, pos + fm.height() + rollup->height() + 6.5));
+ height += rollup->height() + 4;
+ }
+
+ return height;
+}
+
+void RollupWidget::resizeEvent(QResizeEvent* size)
+{
+ arrangeRollups();
+ QWidget::resizeEvent(size);
+}
+
+void RollupWidget::mousePressEvent(QMouseEvent* event)
+{
+ QFontMetrics fm(font());
+
+ // menu box left
+ if(QRectF(3.5, 3.5, fm.ascent(), fm.ascent()).contains(event->pos())) {
+ emit customContextMenuRequested(event->pos());
+ return;
+ }
+
+ // close button right
+ if(QRectF(width() - 3.5 - fm.ascent(), 3.5, fm.ascent(), fm.ascent()).contains(event->pos())) {
+ close();
+ return;
+ }
+
+ // check if we need to change a rollup widget
+ int pos = fm.height() + 4;
+ for(int i = 0; i < children().count(); ++i) {
+ QWidget* r = qobject_cast<QWidget*>(children()[i]);
+ if(r != NULL) {
+ if((event->y() >= pos) && (event->y() < (pos + fm.height() + 3))) {
+ if(r->isHidden())
+ r->show();
+ else r->hide();
+ arrangeRollups();
+ repaint();
+ return;
+ } else {
+ pos += fm.height() + 2;
+ if(!r->isHidden())
+ pos += r->height() + 5;
+ }
+ }
+ }
+}
+
+bool RollupWidget::eventFilter(QObject* object, QEvent* event)
+{
+ if((event->type() == QEvent::Show) || (event->type() == QEvent::Hide)) {
+ if(children().contains(object))
+ arrangeRollups();
+ } else if((event->type() == QEvent::ChildAdded) || (event->type() == QEvent::ChildRemoved)) {
+ if(children().contains(object))
+ arrangeRollups();
+ }
+
+ return QWidget::eventFilter(object, event);
+}
diff --git a/sdrbase/gui/scopewindow.cpp b/sdrbase/gui/scopewindow.cpp
index 6188b64..2f6200f 100644
--- a/sdrbase/gui/scopewindow.cpp
+++ b/sdrbase/gui/scopewindow.cpp
@@ -135,6 +135,10 @@ void ScopeWindow::on_displayMode_currentIndexChanged(int index)
case 3: // derived1+derived2
ui->scope->setMode(GLScope::ModeDerived12);
break;
+ case 4: // clostationary
+ ui->scope->setMode(GLScope::ModeCyclostationary);
+ break;
+
default:
break;
}
diff --git a/sdrbase/gui/scopewindow.ui b/sdrbase/gui/scopewindow.ui
index a2c7ffd..d521af3 100644
--- a/sdrbase/gui/scopewindow.ui
+++ b/sdrbase/gui/scopewindow.ui
@@ -82,6 +82,11 @@
<string>Derived 1st + 2nd order</string>
</property>
</item>
+ <item>
+ <property name="text">
+ <string>Cyclostationary</string>
+ </property>
+ </item>
</widget>
</item>
<item>