changeset 963:fa96108d552d osx-retina

Merge from default branch
author Chris Cannam
date Thu, 14 May 2015 15:39:47 +0100
parents 092de22db207 (current diff) b12cd1c2dad5 (diff)
children 9b4771ba2e3e
files layer/TimeValueLayer.cpp
diffstat 5 files changed, 217 insertions(+), 94 deletions(-) [+]
line wrap: on
line diff
--- a/layer/LayerFactory.cpp	Wed Apr 29 13:28:44 2015 +0100
+++ b/layer/LayerFactory.cpp	Thu May 14 15:39:47 2015 +0100
@@ -198,7 +198,10 @@
     LayerTypeSet types;
     types.insert(TimeInstants);
     types.insert(TimeValues);
-    types.insert(FlexiNotes);
+    // Because this is strictly a UI function -- list the layer types
+    // to show in a menu -- it should not contain FlexiNotes; the
+    // layer isn't meaningfully editable in SV
+//    types.insert(FlexiNotes);
     types.insert(Notes);
     types.insert(Regions);
     types.insert(Text);
--- a/layer/LayerFactory.h	Wed Apr 29 13:28:44 2015 +0100
+++ b/layer/LayerFactory.h	Thu May 14 15:39:47 2015 +0100
@@ -57,6 +57,11 @@
 
     typedef std::set<LayerType> LayerTypeSet;
     LayerTypeSet getValidLayerTypes(Model *model);
+
+    /**
+     * Return the set of layer types that an end user should be
+     * allowed to create, empty, for subsequent editing.
+     */
     LayerTypeSet getValidEmptyLayerTypes();
 
     LayerType getLayerType(const Layer *);
--- a/layer/TimeValueLayer.cpp	Wed Apr 29 13:28:44 2015 +0100
+++ b/layer/TimeValueLayer.cpp	Thu May 14 15:39:47 2015 +0100
@@ -20,6 +20,7 @@
 #include "base/Profiler.h"
 #include "base/LogRange.h"
 #include "base/RangeMapper.h"
+#include "base/Pitch.h"
 #include "ColourDatabase.h"
 #include "view/View.h"
 
@@ -606,20 +607,31 @@
 
     RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate());
     
+    QString valueText;
+    float value = points.begin()->value;
+    QString unit = getScaleUnits();
+
+    if (unit == "Hz") {
+        valueText = tr("%1 Hz (%2, %3)")
+            .arg(value)
+            .arg(Pitch::getPitchLabelForFrequency(value))
+            .arg(Pitch::getPitchForFrequency(value));
+    } else if (unit != "") {
+        valueText = tr("%1 %2").arg(value).arg(unit);
+    } else {
+        valueText = tr("%1").arg(value);
+    }
+    
     QString text;
-    QString unit = getScaleUnits();
-    if (unit != "") unit = " " + unit;
 
     if (points.begin()->label == "") {
-	text = QString(tr("Time:\t%1\nValue:\t%2%3\nNo label"))
+	text = QString(tr("Time:\t%1\nValue:\t%2\nNo label"))
 	    .arg(rt.toText(true).c_str())
-	    .arg(points.begin()->value)
-            .arg(unit);
+	    .arg(valueText);
     } else {
-	text = QString(tr("Time:\t%1\nValue:\t%2%3\nLabel:\t%4"))
+	text = QString(tr("Time:\t%1\nValue:\t%2\nLabel:\t%4"))
 	    .arg(rt.toText(true).c_str())
-	    .arg(points.begin()->value)
-            .arg(unit)
+	    .arg(valueText)
 	    .arg(points.begin()->label);
     }
 
--- a/widgets/CSVFormatDialog.cpp	Wed Apr 29 13:28:44 2015 +0100
+++ b/widgets/CSVFormatDialog.cpp	Thu May 14 15:39:47 2015 +0100
@@ -121,16 +121,37 @@
     layout->addWidget(new QLabel(tr("Timing is specified:")), row, 0);
     
     m_timingTypeCombo = new QComboBox;
