#include "DialView.h" #include using namespace std; #include #include #include #include #include DialView::DialView(QWidget* parent) : QFrame(parent, "DialView") , View("Dial", this) { m_error = 0.0f; m_min_error = 0.0f; m_max_error = 0.0f; // settings setting_showTolerance = new QAction(this); setting_showTolerance->setMenuText(tr("Show tolerance")); setting_showTolerance->setToggleAction(true); setting_showTolerance->setOn(true); connect(setting_showTolerance, SIGNAL(toggled(bool)), this, SLOT(update())); setting_showTolerance->addTo(&m_popup_menu); setting_showTrace = new QAction(this); setting_showTrace->setMenuText(tr("Show trace")); setting_showTrace->setToggleAction(true); setting_showTrace->setOn(true); connect(setting_showTrace, SIGNAL(toggled(bool)), this, SLOT(update())); setting_showTrace->addTo(&m_popup_menu); setting_useCents = new QAction(this); setting_useCents->setMenuText(tr("Use cents")); setting_useCents->setToggleAction(true); setting_useCents->setOn(true); connect(setting_useCents, SIGNAL(toggled(bool)), this, SLOT(update())); setting_useCents->addTo(&m_popup_menu); m_popup_menu.insertItem(new Title(tr("Scale range"), &m_popup_menu)); setting_spinScale = new QSpinBox(5, 100, 1, &m_popup_menu); setting_spinScale->setValue(50); QToolTip::add(setting_spinScale, tr("Scale range (in cents)")); connect(setting_spinScale, SIGNAL(valueChanged(int)), this, SLOT(update())); m_popup_menu.insertItem(setting_spinScale); } void DialView::save() { s_settings->writeEntry("showTolerance", setting_showTolerance->isOn()); s_settings->writeEntry("showTrace", setting_showTrace->isOn()); s_settings->writeEntry("useCents", setting_useCents->isOn()); s_settings->writeEntry("spinScale", setting_spinScale->value()); } void DialView::load() { setting_showTolerance->setOn(s_settings->readBoolEntry("showTolerance", setting_showTolerance->isOn())); setting_showTrace->setOn(s_settings->readBoolEntry("showTrace", setting_showTrace->isOn())); setting_useCents->setOn(s_settings->readBoolEntry("useCents", setting_useCents->isOn())); setting_spinScale->setValue(s_settings->readNumEntry("spinScale", setting_spinScale->value())); } void DialView::clearSettings() { s_settings->removeEntry("showTolerance"); s_settings->removeEntry("showTrace"); s_settings->removeEntry("useCents"); s_settings->removeEntry("spinScale"); } void DialView::drawTextTickCent(QPainter& p, int bigw, int bigh, int r) { QString txt; // double deg = 0.0; int bw = bigw/2-p.fontMetrics().height()+p.fontMetrics().height()/2+2; int bh = bigh-p.fontMetrics().height()+p.fontMetrics().height()/2+2; // only work within range that is a pure multiple of r int range = int(setting_spinScale->value()/r)*r; float scale = 50.0f/setting_spinScale->value()/100.0f; for(int i=-range; i<=range; i+=r) { txt = QString::number(i); float angle = (150.0f/180.0f)*i*scale*Math::Pi + Math::Pi/2; QPoint pos(int(-bw*cos(angle)),int(-bh*sin(angle))); p.translate(pos.x(), pos.y()); if(height()>width()) p.rotate(90); p.drawText(-p.fontMetrics().width(txt)/2,p.fontMetrics().height()/2, txt); if(height()>width()) p.rotate(-90); p.translate(-pos.x(), -pos.y()); } } void DialView::drawTicksCent(QPainter& p, int bigw, int bigh, int r, int ticks_size, int h) { int sw = int(bigw/2.0f-p.fontMetrics().height()-ticks_size); int sh = bigh-p.fontMetrics().height()-ticks_size; int bw = sw + h; int bh = sh + h; // only work within range that is a pure multiple of r float range = int(setting_spinScale->value()/r)*r; float scale = 50.0f/setting_spinScale->value()/100.0f; for(float i=-range; i<=range; i+=r) { float angle = (150.0f/180.0f)*i*scale*Math::Pi + Math::Pi/2; p.drawLine(-QPoint(int(sw*cos(angle)),int(sh*sin(angle))), -QPoint(int(bw*cos(angle)),int(bh*sin(angle)))); } } void DialView::drawTextTickFrac(QPainter& p, int bigw, int bigh, int num, int den) { QString txt; double deg = 0.0; if(num==0 || den==0) txt = "0"; else { deg = num*150/den; txt = QString::number(den*(50/setting_spinScale->value())); } int bw = bigw/2-p.fontMetrics().height()+p.fontMetrics().height()/2+2; int bh = bigh-p.fontMetrics().height()+p.fontMetrics().height()/2+2; float angle = deg/180.0f*Math::Pi + Math::Pi/2; QPoint pos(int(-bw*cos(angle)),int(-bh*sin(angle))); p.translate(pos.x(), pos.y()); if(height()>width()) p.rotate(90); p.drawText(-p.fontMetrics().width(txt)/2,p.fontMetrics().height()/2, txt); if(height()>width()) p.rotate(-90); p.translate(-pos.x(), -pos.y()); } void DialView::drawTicksFrac(QPainter& p, int bigw, int bigh, float r, int ticks_size, int h) { int sw = bigw/2-p.fontMetrics().height()-ticks_size; int sh = bigh-p.fontMetrics().height()-ticks_size; int bw = sw + h; int bh = sh + h; for(float i=-0.5f+r; i<0.5f; i+=2*r) { float angle = (150.0f/180.0f)*i*Math::Pi + Math::Pi/2; p.drawLine(-QPoint(int(sw*cos(angle)),int(sh*sin(angle))), -QPoint(int(bw*cos(angle)),int(bh*sin(angle)))); } } void DialView::setError(float error) { m_error = error; repaint(); } void DialView::drawContents(QPainter* pp) { QPainter& p = *pp; float human_tol = Music::f2hf(441.0,440.0); // TODO float scale; if(setting_useCents->isOn()) scale = 50.0f/setting_spinScale->value(); else scale = int(50/setting_spinScale->value()); int bigw = width(); int bigh = height(); QPoint c(width()/2,height()); QPoint unity_center = c+QPoint(p.fontMetrics().width("cent"),0); QString unity; if(setting_useCents->isOn()) unity = "cents"; else unity = "1/x"; if(height()>width()) { c = QPoint(width(), height()/2); bigw = height(); bigh = width(); unity_center = c+QPoint(-p.fontMetrics().width(unity),-p.fontMetrics().height()); } int ticks_size = bigh/10; // draw unity p.setPen(QColor(0,0,0)); p.drawText(unity_center, unity); p.translate(c.x(), c.y()); if(height()>width()) p.rotate(-90); // draw pie int pie_width = bigw/2-p.fontMetrics().height()-ticks_size-2; int pie_height = bigh-p.fontMetrics().height()-ticks_size-2; p.setBrush(QColor(123,205,145)); QPen pen1 = p.pen(); pen1.setColor(QColor(83,165,105)); // pen1.setStyle(Qt::DashLine); // pen1.setWidth(2); p.setPen(pen1); if(setting_showTolerance->isOn()) { float pie_deg = (150.0f/180.0f)*scale*human_tol*180; p.drawPie(-pie_width,-pie_height,2*pie_width,2*pie_height, int((90-pie_deg)*16),int(2*pie_deg*16)); } // draw min max if((m_error>-1.0f && m_error<1.0f) && setting_showTrace->isOn() && m_max_error-m_min_error>0.0) { int line_width = ticks_size/4; int mm_height = pie_height - line_width/2; int mm_width = pie_width - line_width/2; QPen pen3 = p.pen(); pen3.setColor(QColor(128,128,128)); pen3.setWidth(line_width); p.setPen(pen3); float mm_degf = (150.0f/180.0f)*scale*180; p.drawArc(-mm_width,-mm_height,2*mm_width,2*mm_height,int((90-mm_degf*m_min_error)*16),int((-mm_degf*(m_max_error-m_min_error))*16)); } // draw text marks p.setPen(QColor(0,0,0)); if(setting_useCents->isOn()) { int grad = 10; if(setting_spinScale->value() <= 25) grad=5; if(setting_spinScale->value() <= 10) grad=1; drawTextTickCent(p, bigw, bigh, grad); } else { drawTextTickFrac(p, bigw, bigh, 0,1); drawTextTickFrac(p, bigw, bigh, 1,2); drawTextTickFrac(p, bigw, bigh, -1,2); drawTextTickFrac(p, bigw, bigh, 1,4); drawTextTickFrac(p, bigw, bigh, -1,4); drawTextTickFrac(p, bigw, bigh, 1,8); drawTextTickFrac(p, bigw, bigh, -1,8); drawTextTickFrac(p, bigw, bigh, 1,16); drawTextTickFrac(p, bigw, bigh, -1,16); } // draw ticks int sw = bigw/2-p.fontMetrics().height()-ticks_size; int sh = bigh-p.fontMetrics().height()-ticks_size; int bw = sw + ticks_size; int bh = sh + ticks_size; if(setting_useCents->isOn()) { drawTicksCent(p, bigw, bigh, 10, ticks_size, ticks_size); drawTicksCent(p, bigw, bigh, 5, ticks_size, int(ticks_size * 0.6)); drawTicksCent(p, bigw, bigh, 1, ticks_size, int(ticks_size * 0.3)); } else { for(float i=-1.0f; i<=1.0f; i+=0.25f) { float angle = (150.0f/360.0f)*i*Math::Pi + Math::Pi/2; p.drawLine(-QPoint(int(sw*cos(angle)),int(sh*sin(angle))), -QPoint(int(bw*cos(angle)),int(bh*sin(angle)))); } drawTicksFrac(p, bigw, bigh, 0.125f, ticks_size, 2*ticks_size/3); drawTicksFrac(p, bigw, bigh, 0.0625f, ticks_size, ticks_size/2); drawTicksFrac(p, bigw, bigh, 0.03125f, ticks_size, ticks_size/3); } // draw arrow if(m_error>-1.0f && m_error<1.0f) { float angle = (150.0f/180.0f)*scale*m_error*Math::Pi + Math::Pi/2; QPoint final_point = -QPoint(int((pie_width-2)*cos(angle)),int((pie_height-2)*sin(angle))); QPoint mid_point = 9*final_point/10; QPen pen2 = p.pen(); pen2.setWidth(3); pen2.setColor(QColor(64,64,64)); p.setPen(pen2); p.drawLine(QPoint(0,0), mid_point); pen2.setWidth(1); p.setPen(pen2); p.drawLine(mid_point, final_point); } p.flush(); }