diff layer/TimeValueLayer.cpp @ 101:0f36cdf407a6 sv1-v0.9rc1

* Make vertical scale alignment modes work in note layer as well as time-value layer, and several significant fixes to it * Make it possible to draw notes properly on the note layer * Show units (and frequencies etc in note layer's case) in the time-value and note layer description boxes * Minor fix to item edit dialog layout * Some minor menu rearrangement * Comment out a lot of debug output * Add SV website and reference URLs to Help menu, and add code to (attempt to) open them in the user's preferred browser
author Chris Cannam
date Fri, 12 May 2006 14:40:43 +0000
parents 0db5e7492ce8
children 999ae0f7d10c
line wrap: on
line diff
--- a/layer/TimeValueLayer.cpp	Thu May 11 15:02:14 2006 +0000
+++ b/layer/TimeValueLayer.cpp	Fri May 12 14:40:43 2006 +0000
@@ -42,7 +42,7 @@
     m_editingCommand(0),
     m_colour(Qt::darkGreen),
     m_plotStyle(PlotConnectedPoints),
-    m_verticalScale(LinearScale)
+    m_verticalScale(AutoAlignScale)
 {
     
 }
@@ -60,7 +60,7 @@
     connect(m_model, SIGNAL(completionChanged()),
 	    this, SIGNAL(modelCompletionChanged()));
 
-    std::cerr << "TimeValueLayer::setModel(" << model << ")" << std::endl;
+//    std::cerr << "TimeValueLayer::setModel(" << model << ")" << std::endl;
 
     emit modelReplaced();
 }
@@ -169,10 +169,10 @@
     } else if (name == "Vertical Scale") {
 	switch (value) {
 	default:
-	case 0: return tr("Linear Scale");
-	case 1: return tr("Log Scale");
-	case 2: return tr("+/-1 Scale");
-	case 3: return tr("Frequency Scale");
+	case 0: return tr("Auto-Align");
+	case 1: return tr("Linear Scale");
+	case 2: return tr("Log Scale");
+	case 3: return tr("+/-1 Scale");
 	}
     }
     return tr("<unknown>");
@@ -242,14 +242,27 @@
 }
 
 bool
-TimeValueLayer::getValueExtents(float &min, float &max, QString &unit) const
+TimeValueLayer::getValueExtents(float &min, float &max,
+                                bool &logarithmic, QString &unit) const
 {
+    if (!m_model) return false;
     min = m_model->getValueMinimum();
     max = m_model->getValueMaximum();
+    logarithmic = (m_verticalScale == LogScale);
     unit = m_model->getScaleUnits();
     return true;
 }
 
+bool
+TimeValueLayer::getDisplayExtents(float &min, float &max) const
+{
+    if (!m_model || m_verticalScale == AutoAlignScale) return false;
+
+    min = m_model->getValueMinimum();
+    max = m_model->getValueMaximum();
+    return true;
+}
+
 SparseTimeValueModel::PointList
 TimeValueLayer::getLocalPoints(View *v, int x) const
 {
@@ -315,15 +328,19 @@
     RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate());
     
     QString text;
+    QString unit = m_model->getScaleUnits();
+    if (unit != "") unit = " " + unit;
 
     if (points.begin()->label == "") {
-	text = QString(tr("Time:\t%1\nValue:\t%2\nNo label"))
-	    .arg(rt.toText(true).c_str())
-	    .arg(points.begin()->value);
-    } else {
-	text = QString(tr("Time:\t%1\nValue:\t%2\nLabel:\t%3"))
+	text = QString(tr("Time:\t%1\nValue:\t%2%3\nNo label"))
 	    .arg(rt.toText(true).c_str())
 	    .arg(points.begin()->value)
+            .arg(unit);
+    } else {
+	text = QString(tr("Time:\t%1\nValue:\t%2%3\nLabel:\t%4"))
+	    .arg(rt.toText(true).c_str())
+	    .arg(points.begin()->value)
+            .arg(unit)
 	    .arg(points.begin()->label);
     }
 
@@ -404,81 +421,89 @@
     return found;
 }
 