-    m_timingTypeCombo->addItem(tr("Explicitly, in seconds"));
-    m_timingTypeCombo->addItem(tr("Explicitly, in milliseconds"));
-    m_timingTypeCombo->addItem(tr("Explicitly, in audio sample frames"));
-    m_timingTypeCombo->addItem(tr("Implicitly: rows are equally spaced in time"));
+
+    m_timingLabels = {
+        { TimingExplicitSeconds, tr("Explicitly, in seconds") },
+        { TimingExplicitMsec, tr("Explicitly, in milliseconds") },
+        { TimingExplicitSamples, tr("Explicitly, in audio sample frames") },
+        { TimingImplicit, tr("Implicitly: rows are equally spaced in time") }
+    };
+
+    for (auto &l: m_timingLabels) {
+        m_timingTypeCombo->addItem(l.second);
+    }
+
     layout->addWidget(m_timingTypeCombo, row++, 1, 1, 2);
+
     connect(m_timingTypeCombo, SIGNAL(activated(int)),
 	    this, SLOT(timingTypeChanged(int)));
-    m_timingTypeCombo->setCurrentIndex
-        (m_format.getTimingType() == CSVFormat::ExplicitTiming ?
-         m_format.getTimeUnits() == CSVFormat::TimeSeconds ? 0 : 2 : 3);
+
+    m_initialTimingOption = TimingImplicit;
+    if (m_format.getTimingType() == CSVFormat::ExplicitTiming) {
+        switch (m_format.getTimeUnits()) {
+        case CSVFormat::TimeSeconds:
+            m_initialTimingOption = TimingExplicitSeconds; break;
+        case CSVFormat::TimeMilliseconds:
+            m_initialTimingOption = TimingExplicitMsec; break;
+        case CSVFormat::TimeAudioFrames:
+            m_initialTimingOption = TimingExplicitSamples; break;
+        case CSVFormat::TimeWindows:
+            m_initialTimingOption = TimingImplicit; break;
+        }
+    }
+    m_timingTypeCombo->setCurrentIndex(int(m_initialTimingOption));
 
     m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):"));
     layout->addWidget(m_sampleRateLabel, row, 0);
@@ -189,7 +210,6 @@
     setLayout(layout);
 
     timingTypeChanged(m_timingTypeCombo->currentIndex());
-    updateModelLabel();
 }
 
 CSVFormatDialog::~CSVFormatDialog()
@@ -230,46 +250,61 @@
 }
 
 void
