Make the main window more portable and font change capable

The Rx meter  is now a better  Qt citizen and can be  resized. Added a
more obvious peak signal indicator. It  is now a custom widget derived
from QFrame and is now directly added via promotion in Designer.

Added a custom  widget to act as  a letter spin box, this  is used for
sub mode control.  Switched the frequency tolerance widget  to a combo
box with preset  values so that it is more  uniform across systems and
font sizes.

Added container widgets  for group control of various  UI widgets such
as  QSO controls,  DX call  controls and  WSPR controls.  Introduced a
stacked widget to allow the WSPR controls to be swapped in in place of
the "QSO" controls. The "QSO" controls  are are the Rx, Tx and related
controls along with  the main tab widget with the  message buttons and
fields. This means  that the WSPR version of the  main window (and EME
Echo mode) are now much cleaner.

Increased the  size of the  rig control  widget and styled  its colour
using a dynamic property so that it  can be defined in the Designer UI
definition. Reinstated it  as a push button to do  a rig control reset
and retry after an error.

Reset most UI widgets to default properties, particularly removing any
fixed sizes so that they can resize freely when fonts are changed. The
overall layout is now controlled almost exclusively by stretch factors
on some of the rows and columns of the various grid layout managers.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@5630 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2015-06-25 22:41:13 +00:00
parent 61f76d6b46
commit 3dd824ad6b
13 changed files with 1950 additions and 2296 deletions

View File

