changeset 559:5bcfc5606528

* Add option to import time+duration (or time+endtime) from CSV files (importing to Region layers) * Fix ffwd/rwd in Region layers so as to behave like time-value layers
author Chris Cannam
date Thu, 08 Jul 2010 14:22:28 +0000
parents 9fc13f61ae74
children e15afed2bfeb
files layer/RegionLayer.cpp layer/RegionLayer.h layer/TimeValueLayer.cpp widgets/CSVFormatDialog.cpp widgets/CSVFormatDialog.h
diffstat 5 files changed, 121 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/layer/RegionLayer.cpp	Tue Jun 22 09:45:42 2010 +0000
+++ b/layer/RegionLayer.cpp	Thu Jul 08 14:22:28 2010 +0000
@@ -517,6 +517,79 @@
     return found;
 }
 
+bool
+RegionLayer::snapToSimilarFeature(View *v, int &frame,
+                                  size_t &resolution,
+                                  SnapType snap) const
+{
+    if (!m_model) {
+	return Layer::snapToSimilarFeature(v, frame, resolution, snap);
+    }
+
+    resolution = m_model->getResolution();
+
+    const RegionModel::PointList &points = m_model->getPoints();
+    RegionModel::PointList close = m_model->getPoints(frame, frame);
+
+    RegionModel::PointList::const_iterator i;
+
+    int matchframe = frame;
+    float matchvalue = 0.f;
+
+    for (i = close.begin(); i != close.end(); ++i) {
+        if (i->frame > frame) break;
+        matchvalue = i->value;
+        matchframe = i->frame;
+    }
+
+    int snapped = frame;
+    bool found = false;
+    bool distant = false;
+    float epsilon = 0.0001;
+
+    i = close.begin();
+
+    // Scan through the close points first, then the more distant ones
+    // if no suitable close one is found
+
+    while (i != points.end()) {
+
+        if (i == close.end()) {
+            i = points.begin();
+            distant = true;
+        }
+
+	if (snap == SnapRight) {
+
+	    if (i->frame > matchframe &&
+                fabsf(i->value - matchvalue) < epsilon) {
+		snapped = i->frame;
+		found = true;
+		break;
+	    }
+
+	} else if (snap == SnapLeft) {
+
+	    if (i->frame < matchframe) {
+                if (fabsf(i->value - matchvalue) < epsilon) {
+                    snapped = i->frame;
+                    found = true; // don't break, as the next may be better
+                }
+	    } else if (found || distant) {
+		break;
+	    }
+
+	} else { 
+            // no other snap types supported
+	}
+
+        ++i;
+    }
+
+    frame = snapped;
+    return found;
+}
+
 void
 RegionLayer::getScaleExtents(View *v, float &min, float &max, bool &log) const
 {
@@ -847,6 +920,7 @@
                 RegionModel::Point::Comparator()(illuminatePoint, p) ||
                 RegionModel::Point::Comparator()(p, illuminatePoint)) {
 
+                paint.setPen(QPen(getForegroundQColor(v), 1));
                 paint.drawLine(x, 0, x, v->height());
                 paint.setPen(Qt::NoPen);
 
@@ -854,7 +928,7 @@
                 paint.setPen(QPen(getForegroundQColor(v), 2));
             }
 