+CSVFormatDialog::applyStartTimePurpose()
+{
+    // First check if we already have any
+    for (int i = 0; i < m_format.getColumnCount(); ++i) {
+        QComboBox *cb = m_columnPurposeCombos[i];
+        if (cb->currentIndex() == int(CSVFormat::ColumnStartTime)) {
+            return;
+        }
+    }
+    // and if not, select one
+    for (int i = 0; i < m_format.getColumnCount(); ++i) {
+        QComboBox *cb = m_columnPurposeCombos[i];
+        if (cb->currentIndex() == int(CSVFormat::ColumnValue)) {
+            cb->setCurrentIndex(int(CSVFormat::ColumnStartTime));
+            return;
+        }
+    }
+}
+
+void
+CSVFormatDialog::removeStartTimePurpose()
+{
+    for (int i = 0; i < m_format.getColumnCount(); ++i) {
+        QComboBox *cb = m_columnPurposeCombos[i];
+        if (cb->currentIndex() == int(CSVFormat::ColumnStartTime)) {
+            cb->setCurrentIndex(int(CSVFormat::ColumnValue));
+        }
+    }
+}
+
+void
+CSVFormatDialog::updateComboVisibility()
+{
+    bool wantRate = (m_format.getTimingType() == CSVFormat::ImplicitTiming ||
+                     m_format.getTimeUnits() == CSVFormat::TimeAudioFrames);
+    bool wantWindow = (m_format.getTimingType() == CSVFormat::ImplicitTiming);
+    
+    m_sampleRateCombo->setEnabled(wantRate);
+    m_sampleRateLabel->setEnabled(wantRate);
+
+    m_windowSizeCombo->setEnabled(wantWindow);
+    m_windowSizeLabel->setEnabled(wantWindow);
+}
+
+void
 CSVFormatDialog::timingTypeChanged(int type)
 {
-    switch (type) {
-
-    case 0:
-	m_format.setTimingType(CSVFormat::ExplicitTiming);
-	m_format.setTimeUnits(CSVFormat::TimeSeconds);
-	m_sampleRateCombo->setEnabled(false);
-	m_sampleRateLabel->setEnabled(false);
-	m_windowSizeCombo->setEnabled(false);
-	m_windowSizeLabel->setEnabled(false);
-	break;
-
-    case 1:
-	m_format.setTimingType(CSVFormat::ExplicitTiming);
-	m_format.setTimeUnits(CSVFormat::TimeMilliseconds);
-	m_sampleRateCombo->setEnabled(true);
-	m_sampleRateLabel->setEnabled(true);
-	m_windowSizeCombo->setEnabled(false);
-	m_windowSizeLabel->setEnabled(false);
-	break;
-
-    case 2:
-	m_format.setTimingType(CSVFormat::ExplicitTiming);
-	m_format.setTimeUnits(CSVFormat::TimeAudioFrames);
-	m_sampleRateCombo->setEnabled(true);
-	m_sampleRateLabel->setEnabled(true);
-	m_windowSizeCombo->setEnabled(false);
-	m_windowSizeLabel->setEnabled(false);
-	break;
-
-    case 3:
-	m_format.setTimingType(CSVFormat::ImplicitTiming);
-	m_format.setTimeUnits(CSVFormat::TimeWindows);
-	m_sampleRateCombo->setEnabled(true);
-	m_sampleRateLabel->setEnabled(true);
-	m_windowSizeCombo->setEnabled(true);
-	m_windowSizeLabel->setEnabled(true);
-	break;
+    // Update any column purpose combos
+    if (TimingOption(type) == TimingImplicit) {
+        removeStartTimePurpose();
+    } else {
+        applyStartTimePurpose();
     }
+    updateFormatFromDialog();
+    updateComboVisibility();
 }
 
 void
@@ -292,43 +327,26 @@
 CSVFormatDialog::columnPurposeChanged(int p)
 {
     QObject *o = sender();
-
     QComboBox *cb = qobject_cast<QComboBox *>(o);
     if (!cb) return;
 
     CSVFormat::ColumnPurpose purpose = (CSVFormat::ColumnPurpose)p;
 
-    bool haveStartTime = false;
-    bool haveDuration = false;
-    bool havePitch = false;
-    int valueCount = 0;
-
+    bool haveStartTime = false; // so as to update timing type combo appropriately
+    
+    // Ensure the column purpose combos are consistent with one
+    // another, without reference to m_format (which we'll update
+    // separately)
+    
     for (int i = 0; i < m_columnPurposeCombos.size(); ++i) {
 
-        CSVFormat::ColumnPurpose cp = m_format.getColumnPurpose(i);
-
-        bool thisChanged = (cb == m_columnPurposeCombos[i]);
+        QComboBox *thisCombo = m_columnPurposeCombos[i];
         
-        if (thisChanged) {
-
-            cerr << "i == " << i << ", fuzzy == " << m_fuzzyColumn
-                      << ", p == " << p << endl;
-
-            if (i == m_fuzzyColumn) {
-                for (int j = i; j < m_format.getColumnCount(); ++j) {
-                    if (p == 0) { // Ignore
-                        m_format.setColumnPurpose(j, CSVFormat::ColumnUnknown);
-                    } else { // Value
-                        m_format.setColumnPurpose(j, CSVFormat::ColumnValue);
-                        ++valueCount;
-                    }
-                }
-                continue;
-            }
-
-            cp = purpose;
-
-        } else {
+        CSVFormat::ColumnPurpose cp = (CSVFormat::ColumnPurpose)
+            (thisCombo->currentIndex());
+        bool thisChanged = (cb == thisCombo);
+        
+        if (!thisChanged) {
 
             if (i == m_fuzzyColumn) continue;
 
@@ -353,29 +371,98 @@
                     cp = CSVFormat::ColumnUnknown;
                 }
             }
+
+            if (cp == CSVFormat::ColumnStartTime) {
+                haveStartTime = true;
+            }
+        
+            thisCombo->setCurrentIndex(int(cp));
+
+        } else {
+            if (purpose == CSVFormat::ColumnStartTime) {
+                haveStartTime = true;
+            }
         }
+    }
 
-        if (cp == CSVFormat::ColumnStartTime) {
+    if (!haveStartTime) {
+        m_timingTypeCombo->setCurrentIndex(int(TimingImplicit));
+    } else if (m_timingTypeCombo->currentIndex() == int(TimingImplicit)) {
+        if (m_initialTimingOption == TimingImplicit) {
+            m_timingTypeCombo->setCurrentIndex(TimingExplicitSeconds);
+        } else {
+            m_timingTypeCombo->setCurrentIndex(m_initialTimingOption);
+        }
+    }
+
+    updateFormatFromDialog();
+    updateComboVisibility();
+}
+
+void
+CSVFormatDialog::updateFormatFromDialog()
+{
+    switch (TimingOption(m_timingTypeCombo->currentIndex())) {
+
+    case TimingExplicitSeconds:
+	m_format.setTimingType(CSVFormat::ExplicitTiming);
+	m_format.setTimeUnits(CSVFormat::TimeSeconds);
+	break;
+
+    case TimingExplicitMsec:
+	m_format.setTimingType(CSVFormat::ExplicitTiming);
+	m_format.setTimeUnits(CSVFormat::TimeMilliseconds);
+	break;
+
+    case TimingExplicitSamples:
+	m_format.setTimingType(CSVFormat::ExplicitTiming);
+	m_format.setTimeUnits(CSVFormat::TimeAudioFrames);
+	break;
+
+    case TimingImplicit:
+	m_format.setTimingType(CSVFormat::ImplicitTiming);
+	m_format.setTimeUnits(CSVFormat::TimeWindows);
+	break;
+    }
+
+    bool haveStartTime = false;
+    bool haveDuration = false;
+    bool havePitch = false;
+    int valueCount = 0;
+
+    for (int i = 0; i < m_columnPurposeCombos.size(); ++i) {
+
+        QComboBox *thisCombo = m_columnPurposeCombos[i];
+        
+        CSVFormat::ColumnPurpose purpose = (CSVFormat::ColumnPurpose)
+            (thisCombo->currentIndex());
+
+        if (purpose == CSVFormat::ColumnStartTime) {
             haveStartTime = true;
         }
-        if (cp == CSVFormat::ColumnEndTime ||
-            cp == CSVFormat::ColumnDuration) {
+        if (purpose == CSVFormat::ColumnEndTime ||
+            purpose == CSVFormat::ColumnDuration) {
             haveDuration = true;
         }
-        if (cp == CSVFormat::ColumnPitch) {
+        if (purpose == CSVFormat::ColumnPitch) {
             havePitch = true;
         }
-        if (cp == CSVFormat::ColumnValue) {
+        if (purpose == CSVFormat::ColumnValue) {
             ++valueCount;
         }
 
-        m_columnPurposeCombos[i]->setCurrentIndex(int(cp));
-        m_format.setColumnPurpose(i, cp);
-    }
+        m_format.setColumnPurpose(i, purpose);
 
-    if (!haveStartTime) {
-        m_timingTypeCombo->setCurrentIndex(2);
-        timingTypeChanged(2);
+        if (i == m_fuzzyColumn) {
+            for (int j = i + 1; j < m_format.getColumnCount(); ++j) {
+                if (purpose == CSVFormat::ColumnUnknown) {
+                    m_format.setColumnPurpose(j, CSVFormat::ColumnUnknown);
+                } else { // Value
+                    m_format.setColumnPurpose(j, CSVFormat::ColumnValue);
+                    ++valueCount;
+                }
+            }
+        }
     }
 
     if (haveStartTime && haveDuration) {
@@ -398,3 +485,4 @@
 }
 
 
+
--- a/widgets/CSVFormatDialog.h	Wed Apr 29 13:28:44 2015 +0100
+++ b/widgets/CSVFormatDialog.h	Thu May 14 15:39:47 2015 +0100
@@ -40,11 +40,26 @@
     void sampleRateChanged(QString);
     void windowSizeChanged(QString);
     void columnPurposeChanged(int purpose);
+
+    void updateFormatFromDialog();
     void updateModelLabel();
 
 protected:
     CSVFormat m_format;
     int m_maxDisplayCols;
+
+    enum TimingOption {
+        TimingExplicitSeconds = 0,
+        TimingExplicitMsec,
+        TimingExplicitSamples,
+        TimingImplicit
+    };
+    std::map<TimingOption, QString> m_timingLabels;
+    TimingOption m_initialTimingOption;
+
+    void updateComboVisibility();
+    void applyStartTimePurpose();
+    void removeStartTimePurpose();
     
     QComboBox *m_timingTypeCombo;
     QLabel *m_sampleRateLabel;