@ -206,6 +206,8 @@ set (wsjt_qt_CXXSRCS
DXLabSuiteCommanderTransceiver.cpp
NetworkMessage.cpp
MessageClient.cpp
LettersSpinBox.cpp
HelpTextWindow.cpp
)
set (jt9_CXXSRCS

View File

@ -2465,6 +2465,10 @@ void Configuration::impl::update_audio_channels (QComboBox const * source_combo_
void Configuration::impl::set_application_font (QFont const& font)
{
qApp->setStyleSheet (qApp->styleSheet () + "* {" + font_as_stylesheet (font) + '}');
for (auto& widget : qApp->topLevelWidgets ())
{
widget->updateGeometry ();
}
}
// load all the supported rig names into the selection combo box

29
HelpTextWindow.cpp Normal file
View File

@ -0,0 +1,29 @@
#include "HelpTextWindow.hpp"
#include <QApplication>
#include <QString>
#include <QPalette>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include "qt_helpers.hpp"
HelpTextWindow::HelpTextWindow (QString const& title, QString const& file_name, QFont const& font, QWidget * parent)
: QLabel {parent, Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint}
{
QFile source {file_name};
if (!source.open (QIODevice::ReadOnly | QIODevice::Text))
{
QMessageBox::warning (this, QApplication::applicationName ()
, "Cannot open \"" + source.fileName ()
+ "\" for reading:" + source.errorString ());
return;
}
setText (QTextStream {&source}.readAll ());
setWindowTitle(QApplication::applicationName () + " - " + title);
setMargin (10);
setBackgroundRole (QPalette::Base);
setAutoFillBackground (true);
setStyleSheet (font_as_stylesheet (font));
}

16
HelpTextWindow.hpp Normal file
View File

@ -0,0 +1,16 @@
#ifndef HELP_TEXT_WINDOW_HPP__
#define HELP_TEXT_WINDOW_HPP__
#include <QLabel>
#include <QFont>
class QString;
class HelpTextWindow final
: public QLabel
{
public:
HelpTextWindow (QString const& title, QString const& file_name, QFont const& = QFont {}, QWidget * parent = nullptr);
};
#endif

27
LettersSpinBox.cpp Normal file
View File

@ -0,0 +1,27 @@
#include "LettersSpinBox.hpp"
#include <QString>
#include "moc_LettersSpinBox.cpp"
QString LettersSpinBox::textFromValue (int value) const
{
QString text;
do
{
auto digit = value % 26;
value /= 26;
text = QChar {lowercase_ ? 'a' + digit : 'A' + digit} + text;
} while (value);
return text;
}
int LettersSpinBox::valueFromText (QString const& text) const
{
int value {0};
for (int index = text.size (); index > 0; --index)
{
value = value * 26 + text[index - 1].toLatin1 () - (lowercase_ ? 'a' : 'A');
};
return value;
}

31
LettersSpinBox.hpp Normal file
View File

@ -0,0 +1,31 @@
#ifndef LETTERS_SPIN_BOX_HPP_
#define LETTERS_SPIN_BOX_HPP_
#include <QSpinBox>
class QString;
//
// LettersSpinBox - select from consecutive letters
//
class LettersSpinBox final
: public QSpinBox
{
Q_OBJECT
Q_PROPERTY (bool lowercase MEMBER lowercase_)
public:
LettersSpinBox (QWidget * parent = nullptr)
: QSpinBox {parent}
, lowercase_ {false}
{
}
QString textFromValue (int) const override;
int valueFromText (QString const&) const override;
private:
bool lowercase_;
};
#endif

View File

@ -16,6 +16,7 @@
#include <QtConcurrent/QtConcurrentRun>
#include <QProgressDialog>
#include <QHostInfo>
#include <QVector>
#include "revision_utils.hpp"
#include "qt_helpers.hpp"
@ -38,6 +39,8 @@
#include "LiveFrequencyValidator.hpp"
#include "MessageClient.hpp"
#include "wsprnet.h"
#include "signalmeter.h"
#include "HelpTextWindow.hpp"
#include "ui_mainwindow.h"
#include "moc_mainwindow.cpp"
@ -64,32 +67,6 @@ namespace
}
}
class HelpTextWindow
: public QLabel
{
public:
HelpTextWindow (QString const& title, QString const& file_name, QFont const& = QFont {}, QWidget * parent = nullptr);
};
HelpTextWindow::HelpTextWindow (QString const& title, QString const& file_name, QFont const& font, QWidget * parent)
: QLabel {parent, Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint}
{
QFile source {file_name};
if (!source.open (QIODevice::ReadOnly | QIODevice::Text))
{
QMessageBox::warning (this, QApplication::applicationName ()
, "Cannot open \"" + source.fileName ()
+ "\" for reading:" + source.errorString ());
return;
}
setText (QTextStream {&source}.readAll ());
setWindowTitle(QApplication::applicationName () + " - " + title);
setMargin (10);
setBackgroundRole (QPalette::Base);
setAutoFillBackground (true);
setStyleSheet (font_as_stylesheet (font));
}
//--------------------------------------------------- MainWindow constructor
MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdmem,
unsigned downSampleFactor, QWidget *parent) :
@ -346,12 +323,6 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
, &QLineEdit::editingFinished
, [this] () {on_freeTextMsg_currentTextChanged (ui->freeTextMsg->lineEdit ()->text ());});
auto font = ui->readFreq->font();
font.setFamily("helvetica");
font.setPointSize(9);
font.setWeight(75);
ui->readFreq->setFont(font);
connect(&m_guiTimer, &QTimer::timeout, this, &MainWindow::guiUpdate);
m_guiTimer.start(100); //### Don't change the 100 ms! ###
@ -424,14 +395,12 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
m_lockTxFreq=false;
m_baseCall = Radio::base_callsign (m_config.my_callsign ());
ui->readFreq->setEnabled(false);
m_QSOText.clear();
decodeBusy(false);
m_MinW=0;
m_nSubMode=0;
m_tol=500;
m_DTtol=0.5;
m_wideGraph->setTol(m_tol);
m_wideGraph->setTol(500);
m_bShMsgs=false;
m_bTxTime=false;
m_rxDone=false;
@ -441,9 +410,6 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
m_bEchoTxed=false;
m_nWSPRdecodes=0;
signalMeter = new SignalMeter(ui->meterFrame);
signalMeter->resize(50, 160);
for(int i=0; i<28; i++) { //Initialize dBm values
float dbm=(10.0*i)/3.0 - 30.0;
int ndbm=0;
@ -571,16 +537,6 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
on_monitorButton_clicked (!m_config.monitor_off_at_startup ());
if(m_mode=="Echo") monitor(false); //Don't auto-start Monitor in Echo mode.
ui->labTol->setStyleSheet( \
"QLabel { background-color : white; color : black; }");
ui->labTol->setFrameStyle(QFrame::Panel | QFrame::Sunken);
ui->labMinW->setStyleSheet( \
"QLabel { background-color : white; color : black; }");
ui->labMinW->setFrameStyle(QFrame::Panel | QFrame::Sunken);
ui->labSubmode->setStyleSheet( \
"QLabel { background-color : white; color : black; }");
ui->labSubmode->setFrameStyle(QFrame::Panel | QFrame::Sunken);
bool b=m_config.enable_VHF_features() and (m_mode=="JT4" or m_mode=="JT65");
VHF_controls_visible(b);
@ -652,7 +608,7 @@ void MainWindow::writeSettings()
m_settings->setValue("minW",ui->sbMinW->value());
m_settings->setValue("SubMode",ui->sbSubmode->value());
m_settings->setValue("DTtol",m_DTtol);
m_settings->setValue("Ftol",ui->sbTol->value());
m_settings->setValue("FTol",ui->FTol_combo_box->currentText());
m_settings->setValue("MinSync",m_minSync);
m_settings->setValue("EME",m_bEME);
m_settings->setValue ("DialFreq", QVariant::fromValue(m_lastMonitoredFrequency));
@ -706,7 +662,7 @@ void MainWindow::readSettings()
ui->sbMinW->setMaximum(m_nSubMode);
m_DTtol=m_settings->value("DTtol",0.5).toFloat();
ui->sbDT->setValue(m_DTtol);
ui->sbTol->setValue(m_settings->value("Ftol",4).toInt());
ui->FTol_combo_box->setCurrentText(m_settings->value("FTol","500").toString ());
ui->syncSpinBox->setValue(m_settings->value("MinSync",0).toInt());
m_bEME=m_settings->value("EME",false).toBool();
ui->cbEME->setChecked(m_bEME);
@ -770,6 +726,7 @@ void MainWindow::setDecodedTextFont (QFont const& font)
auto style_sheet = "QLabel {" + font_as_stylesheet (font) + '}';
ui->decodedTextLabel->setStyleSheet (ui->decodedTextLabel->styleSheet () + style_sheet);
ui->decodedTextLabel2->setStyleSheet (ui->decodedTextLabel2->styleSheet () + style_sheet);
updateGeometry ();
}
//-------------------------------------------------------------- dataSink()
@ -802,7 +759,7 @@ void MainWindow::dataSink(qint64 frames)
QString t;
m_pctZap=nzap*100.0/m_nsps;
t.sprintf(" Rx noise: %5.1f ",px);
signalMeter->setValue(px); // Update thermometer
ui->signal_meter_widget->setValue(px); // Update thermometer
if(m_monitoring || m_diskData) {
m_wideGraph->dataSink2(s,df3,ihsym,m_diskData);
}
@ -921,9 +878,6 @@ void MainWindow::showStatusMessage(const QString& statusMsg)
void MainWindow::on_actionSettings_triggered() //Setup Dialog
{
ui->readFreq->setStyleSheet("");
ui->readFreq->setEnabled(false);
// things that might change that we need know about
auto callsign = m_config.my_callsign ();
@ -1554,8 +1508,8 @@ void MainWindow::decode() //decode()
jt9com_.nfSplit=m_wideGraph->Fmin();
jt9com_.nfb=m_wideGraph->Fmax();
if(m_mode=="JT9" or m_mode=="JT9+JT65" or
(m_mode=="JT65" and !m_config.enable_VHF_features())) m_tol=20;
jt9com_.ntol=m_tol;
(m_mode=="JT65" and !m_config.enable_VHF_features())) ui->FTol_combo_box->setCurrentText ("20");
jt9com_.ntol=ui->FTol_combo_box->currentText ().toInt ();
if(jt9com_.nutc < m_nutc0) m_RxLog = 1; //Date and Time to all.txt
m_nutc0=jt9com_.nutc;
jt9com_.ntxmode=9;
@ -2173,7 +2127,7 @@ void MainWindow::guiUpdate()
t.time().toString() + " ";
ui->labUTC->setText(utc);
if(!m_monitoring and !m_diskData) {
signalMeter->setValue(0);
ui->signal_meter_widget->setValue(0);
}
m_sec0=nsec;
}
@ -2195,7 +2149,7 @@ void MainWindow::startTx2()
if(t.mid(0,1)=="#") snr=t.mid(1,5).toDouble();
if(snr>0.0 or snr < -50.0) snr=99.0;
transmit (snr);
signalMeter->setValue(0);
ui->signal_meter_widget->setValue(0);
if(m_mode=="Echo" and !m_tune) m_bTransmittedEcho=true;
if(m_mode.mid(0,4)=="WSPR" and !m_tune) {
@ -3149,7 +3103,6 @@ void MainWindow::on_actionWSPR_2_triggered()
m_wideGraph->setPeriod(m_TRperiod,m_nsps);
m_wideGraph->setMode(m_mode);
m_wideGraph->setModeTx(m_modeTx);
VHF_controls_visible(false);
WSPR_config(true);
}
@ -3204,26 +3157,13 @@ void MainWindow::WSPR_config(bool b)
{
ui->decodedTextBrowser2->setVisible(!b);
ui->decodedTextLabel2->setVisible(!b);
ui->controls_stack_widget->setCurrentIndex (b && m_mode != "Echo" ? 1 : 0);
ui->QSO_controls_widget->setVisible (!b);
ui->DX_controls_widget->setVisible (!b);
ui->WSPR_controls_widget->setVisible (b);
ui->label_6->setVisible(!b);
ui->label_7->setVisible(!b);
ui->pbTxMode->setVisible(!b);
ui->TxFreqSpinBox->setVisible(!b);
ui->RxFreqSpinBox->setVisible(!b);
ui->cbTxLock->setVisible(!b);
ui->txFirstCheckBox->setVisible(!b);
ui->pbR2T->setVisible(!b);
ui->pbT2R->setVisible(!b);
ui->rptSpinBox->setVisible(!b);
ui->label_8->setVisible(!b);
ui->labAz->setVisible(!b);
ui->labDist->setVisible(!b);
ui->logQSOButton->setVisible(!b);
ui->label_3->setVisible(!b);
ui->label_4->setVisible(!b);
ui->dxCallEntry->setVisible(!b);
ui->dxGridEntry->setVisible(!b);
ui->lookupButton->setVisible(!b);
ui->addButton->setVisible(!b);
ui->DecodeButton->setEnabled(!b);
if(b and (m_mode!="Echo")) {
ui->decodedTextLabel->setText(
@ -3238,6 +3178,7 @@ void MainWindow::WSPR_config(bool b)
ui->tabWidget->setCurrentIndex (m_nonWSPRTab >= 0 ? m_nonWSPRTab : 1);
m_bSimplex = false;
}
updateGeometry ();
}
void MainWindow::on_TxFreqSpinBox_valueChanged(int n)
@ -3547,12 +3488,11 @@ void MainWindow::on_stopTxButton_clicked() //Stop Tx
void MainWindow::rigOpen ()
{
ui->readFreq->setStyleSheet ("");
update_dynamic_property (ui->readFreq, "state", "warning");
ui->readFreq->setText ("");
ui->readFreq->setEnabled (true);
m_config.transceiver_online (true);
Q_EMIT m_config.sync_transceiver (true);
ui->readFreq->setStyleSheet("QPushButton{background-color: orange;"
"border-width: 0px; border-radius: 5px;}");
}
void MainWindow::on_pbR2T_clicked()
@ -3648,15 +3588,15 @@ void MainWindow::handle_transceiver_update (Transceiver::TransceiverState s)
qsy (s.frequency ());
}
ui->readFreq->setStyleSheet("QPushButton{background-color: #00ff00;"
"border-width: 0px; border-radius: 5px;}");
update_dynamic_property (ui->readFreq, "state", "ok");
ui->readFreq->setEnabled (false);
ui->readFreq->setText (s.split () ? "S" : "");
}
void MainWindow::handle_transceiver_failure (QString reason)
{
ui->readFreq->setStyleSheet("QPushButton{background-color: red;"
"border-width: 0px; border-radius: 5px;}");
update_dynamic_property (ui->readFreq, "state", "error");
ui->readFreq->setEnabled (true);
on_stopTxButton_clicked ();
rigFailure ("Rig Control Error", reason);
}
@ -3846,7 +3786,7 @@ void MainWindow::transmitDisplay (bool transmitting)
if (transmitting == m_transmitting) {
if (transmitting) {
signalMeter->setValue(0);
ui->signal_meter_widget->setValue(0);
if (m_monitoring) monitor (false);
m_btxok=true;
}
@ -3884,13 +3824,9 @@ void MainWindow::transmitDisplay (bool transmitting)
}
}
void MainWindow::on_sbTol_valueChanged(int i)
void MainWindow::on_FTol_combo_box_currentIndexChanged (QString const& text)
{
static int ntol[] = {10,20,50,100,200,500,1000,2000};
m_tol=ntol[i];
m_wideGraph->setTol(m_tol);
QString t="F Tol " + QString::number(ntol[i]);
ui->labTol->setText(t);
m_wideGraph->setTol (text.toInt ());
}
void MainWindow::on_sbDT_valueChanged(double x)
@ -3900,17 +3836,7 @@ void MainWindow::on_sbDT_valueChanged(double x)
void::MainWindow::VHF_controls_visible(bool b)
{
ui->sbSubmode->setVisible(b);
ui->sbMinW->setVisible(b);
ui->cbShMsgs->setVisible(b);
ui->cbTx6->setVisible(b);
ui->labMinW->setVisible(b);
ui->labSubmode->setVisible(b);
ui->cbEME->setVisible(b);
ui->sbDT->setVisible(b);
ui->labTol->setVisible(b);
ui->sbTol->setVisible(b);
ui->syncSpinBox->setVisible(b);
ui->VHFControls_widget->setVisible (b);
}
void::MainWindow::VHF_features_enabled(bool b)
@ -3936,8 +3862,6 @@ void MainWindow::on_sbMinW_valueChanged(int n)
{
m_MinW=qMin(n,m_nSubMode);
ui->sbMinW->setValue(m_MinW);
QString t="MinW " + (QString)QChar(short(n+65));
ui->labMinW->setText(t);
}
void MainWindow::on_sbSubmode_valueChanged(int n)
@ -3946,8 +3870,6 @@ void MainWindow::on_sbSubmode_valueChanged(int n)
m_wideGraph->setSubMode(m_nSubMode);
ui->sbMinW->setMaximum(m_nSubMode);
QString t1=(QString)QChar(short(m_nSubMode+65));
QString t="Submode " + t1;
ui->labSubmode->setText(t);
mode_label->setText(m_mode + " " + t1);
}

