# HG changeset patch # User Chris Cannam # Date 1434356155 -3600 # Node ID f2c63ec85901312aa93045df4942e903c90abb87 # Parent 36cddc3de02351400296093def5e461be4a24ac9# Parent b8187c83b93aa9de7eb0a3718a1488a2c8cdf4ae Branch to test simple FFT model code diff -r 36cddc3de023 -r f2c63ec85901 layer/Colour3DPlotLayer.cpp --- a/layer/Colour3DPlotLayer.cpp Mon Apr 20 09:19:52 2015 +0100 +++ b/layer/Colour3DPlotLayer.cpp Mon Jun 15 09:15:55 2015 +0100 @@ -54,6 +54,7 @@ m_normalizeVisibleArea(false), m_normalizeHybrid(false), m_invertVertical(false), + m_rectified(false), m_opaque(false), m_smooth(false), m_peakResolution(256), @@ -162,6 +163,7 @@ list.push_back("Gain"); list.push_back("Bin Scale"); list.push_back("Invert Vertical Scale"); + list.push_back("Show Rectified"); list.push_back("Opaque"); list.push_back("Smooth"); return list; @@ -175,6 +177,7 @@ if (name == "Normalize Columns") return tr("Normalize Columns"); if (name == "Normalize Visible Area") return tr("Normalize Visible Area"); if (name == "Invert Vertical Scale") return tr("Invert Vertical Scale"); + if (name == "Show Rectified") return tr("Half-Wave Rectify"); if (name == "Gain") return tr("Gain"); if (name == "Opaque") return tr("Always Opaque"); if (name == "Smooth") return tr("Smooth"); @@ -188,6 +191,7 @@ if (name == "Normalize Columns") return "normalise-columns"; if (name == "Normalize Visible Area") return "normalise"; if (name == "Invert Vertical Scale") return "invert-vertical"; + if (name == "Show Rectified") return "derivative"; if (name == "Opaque") return "opaque"; if (name == "Smooth") return "smooth"; return ""; @@ -200,6 +204,7 @@ if (name == "Normalize Columns") return ToggleProperty; if (name == "Normalize Visible Area") return ToggleProperty; if (name == "Invert Vertical Scale") return ToggleProperty; + if (name == "Show Rectified") return ToggleProperty; if (name == "Opaque") return ToggleProperty; if (name == "Smooth") return ToggleProperty; return ValueProperty; @@ -211,6 +216,7 @@ if (name == "Normalize Columns" || name == "Normalize Visible Area" || name == "Colour Scale" || + name == "Show Rectified" || name == "Gain") return tr("Scale"); if (name == "Bin Scale" || name == "Invert Vertical Scale") return tr("Bins"); @@ -275,6 +281,13 @@ *deflt = 0; val = (m_invertVertical ? 1 : 0); + } else if (name == "Show Rectified") { + + if (min) *min = 0; + if (max) *max = 0; + if (deflt) *deflt = 0; + val = (m_rectified ? 1.0 : 0.0); + } else if (name == "Bin Scale") { *min = 0; @@ -355,6 +368,8 @@ setNormalizeVisibleArea(value ? true : false); } else if (name == "Invert Vertical Scale") { setInvertVertical(value ? true : false); + } else if (name == "Show Rectified") { + setShowRectified(value > 0.5); } else if (name == "Opaque") { setOpaque(value ? true : false); } else if (name == "Smooth") { @@ -472,6 +487,15 @@ } void +Colour3DPlotLayer::setShowRectified(bool show) +{ + if (m_rectified == show) return; + m_rectified = show; + cacheInvalid(); + emit layerParametersChanged(); +} + +void Colour3DPlotLayer::setOpaque(bool n) { if (m_opaque == n) return; @@ -930,7 +954,20 @@ { Profiler profiler("Colour3DPlotLayer::getColumn"); + DenseThreeDimensionalModel::Column prev; + if (m_rectified && (col > m_model->getStartFrame())) { + prev = m_model->getColumn(col - 1); + } + DenseThreeDimensionalModel::Column values = m_model->getColumn(col); + + if (m_rectified && !prev.empty()) { + for (int y = 0; y < values.size(); ++y) { + if (values[y] < prev[y]) values[y] = 0; + else values[y] -= prev[y]; + } + } + while (values.size() < m_model->getHeight()) values.push_back(0.f); if (!m_normalizeColumns && !m_normalizeHybrid) return values; diff -r 36cddc3de023 -r f2c63ec85901 layer/Colour3DPlotLayer.h --- a/layer/Colour3DPlotLayer.h Mon Apr 20 09:19:52 2015 +0100 +++ b/layer/Colour3DPlotLayer.h Mon Jun 15 09:15:55 2015 +0100 @@ -139,6 +139,9 @@ void setInvertVertical(bool i); bool getInvertVertical() const; + void setShowRectified(bool); + bool getShowRectified() const { return m_rectified; } + void setOpaque(bool i); bool getOpaque() const; @@ -187,6 +190,7 @@ bool m_normalizeVisibleArea; bool m_normalizeHybrid; bool m_invertVertical; + bool m_rectified; bool m_opaque; bool m_smooth; int m_peakResolution; diff -r 36cddc3de023 -r f2c63ec85901 layer/Layer.h --- a/layer/Layer.h Mon Apr 20 09:19:52 2015 +0100 +++ b/layer/Layer.h Mon Jun 15 09:15:55 2015 +0100 @@ -62,7 +62,7 @@ Model *getModel() { return const_cast(const_cast(this)->getModel()); } - + /** * Return a zoom constraint object defining the supported zoom * levels for this layer. If this returns zero, the layer will @@ -518,6 +518,13 @@ */ virtual RangeMapper *getNewVerticalZoomRangeMapper() const { return 0; } + /** + * Return true if this layer type can function without a model + * being set. If false (the default), the layer will not be loaded + * from a session if its model cannot be found. + */ + virtual bool canExistWithoutModel() const { return false; } + public slots: void showLayer(View *, bool show); diff -r 36cddc3de023 -r f2c63ec85901 layer/LayerFactory.cpp --- a/layer/LayerFactory.cpp Mon Apr 20 09:19:52 2015 +0100 +++ b/layer/LayerFactory.cpp Mon Jun 15 09:15:55 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); diff -r 36cddc3de023 -r f2c63ec85901 layer/LayerFactory.h --- a/layer/LayerFactory.h Mon Apr 20 09:19:52 2015 +0100 +++ b/layer/LayerFactory.h Mon Jun 15 09:15:55 2015 +0100 @@ -57,6 +57,11 @@ typedef std::set 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 *); diff -r 36cddc3de023 -r f2c63ec85901 layer/SpectrogramLayer.cpp --- a/layer/SpectrogramLayer.cpp Mon Apr 20 09:19:52 2015 +0100 +++ b/layer/SpectrogramLayer.cpp Mon Jun 15 09:15:55 2015 +0100 @@ -1629,10 +1629,7 @@ m_windowType, m_windowSize, getWindowIncrement(), - fftSize, - true, // polar - StorageAdviser::SpeedCritical, - m_candidateFillStartFrame); + fftSize); if (!model->isOK()) { QMessageBox::critical @@ -1654,8 +1651,6 @@ m_fftModels[v] = FFTFillPair(model, 0); - model->resume(); - delete m_updateTimer; m_updateTimer = new QTimer((SpectrogramLayer *)this); connect(m_updateTimer, SIGNAL(timeout()), @@ -2445,8 +2440,6 @@ (void)gettimeofday(&tv, 0); m_lastPaintTime = RealTime::fromTimeval(tv) - mainPaintStart; } - -//!!! if (fftSuspended) fft->resume(); } bool diff -r 36cddc3de023 -r f2c63ec85901 layer/SpectrumLayer.cpp --- a/layer/SpectrumLayer.cpp Mon Apr 20 09:19:52 2015 +0100 +++ b/layer/SpectrumLayer.cpp Mon Jun 15 09:15:55 2015 +0100 @@ -112,11 +112,7 @@ m_windowType, m_windowSize, getWindowIncrement(), - m_windowSize, - false, - StorageAdviser::Criteria - (StorageAdviser::SpeedCritical | - StorageAdviser::FrequentLookupLikely)); + m_windowSize); setSliceableModel(newFFT); @@ -125,8 +121,6 @@ m_biasCurve.push_back(1.f / (float(m_windowSize)/2.f)); } - newFFT->resume(); - m_newFFTNeeded = false; } diff -r 36cddc3de023 -r f2c63ec85901 layer/TimeRulerLayer.h --- a/layer/TimeRulerLayer.h Mon Apr 20 09:19:52 2015 +0100 +++ b/layer/TimeRulerLayer.h Mon Jun 15 09:15:55 2015 +0100 @@ -60,6 +60,8 @@ void setProperties(const QXmlAttributes &attributes); + virtual bool canExistWithoutModel() const { return true; } + protected: Model *m_model; LabelHeight m_labelHeight; diff -r 36cddc3de023 -r f2c63ec85901 layer/TimeValueLayer.cpp --- a/layer/TimeValueLayer.cpp Mon Apr 20 09:19:52 2015 +0100 +++ b/layer/TimeValueLayer.cpp Mon Jun 15 09:15:55 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); } diff -r 36cddc3de023 -r f2c63ec85901 layer/WaveformLayer.h --- a/layer/WaveformLayer.h Mon Apr 20 09:19:52 2015 +0100 +++ b/layer/WaveformLayer.h Mon Jun 15 09:15:55 2015 +0100 @@ -202,6 +202,8 @@ virtual int getCurrentVerticalZoomStep() const; virtual void setVerticalZoomStep(int); + virtual bool canExistWithoutModel() const { return true; } + protected: int dBscale(double sample, int m) const; diff -r 36cddc3de023 -r f2c63ec85901 view/AlignmentView.cpp --- a/view/AlignmentView.cpp Mon Apr 20 09:19:52 2015 +0100 +++ b/view/AlignmentView.cpp Mon Jun 15 09:15:55 2015 +0100 @@ -32,14 +32,14 @@ } void -AlignmentView::globalCentreFrameChanged(int f) +AlignmentView::globalCentreFrameChanged(sv_frame_t f) { View::globalCentreFrameChanged(f); update(); } void -AlignmentView::viewCentreFrameChanged(View *v, int f) +AlignmentView::viewCentreFrameChanged(View *v, sv_frame_t f) { View::viewCentreFrameChanged(v, f); if (v == m_above) { @@ -51,7 +51,7 @@ } void -AlignmentView::viewManagerPlaybackFrameChanged(int) +AlignmentView::viewManagerPlaybackFrameChanged(sv_frame_t) { update(); } @@ -127,12 +127,12 @@ paint.fillRect(rect(), bg); - vector keyFrames = getKeyFrames(); + vector keyFrames = getKeyFrames(); - foreach (int f, keyFrames) { + foreach (sv_frame_t f, keyFrames) { int ax = m_above->getXForFrame(f); - int rf = m_above->alignToReference(f); - int bf = m_below->alignFromReference(rf); + sv_frame_t rf = m_above->alignToReference(f); + sv_frame_t bf = m_below->alignFromReference(rf); int bx = m_below->getXForFrame(bf); paint.drawLine(ax, 0, bx, height()); } @@ -140,7 +140,7 @@ paint.end(); } -vector +vector AlignmentView::getKeyFrames() { if (!m_above) { @@ -163,7 +163,7 @@ return getDefaultKeyFrames(); } - vector keyFrames; + vector keyFrames; const SparseOneDimensionalModel::PointList pp = m->getPoints(); for (SparseOneDimensionalModel::PointList::const_iterator pi = pp.begin(); @@ -174,19 +174,19 @@ return keyFrames; } -vector +vector AlignmentView::getDefaultKeyFrames() { - vector keyFrames; + vector keyFrames; if (!m_above || !m_manager) return keyFrames; - int rate = m_manager->getMainModelSampleRate(); + sv_samplerate_t rate = m_manager->getMainModelSampleRate(); if (rate == 0) return keyFrames; - for (int f = m_above->getModelsStartFrame(); + for (sv_frame_t f = m_above->getModelsStartFrame(); f <= m_above->getModelsEndFrame(); - f += rate * 5) { + f += sv_frame_t(rate * 5 + 0.5)) { keyFrames.push_back(f); } diff -r 36cddc3de023 -r f2c63ec85901 view/AlignmentView.h --- a/view/AlignmentView.h Mon Apr 20 09:19:52 2015 +0100 +++ b/view/AlignmentView.h Mon Jun 15 09:15:55 2015 +0100 @@ -30,18 +30,18 @@ void setViewBelow(View *view); public slots: - virtual void globalCentreFrameChanged(int); - virtual void viewCentreFrameChanged(View *, int); + virtual void globalCentreFrameChanged(sv_frame_t); + virtual void viewCentreFrameChanged(View *, sv_frame_t); virtual void viewAboveZoomLevelChanged(int, bool); virtual void viewBelowZoomLevelChanged(int, bool); - virtual void viewManagerPlaybackFrameChanged(int); + virtual void viewManagerPlaybackFrameChanged(sv_frame_t); protected: virtual void paintEvent(QPaintEvent *e); virtual bool shouldLabelSelections() const { return false; } - std::vector getKeyFrames(); - std::vector getDefaultKeyFrames(); + std::vector getKeyFrames(); + std::vector getDefaultKeyFrames(); View *m_above; View *m_below; diff -r 36cddc3de023 -r f2c63ec85901 view/Overview.cpp --- a/view/Overview.cpp Mon Apr 20 09:19:52 2015 +0100 +++ b/view/Overview.cpp Mon Jun 15 09:15:55 2015 +0100 @@ -35,6 +35,10 @@ m_followZoom = false; setPlaybackFollow(PlaybackIgnore); m_modelTestTime.start(); + + bool light = hasLightBackground(); + if (light) m_boxColour = Qt::darkGray; + else m_boxColour = Qt::lightGray; } void @@ -159,6 +163,12 @@ } void +Overview::setBoxColour(QColor c) +{ + m_boxColour = c; +} + +void Overview::paintEvent(QPaintEvent *e) { // Recalculate zoom in case the size of the widget has changed. @@ -263,7 +273,7 @@ foreach (QRect vr, rects) { paint.setBrush(Qt::NoBrush); - paint.setPen(QPen(Qt::gray, 2)); + paint.setPen(QPen(m_boxColour, 2)); paint.drawRoundedRect(vr, 4, 4); } diff -r 36cddc3de023 -r f2c63ec85901 view/Overview.h --- a/view/Overview.h Mon Apr 20 09:19:52 2015 +0100 +++ b/view/Overview.h Mon Jun 15 09:15:55 2015 +0100 @@ -49,6 +49,8 @@ virtual void viewZoomLevelChanged(View *, int, bool); virtual void viewManagerPlaybackFrameChanged(sv_frame_t); + virtual void setBoxColour(QColor); + protected: virtual void paintEvent(QPaintEvent *e); virtual void mousePressEvent(QMouseEvent *e); @@ -67,6 +69,7 @@ bool m_clickedInRange; sv_frame_t m_dragCentreFrame; QTime m_modelTestTime; + QColor m_boxColour; typedef std::set ViewSet; ViewSet m_views; diff -r 36cddc3de023 -r f2c63ec85901 view/Pane.cpp --- a/view/Pane.cpp Mon Apr 20 09:19:52 2015 +0100 +++ b/view/Pane.cpp Mon Jun 15 09:15:55 2015 +0100 @@ -388,10 +388,10 @@ Pane::selectionIsBeingEdited() const { if (!m_editingSelection.isEmpty()) { - if (m_mousePos != m_clickPos && - getFrameForX(m_mousePos.x()) != getFrameForX(m_clickPos.x())) { - return true; - } + if (m_mousePos != m_clickPos && + getFrameForX(m_mousePos.x()) != getFrameForX(m_clickPos.x())) { + return true; + } } return false; } @@ -2115,14 +2115,25 @@ max = snapFrameRight; } + sv_frame_t end = getModelsEndFrame(); + if (min > end) min = end; + if (max > end) max = end; + if (m_manager) { - m_manager->setInProgressSelection(Selection(alignToReference(min), - alignToReference(max)), - !m_resizing && !m_ctrlPressed); + + Selection sel(alignToReference(min), alignToReference(max)); + + bool exc; + bool same = (m_manager->haveInProgressSelection() && + m_manager->getInProgressSelection(exc) == sel); + + m_manager->setInProgressSelection(sel, !m_resizing && !m_ctrlPressed); + + if (!same) { + edgeScrollMaybe(e->x()); + } } - edgeScrollMaybe(e->x()); - update(); if (min != max) { @@ -2145,11 +2156,12 @@ sv_frame_t offset = mouseFrame - getStartFrame(); sv_frame_t available = getEndFrame() - getStartFrame(); sv_frame_t move = 0; - if (offset >= double(available) * 0.95) { - move = sv_frame_t(double(offset - available) * 0.95) + 1; - } else if (offset <= double(available) * 0.10) { - move = sv_frame_t(double(available) * 0.10 - double(offset)) + 1; - move = -move; + sv_frame_t rightEdge = available - (available / 20); + sv_frame_t leftEdge = (available / 10); + if (offset >= rightEdge) { + move = offset - rightEdge + 1; + } else if (offset <= leftEdge) { + move = offset - leftEdge - 1; } if (move != 0) { setCentreFrame(m_centreFrame + move); diff -r 36cddc3de023 -r f2c63ec85901 view/ViewManager.cpp --- a/view/ViewManager.cpp Mon Apr 20 09:19:52 2015 +0100 +++ b/view/ViewManager.cpp Mon Jun 15 09:15:55 2015 +0100 @@ -166,6 +166,7 @@ void ViewManager::setPlaybackFrame(sv_frame_t f) { + if (f < 0) f = 0; if (m_playbackFrame != f) { m_playbackFrame = f; emit playbackFrameChanged(f); diff -r 36cddc3de023 -r f2c63ec85901 widgets/CSVFormatDialog.cpp --- a/widgets/CSVFormatDialog.cpp Mon Apr 20 09:19:52 2015 +0100 +++ b/widgets/CSVFormatDialog.cpp Mon Jun 15 09:15:55 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,66 @@ } void +CSVFormatDialog::applyStartTimePurpose() +{ + // First check if we already have any. NB there may be fewer than + // m_format.getColumnCount() elements in m_columnPurposeCombos + // (because of the fuzzy column behaviour) + for (int i = 0; i < m_columnPurposeCombos.size(); ++i) { + QComboBox *cb = m_columnPurposeCombos[i]; + if (cb->currentIndex() == int(CSVFormat::ColumnStartTime)) { + return; + } + } + // and if not, select one + for (int i = 0; i < m_columnPurposeCombos.size(); ++i) { + QComboBox *cb = m_columnPurposeCombos[i]; + if (cb->currentIndex() == int(CSVFormat::ColumnValue)) { + cb->setCurrentIndex(int(CSVFormat::ColumnStartTime)); + return; + } + } +} + +void +CSVFormatDialog::removeStartTimePurpose() +{ + // NB there may be fewer than m_format.getColumnCount() elements + // in m_columnPurposeCombos (because of the fuzzy column + // behaviour) + for (int i = 0; i < m_columnPurposeCombos.size(); ++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 +332,26 @@ CSVFormatDialog::columnPurposeChanged(int p) { QObject *o = sender(); - QComboBox *cb = qobject_cast(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 +376,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 +490,4 @@ } + diff -r 36cddc3de023 -r f2c63ec85901 widgets/CSVFormatDialog.h --- a/widgets/CSVFormatDialog.h Mon Apr 20 09:19:52 2015 +0100 +++ b/widgets/CSVFormatDialog.h Mon Jun 15 09:15:55 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 m_timingLabels; + TimingOption m_initialTimingOption; + + void updateComboVisibility(); + void applyStartTimePurpose(); + void removeStartTimePurpose(); QComboBox *m_timingTypeCombo; QLabel *m_sampleRateLabel; diff -r 36cddc3de023 -r f2c63ec85901 widgets/WindowShapePreview.cpp --- a/widgets/WindowShapePreview.cpp Mon Apr 20 09:19:52 2015 +0100 +++ b/widgets/WindowShapePreview.cpp Mon Jun 15 09:15:55 2015 +0100 @@ -209,7 +209,6 @@ void WindowShapePreview::setWindowType(WindowType type) { - if (m_windowType == type) return; m_windowType = type; updateLabels(); } diff -r 36cddc3de023 -r f2c63ec85901 widgets/WindowTypeSelector.cpp --- a/widgets/WindowTypeSelector.cpp Mon Apr 20 09:19:52 2015 +0100 +++ b/widgets/WindowTypeSelector.cpp Mon Jun 15 09:15:55 2015 +0100 @@ -78,7 +78,9 @@ connect(m_windowCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(windowIndexChanged(int))); - windowIndexChanged(index); + + m_windowType = defaultType; + m_windowShape->setWindowType(m_windowType); } WindowTypeSelector::~WindowTypeSelector()