+void
+TimeValueLayer::getScaleExtents(View *v, float &min, float &max, bool &log) const
+{
+    min = 0.0;
+    max = 0.0;
+    log = false;
+
+    if (m_verticalScale == AutoAlignScale) {
+
+        if (!v->getValueExtents(m_model->getScaleUnits(), min, max, log)) {
+            min = m_model->getValueMinimum();
+            max = m_model->getValueMaximum();
+        } else if (log) {
+            min = (min < 0.0) ? -log10(-min) : (min == 0.0) ? 0.0 : log10(min);
+            max = (max < 0.0) ? -log10(-max) : (max == 0.0) ? 0.0 : log10(max);
+        }
+
+    } else if (m_verticalScale == PlusMinusOneScale) {
+
+        min = -1.0;
+        max = 1.0;
+
+    } else {
+
+        min = m_model->getValueMinimum();
+        max = m_model->getValueMaximum();
+
+        if (m_verticalScale == LogScale) {
+            min = (min < 0.0) ? -log10(-min) : (min == 0.0) ? 0.0 : log10(min);
+            max = (max < 0.0) ? -log10(-max) : (max == 0.0) ? 0.0 : log10(max);
+            log = true;
+        }
+    }
+
+    if (max == min) max = min + 1.0;
+}
+
 int
 TimeValueLayer::getYForValue(View *v, float val) const
 {
     float min = 0.0, max = 0.0;
+    bool logarithmic = false;
     int h = v->height();
 
-    if (!v->getValueExtents(m_model->getScaleUnits(), min, max)) {
-        min = m_model->getValueMinimum();
-        max = m_model->getValueMaximum();
+    getScaleExtents(v, min, max, logarithmic);
+
+//    std::cerr << "getYForValue(" << val << "): min " << min << ", max "
+//              << max << ", log " << logarithmic << std::endl;
+
+    if (logarithmic) {
+        val = (val < 0.0) ? -log10(-val) : (val == 0.0) ? 0.0 : log10(val);
     }
 
-    if (max == min) max = min + 1.0;
-
-/*!!!
-    float min = m_model->getValueMinimum();
-    float max = m_model->getValueMaximum();
-    if (max == min) max = min + 1.0;
-
-    int h = v->height();
-
-    if (m_verticalScale == FrequencyScale || m_verticalScale == LogScale) {
-        
-        if (m_verticalScale == FrequencyScale) {
-            // If we have a spectrogram layer on the same view as us, align
-            // ourselves with it...
-            for (int i = 0; i < v->getLayerCount(); ++i) {
-                SpectrogramLayer *spectrogram = dynamic_cast<SpectrogramLayer *>
-                    (v->getLayer(i));
-                if (spectrogram) {
-                    return spectrogram->getYForFrequency(v, val);
-                }
-            }
-        }
-
-        min = (min < 0.0) ? -log10(-min) : (min == 0.0) ? 0.0 : log10(min);
-        max = (max < 0.0) ? -log10(-max) : (max == 0.0) ? 0.0 : log10(max);
-        val = (val < 0.0) ? -log10(-val) : (val == 0.0) ? 0.0 : log10(val);
-
-    } else if (m_verticalScale == PlusMinusOneScale) {
-        min = -1.0;
-        max = 1.0;
-    }
-*/
-
     return int(h - ((val - min) * h) / (max - min));
 }
 
 float
 TimeValueLayer::getValueForY(View *v, int y) const
 {
-    //!!!
-
-    float min = m_model->getValueMinimum();
-    float max = m_model->getValueMaximum();
-    if (max == min) max = min + 1.0;
-
+    float min = 0.0, max = 0.0;
+    bool logarithmic = false;
     int h = v->height();
 
-    return min + (float(h - y) * float(max - min)) / h;
+    getScaleExtents(v, min, max, logarithmic);
+
+    float val = min + (float(h - y) * float(max - min)) / h;
+
+    if (logarithmic) {
+        val = pow(10, val);
+    }
+
+    return val;
 }
 
 QColor
-TimeValueLayer::getColourForValue(float val) const
+TimeValueLayer::getColourForValue(View *v, float val) const
 {
-    float min = m_model->getValueMinimum();
-    float max = m_model->getValueMaximum();
-    if (max == min) max = min + 1.0;
+    float min, max;
+    bool log;
+    getScaleExtents(v, min, max, log);
 
-    if (m_verticalScale == FrequencyScale || m_verticalScale == LogScale) {
-        min = (min < 0.0) ? -log10(-min) : (min == 0.0) ? 0.0 : log10(min);
-        max = (max < 0.0) ? -log10(-max) : (max == 0.0) ? 0.0 : log10(max);
+    if (log) {
         val = (val < 0.0) ? -log10(-val) : (val == 0.0) ? 0.0 : log10(val);
-    } else if (m_verticalScale == PlusMinusOneScale) {
-        min = -1.0;
-        max = 1.0;
     }
 
     int iv = ((val - min) / (max - min)) * 255.999;
@@ -581,7 +606,7 @@
 	paint.setPen(m_colour);
 
 	if (m_plotStyle == PlotSegmentation) {
-            paint.setBrush(getColourForValue(p.value));
+            paint.setBrush(getColourForValue(v, p.value));
 	    labelY = v->height();
 	} else if (m_plotStyle == PlotLines ||
 		   m_plotStyle == PlotCurve) {
@@ -744,7 +769,7 @@
         paint.save();
         for (int y = 0; y < boxh; ++y) {
             float val = ((boxh - y) * (max - min)) / boxh + min;
-            paint.setPen(getColourForValue(val));
+            paint.setPen(getColourForValue(v, val));
             paint.drawLine(boxx + 1, y + boxy + 1, boxx + boxw, y + boxy + 1);
         }
         paint.restore();
@@ -789,7 +814,7 @@
 void
 TimeValueLayer::drawStart(View *v, QMouseEvent *e)
 {
-    std::cerr << "TimeValueLayer::drawStart(" << e->x() << "," << e->y() << ")" << std::endl;
+//    std::cerr << "TimeValueLayer::drawStart(" << e->x() << "," << e->y() << ")" << std::endl;
 
     if (!m_model) return;
 
@@ -807,7 +832,7 @@
         for (SparseTimeValueModel::PointList::iterator i = points.begin();
              i != points.end(); ++i) {
             if (((i->frame / resolution) * resolution) != frame) {
-                std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl;
+//                std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl;
                 continue;
             }
             m_editingPoint = *i;
@@ -835,7 +860,7 @@
 void
 TimeValueLayer::drawDrag(View *v, QMouseEvent *e)
 {
-    std::cerr << "TimeValueLayer::drawDrag(" << e->x() << "," << e->y() << ")" << std::endl;
+//    std::cerr << "TimeValueLayer::drawDrag(" << e->x() << "," << e->y() << ")" << std::endl;
 
     if (!m_model || !m_editing) return;
 
@@ -848,7 +873,7 @@
 
     SparseTimeValueModel::PointList points = getLocalPoints(v, e->x());
 
-    std::cerr << points.size() << " points" << std::endl;
+//    std::cerr << points.size() << " points" << std::endl;
 
     bool havePoint = false;
 
@@ -857,14 +882,14 @@
              i != points.end(); ++i) {
             if (i->frame == m_editingPoint.frame &&
                 i->value == m_editingPoint.value) {
-                std::cerr << "ignoring current editing point at " << i->frame << ", " << i->value << std::endl;
+            //    std::cerr << "ignoring current editing point at " << i->frame << ", " << i->value << std::endl;
                 continue;
             }
             if (((i->frame / resolution) * resolution) != frame) {
-                std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl;
+            //    std::cerr << "ignoring out-of-range frame at " << i->frame << std::endl;
                 continue;
             }
-            std::cerr << "adjusting to new point at " << i->frame << ", " << i->value << std::endl;
+        //    std::cerr << "adjusting to new point at " << i->frame << ", " << i->value << std::endl;
             m_editingPoint = *i;
             m_originalPoint = m_editingPoint;
             m_editingCommand->deletePoint(m_editingPoint);
@@ -887,7 +912,7 @@
 void
 TimeValueLayer::drawEnd(View *v, QMouseEvent *e)
 {
-    std::cerr << "TimeValueLayer::drawEnd(" << e->x() << "," << e->y() << ")" << std::endl;
+//    std::cerr << "TimeValueLayer::drawEnd(" << e->x() << "," << e->y() << ")" << std::endl;
     if (!m_model || !m_editing) return;
     m_editingCommand->finish();
     m_editingCommand = 0;
@@ -897,7 +922,7 @@
 void
 TimeValueLayer::editStart(View *v, QMouseEvent *e)
 {
-    std::cerr << "TimeValueLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl;
+//    std::cerr << "TimeValueLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl;
 
     if (!m_model) return;
 
@@ -918,7 +943,7 @@
 void
 TimeValueLayer::editDrag(View *v, QMouseEvent *e)
 {
-    std::cerr << "TimeValueLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl;
+//    std::cerr << "TimeValueLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl;
 
     if (!m_model || !m_editing) return;
 
@@ -942,7 +967,7 @@
 void
 TimeValueLayer::editEnd(View *v, QMouseEvent *e)
 {
-    std::cerr << "TimeValueLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl;
+//    std::cerr << "TimeValueLayer::editEnd(" << e->x() << "," << e->y() << ")" << std::endl;
     if (!m_model || !m_editing) return;
 
     if (m_editingCommand) {