View File

@ -28,7 +28,6 @@
#include "WSPRBandHopping.hpp"
#include "Transceiver.hpp"
#include "psk_reporter.h"
#include "signalmeter.h"
#include "logbook/logbook.h"
#include "Detector.hpp"
#include "Modulator.hpp"
@ -202,7 +201,7 @@ private slots:
void stopTuneATU();
void auto_tx_mode (bool);
void on_actionMessage_averaging_triggered();
void on_sbTol_valueChanged(int i);
void on_FTol_combo_box_currentIndexChanged(QString const&);
void on_actionInclude_averaging_triggered();
void on_actionInclude_correlation_triggered();
void on_sbDT_valueChanged(double x);
@ -325,7 +324,6 @@ private:
qint32 m_astroFont;
qint32 m_nSubMode;
qint32 m_MinW;
qint32 m_tol;
qint32 m_nclearave;
qint32 m_minSync;
qint32 m_dBm;
@ -462,7 +460,6 @@ private:
QDateTime m_dateTimeQSO;
QSharedMemory *mem_jt9;
SignalMeter *signalMeter;
LogBook m_logBook;
DecodedText m_QSOText;
unsigned m_msAudioOutputBuffered;

File diff suppressed because it is too large Load Diff

View File

@ -3,15 +3,20 @@
#include "meterwidget.h"
#include <QPainter>
#include <QPolygon>
#include "moc_meterwidget.cpp"
MeterWidget::MeterWidget(QWidget *parent) :
QWidget(parent),
m_signal(0)
MeterWidget::MeterWidget(QWidget * parent)
: QWidget {parent}
, m_top_padding {0}
, m_bottom_padding {0}
, m_signal {0}
{
for ( int i = 0; i < 10; i++ ) {
signalQueue.enqueue(0);
}
for ( int i = 0; i < 10; i++ ) {
signalQueue.enqueue(0);
}
}
void MeterWidget::setValue(int value)
@ -31,23 +36,34 @@ void MeterWidget::setValue(int value)
update();
}
void MeterWidget::paintEvent( QPaintEvent * )
QSize MeterWidget::sizeHint () const
{
int pos;
QPainter p;
p.begin(this);
// Sanitize
m_signal = m_signal < 0 ? 0 : m_signal;
m_signal = m_signal > 60 ? 60 : m_signal;
pos = m_signal * 2;
QRect r(0, height() - pos, width(), pos );
p.fillRect(r, QColor( 255, 150, 0 ));
// Draw peak hold indicator
p.setPen(Qt::black);
pos = m_sigPeak * 2;
p.drawLine(0, height() - pos, 10, height() - pos);
return {10, 100};
}
void MeterWidget::paintEvent (QPaintEvent * event)
{
QWidget::paintEvent (event);
// Sanitize
m_signal = m_signal < 0 ? 0 : m_signal;
m_signal = m_signal > 60 ? 60 : m_signal;
QPainter p {this};
p.setPen (Qt::NoPen);
auto const& target = contentsRect ();
QRect r {QPoint {target.left (), static_cast<int> (target.top () + target.height () - m_signal / 60. * target.height ())}
, QPoint {target.right (), target.bottom ()}};
p.setBrush (QColor {255, 150, 0});
p.drawRect (r);
if (m_sigPeak)
{
// Draw peak hold indicator
auto peak = static_cast<int> (target.top () + target.height () - m_sigPeak / 60. * target.height ());
p.setBrush (Qt::black);
p.translate (target.left (), peak);
p.drawPolygon (QPolygon {{{0, -4}, {0, 4}, {target.width (), 0}}});
}
}