-	    paint.drawRect(x, 0, ex - x, v->height() + 1);
+	    paint.drawRect(x, -1, ex - x, v->height() + 2);
 
 	} else {
 
--- a/layer/RegionLayer.h	Tue Jun 22 09:45:42 2010 +0000
+++ b/layer/RegionLayer.h	Thu Jul 08 14:22:28 2010 +0000
@@ -42,6 +42,9 @@
     virtual bool snapToFeatureFrame(View *v, int &frame,
 				    size_t &resolution,
 				    SnapType snap) const;
+    virtual bool snapToSimilarFeature(View *v, int &frame,
+                                      size_t &resolution,
+                                      SnapType snap) const;
 
     virtual void drawStart(View *v, QMouseEvent *);
     virtual void drawDrag(View *v, QMouseEvent *);
--- a/layer/TimeValueLayer.cpp	Tue Jun 22 09:45:42 2010 +0000
+++ b/layer/TimeValueLayer.cpp	Thu Jul 08 14:22:28 2010 +0000
@@ -1072,6 +1072,8 @@
 	    
 	    if (nx <= x) continue;
 
+            paint.setPen(QPen(getForegroundQColor(v), 2));
+
             if (illuminateFrame != p.frame) {
                 if (!m_drawSegmentDivisions ||
                     nx < x + 5 ||
--- a/widgets/CSVFormatDialog.cpp	Tue Jun 22 09:45:42 2010 +0000
+++ b/widgets/CSVFormatDialog.cpp	Thu Jul 08 14:22:28 2010 +0000
@@ -31,6 +31,7 @@
     QDialog(parent),
     m_modelType(CSVFormat::OneDimensionalModel),
     m_timingType(CSVFormat::ExplicitTiming),
+    m_durationType(CSVFormat::Durations),
     m_timeUnits(CSVFormat::TimeAudioFrames),
     m_separator(""),
     m_behaviour(QString::KeepEmptyParts)
@@ -40,6 +41,7 @@
 
     m_modelType = format.getModelType();
     m_timingType = format.getTimingType();
+    m_durationType = format.getDurationType();
     m_timeUnits = format.getTimeUnits();
     m_separator = format.getSeparator();
     m_sampleRate = format.getSampleRate();
@@ -58,6 +60,7 @@
     m_modelTypeCombo = new QComboBox;
     m_modelTypeCombo->addItem(tr("A point in time"));
     m_modelTypeCombo->addItem(tr("A value at a time"));
+    m_modelTypeCombo->addItem(tr("A value across a time range"));
     m_modelTypeCombo->addItem(tr("A set of values"));
     layout->addWidget(m_modelTypeCombo, 1, 1, 1, 2);
     connect(m_modelTypeCombo, SIGNAL(activated(int)),
@@ -76,8 +79,19 @@
     m_timingTypeCombo->setCurrentIndex(m_timingType == CSVFormat::ExplicitTiming ?
                                        m_timeUnits == CSVFormat::TimeSeconds ? 0 : 1 : 2);
 
+    m_durationTypeLabel = new QLabel(tr("The second column contains:"));
+    layout->addWidget(m_durationTypeLabel, 3, 0);
+    
+    m_durationTypeCombo = new QComboBox;
+    m_durationTypeCombo->addItem(tr("Duration"));
+    m_durationTypeCombo->addItem(tr("End time"));
+    layout->addWidget(m_durationTypeCombo, 3, 1, 1, 2);
+    connect(m_durationTypeCombo, SIGNAL(activated(int)),
+	    this, SLOT(durationTypeChanged(int)));
+    m_durationTypeCombo->setCurrentIndex(int(m_durationType));
+
     m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):"));
-    layout->addWidget(m_sampleRateLabel, 3, 0);
+    layout->addWidget(m_sampleRateLabel, 4, 0);
     
     size_t sampleRates[] = {
 	8000, 11025, 12000, 22050, 24000, 32000,
@@ -92,14 +106,14 @@
     }
     m_sampleRateCombo->setEditable(true);
 
-    layout->addWidget(m_sampleRateCombo, 3, 1);
+    layout->addWidget(m_sampleRateCombo, 4, 1);
     connect(m_sampleRateCombo, SIGNAL(activated(QString)),
 	    this, SLOT(sampleRateChanged(QString)));
     connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)),
 	    this, SLOT(sampleRateChanged(QString)));
 
     m_windowSizeLabel = new QLabel(tr("Frame increment between rows:"));
-    layout->addWidget(m_windowSizeLabel, 4, 0);
+    layout->addWidget(m_windowSizeLabel, 5, 0);
 
     m_windowSizeCombo = new QComboBox;
     m_windowSize = 1024;
@@ -110,30 +124,32 @@
     }
     m_windowSizeCombo->setEditable(true);
 
-    layout->addWidget(m_windowSizeCombo, 4, 1);
+    layout->addWidget(m_windowSizeCombo, 5, 1);
     connect(m_windowSizeCombo, SIGNAL(activated(QString)),
 	    this, SLOT(windowSizeChanged(QString)));
     connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)),
 	    this, SLOT(windowSizeChanged(QString)));
 
-    layout->addWidget(new QLabel(tr("\nExample data from file:")), 5, 0, 1, 4);
+    layout->addWidget(new QLabel(tr("\nExample data from file:")), 6, 0, 1, 4);
 
     m_exampleWidget = new QTableWidget
 	(std::min(10, m_example.size()), m_maxExampleCols);
 
