#include <qtimer.h>
#include <qtooltip.h>
#include <qimage.h>
+#include <qboxlayout.h>
+#include <qwidgetaction.h>
#include <Music/Music.h>
void GLStatistics::AverageNote::init()
}
QString GLStatistics::AverageNote::getName() const
{
- return Music::h2n(ht)+factor;
+ return QString::fromStdString(Music::h2n(ht))+factor;
}
void GLStatistics::AverageNote::addErr(float err)
{
}
if(errs.size()>1)
{
- err_std /= errs.size()-1; // unbiased estimation of the variance
+ err_std /= errs.size()-1; // unbiased estimation of the variance
err_std = sqrt(err_std);
}
}
void GLStatistics::addNote(int ht, float err)
{
- if(isHidden() && !setting_keep_hidden->isOn())
+ m_current_ht = ht;
+
+ if(isHidden() && !setting_keep_hidden->isChecked())
return;
- if(ht<setting_scale_min->minValue() || ht>setting_scale_max->maxValue())
+ if(ht<setting_scale_min->minimum() || ht>setting_scale_max->maximum())
return;
// cerr << "ht=" << ht << endl;
- if(setting_scale_auto->isOn())
+ if(!setting_scale_auto->isChecked())
+ {
+ resizeScale();
+
+ // drop ht outside of scale
+ if(ht<setting_scale_min->value() || ht>setting_scale_max->value())
+ return;
+
+ // add note
+ m_avg_notes[ht-setting_scale_min->value()].addErr(err);
+ }
+ else
{
if(m_avg_notes.empty())
{
}
void GLStatistics::addNote(int ht, int num, int den, float err)
{
+ m_current_ht = ht;
}
void GLStatistics::addNote(int ht, float cents, float err)
{
+ m_current_ht = ht;
+}
+
+void GLStatistics::resizeScale()
+{
+ if(setting_scale_auto->isChecked() || setting_scale_max->value()-setting_scale_min->value()+1<1)
+ return;
+
+ if(m_avg_notes.size()==0 || m_avg_notes[0].ht!=setting_scale_min->value() || m_avg_notes[m_avg_notes.size()-1].ht!=setting_scale_max->value())
+ {
+ vector<AverageNote> avg_notes(setting_scale_max->value()-setting_scale_min->value()+1);
+ for(int i=0; i<int(m_avg_notes.size()); i++)
+ {
+ int in = i+m_avg_notes[0].ht-setting_scale_min->value();
+ if(in>=0 && in<int(avg_notes.size()))
+ avg_notes[in] = m_avg_notes[i];
+ }
+ for(size_t i=0; i<avg_notes.size(); i++)
+ avg_notes[i].ht = setting_scale_min->value()+i;
+ m_avg_notes = avg_notes;
+ }
}
GLStatistics::GLStatistics(QWidget* parent)
-: QGLWidget(parent, "GLStatistics")
-, View("Statistics", this)
+: QGLWidget(parent)
+, View(tr("Statistics"), this)
{
// settings
- QImage img;
+ QPixmap img;
img.loadFromData(g_icon_statistics, sizeof(g_icon_statistics), "PNG");
- setting_show->setIconSet(QIconSet(QImage(img)));
- setting_show->setOn(false);
+ setting_show->setIcon(QIcon(img));
+ setting_show->setChecked(false);
hide();
- setting_reset = new QAction(this);
- setting_reset->setMenuText(tr("Reset statistics"));
+ setting_reset = new QAction(tr("Reset statistics"), this);
+ setting_reset->setShortcut('r');
connect(setting_reset, SIGNAL(activated()), this, SLOT(reset()));
- setting_reset->addTo(&m_popup_menu);
+ m_popup_menu.addAction(setting_reset);
- setting_keep_hidden = new QAction(this);
- setting_keep_hidden->setMenuText(tr("Keep notes when hidden"));
- setting_keep_hidden->setToggleAction(true);
- setting_keep_hidden->setOn(false);
+ setting_keep_hidden = new QAction(tr("Keep notes when hidden"), this);
+ setting_keep_hidden->setCheckable(true);
+ setting_keep_hidden->setChecked(false);
connect(setting_keep_hidden, SIGNAL(toggled(bool)), this, SLOT(update()));
- setting_keep_hidden->addTo(&m_popup_menu);
+ m_popup_menu.addAction(setting_keep_hidden);
+
+ QHBoxLayout* keepActionLayout = new QHBoxLayout(&m_popup_menu);
+
+ QLabel* keepActionTitle = new QLabel(tr("Keep n values"), &m_popup_menu);
+ keepActionLayout->addWidget(keepActionTitle);
- setting_show_std = new QAction(this);
- setting_show_std->setMenuText(tr("Show standard deviation"));
- setting_show_std->setToggleAction(true);
- setting_show_std->setOn(true);
- setting_show_std->setEnabled(true);
+ setting_keep_n_values = new QSpinBox(&m_popup_menu);
+ setting_keep_n_values->setObjectName("setting_keep_n_values");
+ setting_keep_n_values->setMinimum(1);
+ setting_keep_n_values->setMaximum(500);
+ setting_keep_n_values->setSingleStep(3);
+ setting_keep_n_values->setValue(100);
+ setting_keep_n_values->setToolTip(tr("Keep this number of values in the computation of the statistics"));
+ connect(setting_keep_n_values, SIGNAL(valueChanged(int)), this, SLOT(update()));
+ keepActionLayout->addWidget(setting_keep_n_values);
+
+ QWidget* keepActionWidget = new QWidget(&m_popup_menu);
+ keepActionWidget->setLayout(keepActionLayout);
+
+ QWidgetAction* keepAction = new QWidgetAction(&m_popup_menu);
+ keepAction->setDefaultWidget(keepActionWidget);
+ m_popup_menu.addAction(keepAction);
+
+ setting_keep_n_values->setEnabled(false);
+ s_settings->add(setting_keep_n_values);
+
+ setting_show_std = new QAction(tr("Show standard deviation"), this);
+ setting_show_std->setCheckable(true);
+ setting_show_std->setChecked(true);
connect(setting_show_std, SIGNAL(toggled(bool)), this, SLOT(update()));
- setting_show_std->addTo(&m_popup_menu);
+ m_popup_menu.addAction(setting_show_std);
- setting_scale_auto = new QAction(this);
- setting_scale_auto->setMenuText(tr("Scale auto"));
- setting_scale_auto->setToggleAction(true);
- setting_scale_auto->setOn(true);
+ setting_scale_auto = new QAction(tr("Scale auto"), this);
+ setting_scale_auto->setCheckable(true);
+ setting_scale_auto->setChecked(true);
setting_scale_auto->setEnabled(false);
connect(setting_scale_auto, SIGNAL(toggled(bool)), this, SLOT(update()));
- setting_scale_auto->addTo(&m_popup_menu);
+ m_popup_menu.addAction(setting_scale_auto);
+
+ QHBoxLayout* scaleMinActionLayout = new QHBoxLayout(&m_popup_menu);
- m_popup_menu.insertItem(new Title(tr("Scale min"), &m_popup_menu));
- setting_scale_min = new QSpinBox(-96, 96, 1, &m_popup_menu);
- setting_scale_min->setValue(0);
- QToolTip::add(setting_scale_min, tr("Scale min value (in semi-tones)"));
+ QLabel* scaleMinActionTitle = new QLabel(tr("Scale min"), &m_popup_menu);
+ scaleMinActionLayout->addWidget(scaleMinActionTitle);
+
+ setting_scale_min = new QSpinBox(&m_popup_menu);
+ setting_scale_min->setObjectName("setting_scale_min");
+ setting_scale_min->setMinimum(-96);
+ setting_scale_min->setMaximum(96);
+ setting_scale_min->setSingleStep(6);
+ setting_scale_min->setValue(-12);
+ setting_scale_min->setToolTip(tr("Scale min value (in semi-tones)"));
connect(setting_scale_min, SIGNAL(valueChanged(int)), this, SLOT(update()));
- m_popup_menu.insertItem(setting_scale_min);
- setting_scale_min->setEnabled(false);
+ scaleMinActionLayout->addWidget(setting_scale_min);
+
+ QWidget* scaleMinActionWidget = new QWidget(&m_popup_menu);
+ scaleMinActionWidget->setLayout(scaleMinActionLayout);
- m_popup_menu.insertItem(new Title(tr("Scale max"), &m_popup_menu));
- setting_scale_max = new QSpinBox(-96, 96, 1, &m_popup_menu);
- setting_scale_max->setValue(0);
- QToolTip::add(setting_scale_max, tr("Scale max value (in semi-tones)"));
+ QWidgetAction* scaleMinAction = new QWidgetAction(&m_popup_menu);
+ scaleMinAction->setDefaultWidget(scaleMinActionWidget);
+ m_popup_menu.addAction(scaleMinAction);
+
+ setting_scale_min->setEnabled(false);
+ s_settings->add(setting_scale_min);
+ connect(setting_scale_auto, SIGNAL(toggled(bool)), setting_scale_min, SLOT(setDisabled(bool)));
+ connect(setting_scale_min, SIGNAL(valueChanged(int)), this, SLOT(resizeScale()));
+
+ QHBoxLayout* scaleMaxActionLayout = new QHBoxLayout(&m_popup_menu);
+
+ QLabel* scaleMaxActionTitle = new QLabel(tr("Scale max"), &m_popup_menu);
+ scaleMaxActionLayout->addWidget(scaleMaxActionTitle);
+
+ setting_scale_max = new QSpinBox(&m_popup_menu);
+ setting_scale_max->setObjectName("setting_scale_max");
+ setting_scale_max->setMinimum(-96);
+ setting_scale_max->setMaximum(96);
+ setting_scale_max->setSingleStep(6);
+ setting_scale_max->setValue(+12);
+ setting_scale_max->setToolTip(tr("Scale max value (in semi-tones)"));
connect(setting_scale_max, SIGNAL(valueChanged(int)), this, SLOT(update()));
- m_popup_menu.insertItem(setting_scale_max);
+ scaleMaxActionLayout->addWidget(setting_scale_max);
+
+ QWidget* scaleMaxActionWidget = new QWidget(&m_popup_menu);
+ scaleMaxActionWidget->setLayout(scaleMaxActionLayout);
+
+ QWidgetAction* scaleMaxAction = new QWidgetAction(&m_popup_menu);
+ scaleMaxAction->setDefaultWidget(scaleMaxActionWidget);
+ m_popup_menu.addAction(scaleMaxAction);
+
setting_scale_max->setEnabled(false);
+ s_settings->add(setting_scale_max);
+ connect(setting_scale_auto, SIGNAL(toggled(bool)), setting_scale_max, SLOT(setDisabled(bool)));
+ connect(setting_scale_max, SIGNAL(valueChanged(int)), this, SLOT(resizeScale()));
- setting_showTolerance = new QAction(this);
- setting_showTolerance->setMenuText(tr("Show tolerance"));
- setting_showTolerance->setToggleAction(true);
- setting_showTolerance->setOn(true);
+ setting_showTolerance = new QAction(tr("Show tolerance"), this);
+ setting_showTolerance->setCheckable(true);
+ setting_showTolerance->setChecked(true);
connect(setting_showTolerance, SIGNAL(toggled(bool)), this, SLOT(update()));
- setting_showTolerance->addTo(&m_popup_menu);
+ m_popup_menu.addAction(setting_showTolerance);
- setting_useCents = new QAction(this);
- setting_useCents->setMenuText(tr("Use cents"));
- setting_useCents->setToggleAction(true);
- setting_useCents->setOn(true);
+ setting_useCents = new QAction(tr("Use cents"), this);
+ setting_useCents->setCheckable(true);
+ setting_useCents->setChecked(true);
connect(setting_useCents, SIGNAL(toggled(bool)), this, SLOT(update()));
- setting_useCents->addTo(&m_popup_menu);
+ m_popup_menu.addAction(setting_useCents);
+
+ QHBoxLayout* scaleActionLayout = new QHBoxLayout(&m_popup_menu);
- m_popup_menu.insertItem(new Title(tr("Scale range"), &m_popup_menu));
- setting_spinScale = new QSpinBox(5, 50, 1, &m_popup_menu);
+ QLabel* scaleActionTitle = new QLabel(tr("Scale range"), &m_popup_menu);
+ scaleActionLayout->addWidget(scaleActionTitle);
+
+ setting_spinScale = new QSpinBox(&m_popup_menu);
+ setting_spinScale->setMinimum(5);
+ setting_spinScale->setMaximum(50);
+ setting_spinScale->setSingleStep(1);
setting_spinScale->setValue(50);
- QToolTip::add(setting_spinScale, tr("Scale range (in cents)"));
+ setting_spinScale->setToolTip(tr("Scale range (in cents)"));
connect(setting_spinScale, SIGNAL(valueChanged(int)), this, SLOT(update()));
- m_popup_menu.insertItem(setting_spinScale);
+ scaleActionLayout->addWidget(setting_spinScale);
+
+ QWidget* scaleActionWidget = new QWidget(&m_popup_menu);
+ scaleActionWidget->setLayout(scaleActionLayout);
+
+ QWidgetAction* scaleAction = new QWidgetAction(&m_popup_menu);
+ scaleAction->setDefaultWidget(scaleActionWidget);
+ m_popup_menu.addAction(scaleAction);
}
void GLStatistics::save()
{
- s_settings->writeEntry("setting_keep_hidden", setting_keep_hidden->isOn());
- s_settings->writeEntry("setting_show_std", setting_show_std->isOn());
- s_settings->writeEntry("setting_scale_auto", setting_scale_auto->isOn());
- s_settings->writeEntry("setting_scale_min", setting_scale_min->value());
- s_settings->writeEntry("setting_scale_max", setting_scale_max->value());
+ s_settings->setValue("setting_keep_hidden", setting_keep_hidden->isChecked());
+ s_settings->setValue("setting_show_std", setting_show_std->isChecked());
+ s_settings->setValue("setting_scale_auto", setting_scale_auto->isChecked());
}
void GLStatistics::load()
{
- setting_keep_hidden->setOn(s_settings->readBoolEntry("setting_keep_hidden", setting_keep_hidden->isOn()));
- setting_show_std->setOn(s_settings->readBoolEntry("setting_show_std", setting_show_std->isOn()));
- setting_scale_auto->setOn(s_settings->readBoolEntry("setting_scale_auto", setting_scale_auto->isOn()));
- setting_scale_min->setValue(s_settings->readNumEntry("setting_scale_min", setting_scale_min->value()));
- setting_scale_max->setValue(s_settings->readNumEntry("setting_scale_max", setting_scale_max->value()));
+ setting_keep_hidden->setChecked(s_settings->value("setting_keep_hidden", setting_keep_hidden->isChecked()).toBool());
+ setting_show_std->setChecked(s_settings->value("setting_show_std", setting_show_std->isChecked()).toBool());
+ setting_scale_auto->setChecked(s_settings->value("setting_scale_auto", setting_scale_auto->isChecked()).toBool());
}
void GLStatistics::clearSettings()
{
- s_settings->removeEntry("setting_keep_hidden");
- s_settings->removeEntry("setting_show_std");
- s_settings->removeEntry("setting_scale_auto");
- s_settings->removeEntry("setting_scale_min");
- s_settings->removeEntry("setting_scale_max");
+ s_settings->remove("setting_keep_hidden");
+ s_settings->remove("setting_show_std");
+ s_settings->remove("setting_scale_auto");
}
void GLStatistics::reset()
{
m_avg_notes.clear();
- setting_scale_min->setValue(0);
- setting_scale_max->setValue(0);
+ if(setting_scale_auto->isChecked())
+ {
+ setting_scale_min->setValue(0);
+ setting_scale_max->setValue(0);
+ }
+ resizeScale();
updateGL();
}
if(i>=0) txt = QString(" ")+txt;
if(i==0) txt = QString(" ")+txt;
glRasterPos2i(2, int((height()-dy)*i/100.0f*scale) + (height()-dy)/2 + dy - 4);
- for(size_t i=0; i<txt.length(); i++)
- glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, txt.latin1()[i]);
+ string str = txt.toStdString();
+ for(size_t i=0; i<str.length(); i++)
+ glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)str[i]);
}
}
glLineWidth(1.0f);
float human_tol = Music::f2hf(441.0,440.0);
float scale;
- if(setting_useCents->isOn())
+ if(setting_useCents->isChecked())
scale = 50.0f/setting_spinScale->value();
else
scale = int(50/setting_spinScale->value());
// name
- QString str = tr("Statistics");
+ string str = tr("Statistics").toStdString();
glColor3f(0.75,0.75,0.75);
glRasterPos2i(2, height()-20);
for(size_t i = 0; i < str.length(); i++)
- glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, str.latin1()[i]);
+ glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, (unsigned char)str[i]);
int char_size = 9;
int ticks_size = 2+3*char_size;
int grid_height = height()-legend_height;
// draw green rect
- if(setting_showTolerance->isOn())
+ if(setting_showTolerance->isChecked())
{
int green_ytop = int((scale*human_tol+0.5)*grid_height) + legend_height;
int green_ybottom = int((-scale*human_tol+0.5)*grid_height) + legend_height;
}
// std
- if(setting_show_std->isOn())
+ if(setting_show_std->isChecked())
{
glBegin(GL_QUADS);
glLineWidth(1.0f);
}
// horiz lines
- if(setting_useCents->isOn())
+ if(setting_useCents->isChecked())
{
glBegin(GL_LINES);
float gray = 0.87;
// text marks
float gray = 0.5;
glColor3f(gray, gray, gray);
- if(setting_useCents->isOn())
+ if(setting_useCents->isChecked())
{
int grad = 10;
if(setting_spinScale->value() <= 25) grad=5;
else
{
string sfraq, sufraq;
- sufraq = string("1/")+QString::number(int(50/setting_spinScale->value())*2).latin1();
+ sufraq = string("1/")+QString::number(int(50/setting_spinScale->value())*2).toStdString();
sfraq = string("+")+sufraq;
glRasterPos2i(2, 3*grid_height/4-dy+legend_height);
for(size_t i = 0; i < sfraq.size(); i++)
- glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, sfraq[i]);
+ glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)sfraq[i]);
sfraq = string("-")+sufraq;
glRasterPos2i(2, grid_height/4-dy+legend_height);
for(size_t i = 0; i < sfraq.size(); i++)
- glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, sfraq[i]);
+ glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)sfraq[i]);
- sufraq = string("1/")+QString::number(int(50/setting_spinScale->value())*4).latin1();
+ sufraq = string("1/")+QString::number(int(50/setting_spinScale->value())*4).toStdString();
sfraq = string("+")+sufraq;
glRasterPos2i(2, 5*grid_height/8-dy+legend_height);
for(size_t i = 0; i < sfraq.size(); i++)
- glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, sfraq[i]);
+ glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)sfraq[i]);
sfraq = string("-")+sufraq;
glRasterPos2i(2, 3*grid_height/8-dy+legend_height);
for(size_t i = 0; i < sfraq.size(); i++)
- glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, sfraq[i]);
+ glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)sfraq[i]);
}
// vertical lines
glColor3f(0, 0, 1);
for(size_t i=0; i<m_avg_notes.size(); i++)
{
- string str = m_avg_notes[i].getName();
+ string str = m_avg_notes[i].getName().toStdString();
glRasterPos2f(ticks_size+(i+0.5)*float(grid_width)/m_avg_notes.size(), 2);
for(size_t c=0; c<str.length(); c++)
- glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, str[c]);
+ glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)str[c]);
}
// sizes
if(!m_avg_notes[i].errs.empty())
{
- string str = QString::number(m_avg_notes[i].errs.size());
+ string str = QString::number(m_avg_notes[i].errs.size()).toStdString();
glRasterPos2f(ticks_size+(i+0.5)*float(grid_width)/m_avg_notes.size(), 4+legend_height/2);
for(size_t c=0; c<str.length(); c++)
- glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, str[c]);
+ glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (unsigned char)str[c]);
}
}
}
glEnd();
+ // Marks around current note
+ glBegin(GL_LINES);
+ gray = 0;
+ glColor3f(gray, gray, gray);
+ for(size_t i=0; i<m_avg_notes.size(); i++)
+ {
+ if(m_avg_notes[i].ht==m_current_ht)
+ {
+ int x = ticks_size+int(i*float(grid_width)/m_avg_notes.size());
+ glVertex2i(x, legend_height);
+ glVertex2i(x, height());
+ x = ticks_size+int((i+1)*float(grid_width)/m_avg_notes.size());
+ glVertex2i(x, legend_height);
+ glVertex2i(x, height());
+ }
+ }
+ glEnd();
+
glFlush();
}