View File

@ -3,29 +3,31 @@
#define METERWIDGET_H
#include <QWidget>
#include <QtGui>
#include <QQueue>
class MeterWidget : public QWidget
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY (int value READ value WRITE setValue)
public:
explicit MeterWidget(QWidget *parent = 0);
signals:
public slots:
void setValue(int value);
explicit MeterWidget (QWidget *parent = 0);
// value property
int value () const {return m_signal;}
Q_SLOT void setValue (int value);
// QWidget implementation
QSize sizeHint () const override;
protected:
void paintEvent( QPaintEvent * ) override;
private:
QQueue<int> signalQueue;
int m_signal;
int m_sigPeak;
protected:
void paintEvent( QPaintEvent * );
int m_top_padding;
int m_bottom_padding;
QQueue<int> signalQueue;
int m_signal;
int m_sigPeak;
};
#endif // METERWIDGET_H

View File

@ -1,55 +1,98 @@
// Simple bargraph dB meter
// Implemented by Edson Pereira PY2SDR
//
// Limits and geometry are hardcded for now.
#include "signalmeter.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QPainter>
#include <QFontMetrics>
#include <meterwidget.h>
#include "moc_signalmeter.cpp"
SignalMeter::SignalMeter(QWidget *parent) :
QWidget(parent)
class Scale final
: public QWidget
{
resize(parent->size());
public:
explicit Scale (QWidget * parent = 0)
: QWidget {parent}
{
setSizePolicy (QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
}
m_meter = new MeterWidget(this);
m_meter->setGeometry(10, 10, 10, 120);
QSize sizeHint () const override
{
return minimumSizeHint ();
}
m_label = new QLabel(this);
m_label->setGeometry(10, 135, 20, 20);
QSize minimumSizeHint () const override
{
QFontMetrics font_metrics {font (), nullptr};
return {tick_length + text_indent + font_metrics.width ("00+"), (font_metrics.height () + line_spacing) * range};
}
QLabel *dbLabel = new QLabel(this);
dbLabel->setText("dB");
dbLabel->setGeometry(30, 135, 20, 20);
}
protected:
void paintEvent (QPaintEvent * event) override
{
QWidget::paintEvent (event);
SignalMeter::~SignalMeter()
QPainter p {this};
auto const& target = contentsRect ();
QFontMetrics font_metrics {p.font (), this};
auto font_offset = font_metrics.ascent () / 2;
p.drawLine (target.left (), target.top () + font_offset, target.left (), target.bottom () - font_offset - font_metrics.descent ());
for (int i = 0; i <= range; ++i)
{
p.save ();
p.translate (target.left ()
, target.top () + font_offset + i * (target.height () - font_metrics.ascent () - font_metrics.descent ()) / range);
p.drawLine (0, 0, tick_length, 0);
auto text = i ? QString::number ((range - i) * scale) : QString {"%1%2"}.arg ((range - i) * scale).arg ('+');
p.drawText (tick_length + text_indent, font_offset, text);
p.restore ();
}
}
private:
static int const tick_length {4};
static int const text_indent {2};
static int const line_spacing {0};
static int const range {6};
static int const scale {10};
};
SignalMeter::SignalMeter (QWidget * parent)
: QFrame {parent}
{
auto outer_layout = new QVBoxLayout;
outer_layout->setSpacing (0);
}
auto inner_layout = new QHBoxLayout;
inner_layout->setContentsMargins (9, 0, 9, 0);
inner_layout->setSpacing (0);
void SignalMeter::paintEvent( QPaintEvent * )
{
QPainter p;
p.begin(this);
p.drawLine(22, 10, 22, 130);
m_meter = new MeterWidget;
m_meter->setSizePolicy (QSizePolicy::Minimum, QSizePolicy::Minimum);
inner_layout->addWidget (m_meter);
for ( int i = 0; i <= 60; i += 10 ) {
p.drawLine(22, i*2 + 10, 25, i*2 + 10);
}
m_scale = new Scale;
inner_layout->addWidget (m_scale);
for ( int i = 10; i < 60; i += 10 ) {
p.drawText(30, i*2 + 15, QString::number(60 - i));
}
m_reading = new QLabel(this);
outer_layout->addLayout (inner_layout);
outer_layout->addWidget (m_reading);
setLayout (outer_layout);
}
void SignalMeter::setValue(int value)
{
m_meter->setValue(value);
m_label->setText(QString::number(value));
}
void SignalMeter::resizeEvent(QResizeEvent *s)
{
resize(s->size());
QFontMetrics font_metrics {m_scale->font (), nullptr};
m_meter->setContentsMargins (0, font_metrics.ascent () / 2, 0, font_metrics.ascent () / 2 + font_metrics.descent ());
m_meter->setValue(value);
m_reading->setText (QString {"%1dB"}.arg (value, 4));
}

View File

@ -2,29 +2,26 @@
#ifndef SIGNALMETER_H
#define SIGNALMETER_H
#include <QtGui>
#include <QLabel>
#include <meterwidget.h>
#include <QFrame>
class SignalMeter : public QWidget
class QLabel;
class MeterWidget;
class SignalMeter final
: public QFrame
{
Q_OBJECT
Q_OBJECT
public:
explicit SignalMeter(QWidget *parent = 0);
~SignalMeter();
explicit SignalMeter (QWidget * parent = nullptr);
public slots:
void setValue(int value);
void setValue (int value);
private:
MeterWidget *m_meter;
QLabel *m_label;
protected:
void paintEvent( QPaintEvent * );
void resizeEvent(QResizeEvent *s);
MeterWidget * m_meter;
QWidget * m_scale;
QLabel * m_reading;
};
#endif // SIGNALMETER_H