-    layout->addWidget(m_exampleWidget, 6, 0, 1, 4);
+    layout->addWidget(m_exampleWidget, 7, 0, 1, 4);
     layout->setColumnStretch(3, 10);
     layout->setRowStretch(6, 10);
 
     QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok |
                                                 QDialogButtonBox::Cancel);
-    layout->addWidget(bb, 7, 0, 1, 4);
+    layout->addWidget(bb, 8, 0, 1, 4);
     connect(bb, SIGNAL(accepted()), this, SLOT(accept()));
     connect(bb, SIGNAL(rejected()), this, SLOT(reject()));
 
     setLayout(layout);
 
+    modelTypeChanged(m_modelTypeCombo->currentIndex());
     timingTypeChanged(m_timingTypeCombo->currentIndex());
+    durationTypeChanged(m_durationTypeCombo->currentIndex());
 }
 
 CSVFormatDialog::~CSVFormatDialog()
@@ -146,6 +162,7 @@
     CSVFormat format;
     format.setModelType(m_modelType);
     format.setTimingType(m_timingType);
+    format.setDurationType(m_durationType);
     format.setTimeUnits(m_timeUnits);
     format.setSeparator(m_separator);
     format.setSampleRate(m_sampleRate);
@@ -192,12 +209,13 @@
 {
     m_modelType = (CSVFormat::ModelType)type;
 
-//    if (m_modelType == CSVFormat::ThreeDimensionalModel) {
-        // We can't load 3d models with explicit timing, because the 3d
-        // model is dense so we need a fixed sample increment
-//        m_timingTypeCombo->setCurrentIndex(2);
-//        timingTypeChanged(2);
-//    }
+    if (m_modelType == CSVFormat::TwoDimensionalModelWithDuration) {
+        m_durationTypeCombo->setEnabled(true);
+        m_durationTypeLabel->setEnabled(true);
+    } else {
+        m_durationTypeCombo->setEnabled(false);
+        m_durationTypeLabel->setEnabled(false);
+    }
 }
 
 void
@@ -212,10 +230,6 @@
 	m_sampleRateLabel->setEnabled(false);
 	m_windowSizeCombo->setEnabled(false);
 	m_windowSizeLabel->setEnabled(false);
-//        if (m_modelType == CSVFormat::ThreeDimensionalModel) {
-//            m_modelTypeCombo->setCurrentIndex(1);
-//            modelTypeChanged(1);
-//        }
 	break;
 
     case 1:
@@ -225,10 +239,6 @@
 	m_sampleRateLabel->setEnabled(true);
 	m_windowSizeCombo->setEnabled(false);
 	m_windowSizeLabel->setEnabled(false);
-//        if (m_modelType == CSVFormat::ThreeDimensionalModel) {
-//            m_modelTypeCombo->setCurrentIndex(1);
-//            modelTypeChanged(1);
-//        }
 	break;
 
     case 2:
@@ -245,6 +255,12 @@
 }
 
 void
+CSVFormatDialog::durationTypeChanged(int type)
+{
+    m_durationType = (CSVFormat::DurationType)type;
+}
+
+void
 CSVFormatDialog::sampleRateChanged(QString rateString)
 {
     bool ok = false;
--- a/widgets/CSVFormatDialog.h	Tue Jun 22 09:45:42 2010 +0000
+++ b/widgets/CSVFormatDialog.h	Thu Jul 08 14:22:28 2010 +0000
@@ -38,12 +38,14 @@
 protected slots:
     void modelTypeChanged(int type);
     void timingTypeChanged(int type);
+    void durationTypeChanged(int type);
     void sampleRateChanged(QString);
     void windowSizeChanged(QString);
 
 protected:
     CSVFormat::ModelType  m_modelType;
     CSVFormat::TimingType m_timingType;
+    CSVFormat::DurationType m_durationType;
     CSVFormat::TimeUnits  m_timeUnits;
 
     QString    m_separator;
@@ -58,6 +60,8 @@
     
     QComboBox *m_modelTypeCombo;
     QComboBox *m_timingTypeCombo;
+    QLabel *m_durationTypeLabel;
+    QComboBox *m_durationTypeCombo;
     QLabel *m_sampleRateLabel;
     QComboBox *m_sampleRateCombo;
     QLabel *m_windowSizeLabel;