# HG changeset patch # User Chris Cannam # Date 1181838507 0 # Node ID 11021509c4eb88ae84aab17395d426964f32bf39 # Parent 6d113226bb4c81c27d48b429c9af3561f21bf129 * some more work on measurement tool, and refactor Pane::paintEvent diff -r 6d113226bb4c -r 11021509c4eb layer/SpectrogramLayer.cpp --- a/layer/SpectrogramLayer.cpp Thu Jun 14 15:20:49 2007 +0000 +++ b/layer/SpectrogramLayer.cpp Thu Jun 14 16:28:27 2007 +0000 @@ -2469,6 +2469,15 @@ } bool +SpectrogramLayer::getYScaleValue(View *v, int y, + float &value, QString &unit) const +{ + value = getFrequencyForY(v, y); + unit = "Hz"; + return true; +} + +bool SpectrogramLayer::snapToFeatureFrame(View *, int &frame, size_t &resolution, SnapType snap) const diff -r 6d113226bb4c -r 11021509c4eb layer/SpectrogramLayer.h --- a/layer/SpectrogramLayer.h Thu Jun 14 15:20:49 2007 +0000 +++ b/layer/SpectrogramLayer.h Thu Jun 14 16:28:27 2007 +0000 @@ -200,6 +200,8 @@ virtual bool setDisplayExtents(float min, float max); + virtual bool getYScaleValue(View *, int, float &, QString &) const; + virtual QString toXmlString(QString indent = "", QString extraAttributes = "") const; diff -r 6d113226bb4c -r 11021509c4eb layer/WaveformLayer.cpp --- a/layer/WaveformLayer.cpp Thu Jun 14 15:20:49 2007 +0000 +++ b/layer/WaveformLayer.cpp Thu Jun 14 16:28:27 2007 +0000 @@ -388,7 +388,6 @@ int WaveformLayer::dBscale(float sample, int m) const { -//!!! if (sample < 0.0) return -dBscale(-sample, m); if (sample < 0.0) return dBscale(-sample, m); float dB = AudioLevel::multiplier_to_dB(sample); if (dB < -50.0) return 0; @@ -1033,6 +1032,75 @@ return my - vy; } +float +WaveformLayer::getValueForY(View *v, Scale scale, int y, + size_t minChannel, size_t maxChannel) const +{ + if (maxChannel < minChannel) return 0; + + int h = v->height(); + + int channels = maxChannel - minChannel + 1; + int m = (h / channels) / 2; + + if ((m_scale == dBScale || m_scale == MeterScale) && + m_channelMode != MergeChannels) { + m = (h / channels); + } + + int channel = minChannel; + int mind = 0; + + for (int c = minChannel; c <= maxChannel; ++c) { + int my = m + (((c - minChannel) * h) / channels); + int d = y - my; + if (d < 0) d = -d; + if (c == minChannel || d < mind) { + mind = d; + channel = c; + } + } + + int my = m + (((channel - minChannel) * h) / channels); + + int vy = y - my; + float value = 0; + + switch (scale) { + + case LinearScale: + value = float(vy) / m; + break; + + case MeterScale: + value = AudioLevel::preview_to_multiplier(vy, m); + break; + + case dBScale: + value = AudioLevel::dB_to_multiplier((50 * float(vy)) / m - 50); + break; + } + + return value; +} + +bool +WaveformLayer::getYScaleValue(View *v, int y, + float &value, QString &unit) const +{ + size_t channels = 0, minChannel = 0, maxChannel = 0; + bool mergingChannels = false, mixingChannels = false; + + channels = getChannelArrangement(minChannel, maxChannel, + mergingChannels, mixingChannels); + + if (channels == 0) return false; + + value = getValueForY(v, m_scale, y, minChannel, maxChannel); + unit = "V"; + return true; +} + int WaveformLayer::getVerticalScaleWidth(View *, QPainter &paint) const { diff -r 6d113226bb4c -r 11021509c4eb layer/WaveformLayer.h --- a/layer/WaveformLayer.h Thu Jun 14 15:20:49 2007 +0000 +++ b/layer/WaveformLayer.h Thu Jun 14 16:28:27 2007 +0000 @@ -179,6 +179,9 @@ virtual bool getValueExtents(float &min, float &max, bool &log, QString &unit) const; + virtual bool getYScaleValue(View *v, int y, + float &value, QString &unit) const; + virtual QString toXmlString(QString indent = "", QString extraAttributes = "") const; @@ -200,6 +203,9 @@ int getYForValue(View *v, Scale scale, float value, size_t channel, size_t minChannel, size_t maxChannel) const; + float getValueForY(View *v, Scale scale, int y, + size_t minChannel, size_t maxChannel) const; + float m_gain; bool m_autoNormalize; QColor m_colour; diff -r 6d113226bb4c -r 11021509c4eb view/Pane.cpp --- a/view/Pane.cpp Thu Jun 14 15:20:49 2007 +0000 +++ b/view/Pane.cpp Thu Jun 14 16:28:27 2007 +0000 @@ -360,35 +360,13 @@ QPainter paint; QRect r(rect()); + if (e) r = e->rect(); - if (e) { - r = e->rect(); - } -/* - paint.begin(this); - paint.setClipRect(r); - - if (hasLightBackground()) { - paint.setPen(Qt::white); - paint.setBrush(Qt::white); - } else { - paint.setPen(Qt::black); - paint.setBrush(Qt::black); - } - paint.drawRect(r); - - paint.end(); -*/ View::paintEvent(e); paint.begin(this); - if (e) { - paint.setClipRect(r); - } - - int fontHeight = paint.fontMetrics().height(); - int fontAscent = paint.fontMetrics().ascent(); + if (e) paint.setClipRect(r); ViewManager::ToolMode toolMode = m_manager->getToolMode(); @@ -422,80 +400,138 @@ } } + m_scaleWidth = 0; + + if (m_manager && m_manager->shouldShowVerticalScale() && topLayer) { + drawVerticalScale(r, topLayer, paint); + } + + if (m_identifyFeatures && topLayer) { + drawFeatureDescription(topLayer, paint); + } + + int sampleRate = getModelsSampleRate(); + paint.setBrush(Qt::NoBrush); + + if (m_centreLineVisible && + m_manager && + m_manager->shouldShowCentreLine()) { + drawCentreLine(sampleRate, paint); + } + + paint.setPen(QColor(50, 50, 50)); + + if (waveformModel && + m_manager && + m_manager->shouldShowDuration()) { + drawDurationAndRate(r, waveformModel, sampleRate, paint); + } + + if (m_manager && + m_manager->shouldShowLayerNames()) { + drawLayerNames(r, paint); + } + + if (m_clickedInRange && m_manager) { + + //!!! be nice if this looked a bit more in keeping with the + //selection block + + if (m_shiftPressed && toolMode == ViewManager::NavigateMode) { + + paint.setPen(Qt::blue); + //!!! shouldn't use clickPos -- needs to use a clicked frame + paint.drawRect(m_clickPos.x(), m_clickPos.y(), + m_mousePos.x() - m_clickPos.x(), + m_mousePos.y() - m_clickPos.y()); + + } else if (toolMode == ViewManager::MeasureMode && topLayer) { + + drawMeasurementRect(topLayer, paint); + } + } + + if (selectionIsBeingEdited()) { + drawEditingSelection(paint); + } + + paint.end(); +} + +void +Pane::drawVerticalScale(QRect r, Layer *topLayer, QPainter &paint) +{ Layer *scaleLayer = 0; - if (m_manager && m_manager->shouldShowVerticalScale() && topLayer) { + float min, max; + bool log; + QString unit; - float min, max; - bool log; - QString unit; + // If the top layer has no scale and reports no display + // extents, but does report a unit, then the scale should be + // drawn from any underlying layer with a scale and that unit. + // If the top layer has no scale and no value extents at all, + // then the scale should be drawn from any underlying layer + // with a scale regardless of unit. - // If the top layer has no scale and reports no display - // extents, but does report a unit, then the scale should be - // drawn from any underlying layer with a scale and that unit. - // If the top layer has no scale and no value extents at all, - // then the scale should be drawn from any underlying layer - // with a scale regardless of unit. + int sw = topLayer->getVerticalScaleWidth(this, paint); - int sw = topLayer->getVerticalScaleWidth(this, paint); + if (sw > 0) { + scaleLayer = topLayer; + m_scaleWidth = sw; - if (sw > 0) { - scaleLayer = topLayer; - m_scaleWidth = sw; + } else { - } else { + bool hasDisplayExtents = topLayer->getDisplayExtents(min, max); + bool hasValueExtents = topLayer->getValueExtents(min, max, log, unit); + + if (!hasDisplayExtents) { - bool hasDisplayExtents = topLayer->getDisplayExtents(min, max); - bool hasValueExtents = topLayer->getValueExtents(min, max, log, unit); - - if (!hasDisplayExtents) { + if (!hasValueExtents) { - if (!hasValueExtents) { + for (LayerList::iterator vi = m_layers.end(); + vi != m_layers.begin(); ) { + + --vi; + + if ((*vi) == topLayer) continue; + + sw = (*vi)->getVerticalScaleWidth(this, paint); + + if (sw > 0) { + scaleLayer = *vi; + m_scaleWidth = sw; + break; + } + } + } else if (unit != "") { // && hasValueExtents && !hasDisplayExtents - for (LayerList::iterator vi = m_layers.end(); - vi != m_layers.begin(); ) { + QString requireUnit = unit; + + for (LayerList::iterator vi = m_layers.end(); + vi != m_layers.begin(); ) { - --vi; + --vi; - if ((*vi) == topLayer) continue; + if ((*vi) == topLayer) continue; - sw = (*vi)->getVerticalScaleWidth(this, paint); - - if (sw > 0) { - scaleLayer = *vi; - m_scaleWidth = sw; - break; + if ((*vi)->getDisplayExtents(min, max)) { + + // search no further than this: if the + // scale from this layer isn't suitable, + // we'll have to draw no scale (else we'd + // risk ending up with the wrong scale) + + if ((*vi)->getValueExtents(min, max, log, unit) && + unit == requireUnit) { + + sw = (*vi)->getVerticalScaleWidth(this, paint); + if (sw > 0) { + scaleLayer = *vi; + m_scaleWidth = sw; + } } - } - } else if (unit != "") { // && hasValueExtents && !hasDisplayExtents - - QString requireUnit = unit; - - for (LayerList::iterator vi = m_layers.end(); - vi != m_layers.begin(); ) { - - --vi; - - if ((*vi) == topLayer) continue; - - if ((*vi)->getDisplayExtents(min, max)) { - - // search no further than this: if the - // scale from this layer isn't suitable, - // we'll have to draw no scale (else we'd - // risk ending up with the wrong scale) - - if ((*vi)->getValueExtents(min, max, log, unit) && - unit == requireUnit) { - - sw = (*vi)->getVerticalScaleWidth(this, paint); - if (sw > 0) { - scaleLayer = *vi; - m_scaleWidth = sw; - } - } - break; - } + break; } } } @@ -521,306 +557,341 @@ paint.restore(); } +} + +void +Pane::drawFeatureDescription(Layer *topLayer, QPainter &paint) +{ + QPoint pos = m_identifyPoint; + QString desc = topLayer->getFeatureDescription(this, pos); + + if (desc != "") { + + paint.save(); + + int tabStop = + paint.fontMetrics().width(tr("Some lengthy prefix:")); + + QRect boundingRect = + paint.fontMetrics().boundingRect + (rect(), + Qt::AlignRight | Qt::AlignTop | Qt::TextExpandTabs, + desc, tabStop); + + if (hasLightBackground()) { + paint.setPen(Qt::NoPen); + paint.setBrush(QColor(250, 250, 250, 200)); + } else { + paint.setPen(Qt::NoPen); + paint.setBrush(QColor(50, 50, 50, 200)); + } + + int extra = paint.fontMetrics().descent(); + paint.drawRect(width() - boundingRect.width() - 10 - extra, + 10 - extra, + boundingRect.width() + 2 * extra, + boundingRect.height() + extra); + + if (hasLightBackground()) { + paint.setPen(QColor(150, 20, 0)); + } else { + paint.setPen(QColor(255, 150, 100)); + } + + QTextOption option; + option.setWrapMode(QTextOption::NoWrap); + option.setAlignment(Qt::AlignRight | Qt::AlignTop); + option.setTabStop(tabStop); + paint.drawText(QRectF(width() - boundingRect.width() - 10, 10, + boundingRect.width(), + boundingRect.height()), + desc, + option); + + paint.restore(); + } +} - if (m_identifyFeatures && topLayer) { +void +Pane::drawCentreLine(int sampleRate, QPainter &paint) +{ + int fontHeight = paint.fontMetrics().height(); + int fontAscent = paint.fontMetrics().ascent(); + + QColor c = QColor(0, 0, 0); + if (!hasLightBackground()) { + c = QColor(240, 240, 240); + } + paint.setPen(c); + int x = width() / 2 + 1; + paint.drawLine(x, 0, x, height() - 1); + paint.drawLine(x-1, 1, x+1, 1); + paint.drawLine(x-2, 0, x+2, 0); + paint.drawLine(x-1, height() - 2, x+1, height() - 2); + paint.drawLine(x-2, height() - 1, x+2, height() - 1); + + paint.setPen(QColor(50, 50, 50)); + + int y = height() - fontHeight + fontAscent - 6; + + LayerList::iterator vi = m_layers.end(); + + if (vi != m_layers.begin()) { + + switch ((*--vi)->getPreferredFrameCountPosition()) { - QPoint pos = m_identifyPoint; - QString desc = topLayer->getFeatureDescription(this, pos); - - if (desc != "") { + case Layer::PositionTop: + y = fontAscent + 6; + break; - paint.save(); + case Layer::PositionMiddle: + y = (height() - fontHeight) / 2 + + fontAscent; + break; - int tabStop = - paint.fontMetrics().width(tr("Some lengthy prefix:")); - - QRect boundingRect = - paint.fontMetrics().boundingRect - (rect(), - Qt::AlignRight | Qt::AlignTop | Qt::TextExpandTabs, - desc, tabStop); - - if (hasLightBackground()) { - paint.setPen(Qt::NoPen); - paint.setBrush(QColor(250, 250, 250, 200)); - } else { - paint.setPen(Qt::NoPen); - paint.setBrush(QColor(50, 50, 50, 200)); - } - - int extra = paint.fontMetrics().descent(); - paint.drawRect(width() - boundingRect.width() - 10 - extra, - 10 - extra, - boundingRect.width() + 2 * extra, - boundingRect.height() + extra); - - if (hasLightBackground()) { - paint.setPen(QColor(150, 20, 0)); - } else { - paint.setPen(QColor(255, 150, 100)); - } - - QTextOption option; - option.setWrapMode(QTextOption::NoWrap); - option.setAlignment(Qt::AlignRight | Qt::AlignTop); - option.setTabStop(tabStop); - paint.drawText(QRectF(width() - boundingRect.width() - 10, 10, - boundingRect.width(), - boundingRect.height()), - desc, - option); - - paint.restore(); + case Layer::PositionBottom: + // y already set correctly + break; } } - int sampleRate = getModelsSampleRate(); - paint.setBrush(Qt::NoBrush); + if (m_manager && m_manager->shouldShowFrameCount()) { + + if (sampleRate) { - if (m_centreLineVisible && - m_manager && - m_manager->shouldShowCentreLine()) { - - QColor c = QColor(0, 0, 0); - if (!hasLightBackground()) { - c = QColor(240, 240, 240); - } - paint.setPen(c); - int x = width() / 2 + 1; - paint.drawLine(x, 0, x, height() - 1); - paint.drawLine(x-1, 1, x+1, 1); - paint.drawLine(x-2, 0, x+2, 0); - paint.drawLine(x-1, height() - 2, x+1, height() - 2); - paint.drawLine(x-2, height() - 1, x+2, height() - 1); - - paint.setPen(QColor(50, 50, 50)); - - int y = height() - fontHeight - + fontAscent - 6; - - LayerList::iterator vi = m_layers.end(); - - if (vi != m_layers.begin()) { - - switch ((*--vi)->getPreferredFrameCountPosition()) { - - case Layer::PositionTop: - y = fontAscent + 6; - break; - - case Layer::PositionMiddle: - y = (height() - fontHeight) / 2 - + fontAscent; - break; - - case Layer::PositionBottom: - // y already set correctly - break; - } - } - - if (m_manager && m_manager->shouldShowFrameCount()) { - - if (sampleRate) { - - QString text(QString::fromStdString - (RealTime::frame2RealTime - (m_centreFrame, sampleRate).toText(true))); - - int tw = paint.fontMetrics().width(text); - int x = width()/2 - 4 - tw; - - drawVisibleText(paint, x, y, text, OutlinedText); - } + QString text(QString::fromStdString + (RealTime::frame2RealTime + (m_centreFrame, sampleRate).toText(true))); - QString text = QString("%1").arg(m_centreFrame); - - int x = width()/2 + 4; + int tw = paint.fontMetrics().width(text); + int x = width()/2 - 4 - tw; drawVisibleText(paint, x, y, text, OutlinedText); } + + QString text = QString("%1").arg(m_centreFrame); + + int x = width()/2 + 4; + + drawVisibleText(paint, x, y, text, OutlinedText); + } +} - } else { +void +Pane::drawLayerNames(QRect r, QPainter &paint) +{ + int fontHeight = paint.fontMetrics().height(); + int fontAscent = paint.fontMetrics().ascent(); - paint.setPen(QColor(50, 50, 50)); + if (r.y() + r.height() < height() - int(m_layers.size()) * fontHeight - 6) { + return; } - if (waveformModel && - m_manager && - m_manager->shouldShowDuration() && - r.y() + r.height() >= height() - fontHeight - 6) { + std::vector texts; + int maxTextWidth = 0; - size_t modelRate = waveformModel->getSampleRate(); - size_t playbackRate = m_manager->getPlaybackSampleRate(); - size_t outputRate = m_manager->getOutputSampleRate(); + for (LayerList::iterator i = m_layers.begin(); i != m_layers.end(); ++i) { - QString srNote = ""; + QString text = (*i)->getLayerPresentationName(); + int tw = paint.fontMetrics().width(text); + bool reduced = false; + while (tw > width() / 3 && text.length() > 4) { + if (!reduced && text.length() > 8) { + text = text.left(text.length() - 4); + } else { + text = text.left(text.length() - 2); + } + reduced = true; + tw = paint.fontMetrics().width(text + "..."); + } + if (reduced) { + texts.push_back(text + "..."); + } else { + texts.push_back(text); + } + if (tw > maxTextWidth) maxTextWidth = tw; + } + + int lly = height() - 6; + int llx = width() - maxTextWidth - 5; + + if (m_manager->getZoomWheelsEnabled()) { + lly -= 20; + llx -= 36; + } + + if (r.x() + r.width() >= llx) { + + for (size_t i = 0; i < texts.size(); ++i) { + + if (i + 1 == texts.size()) { + paint.setPen(Qt::black); + } + + drawVisibleText(paint, llx, + lly - fontHeight + fontAscent, + texts[i], OutlinedText); + + lly -= fontHeight; + } + } +} - // Show (R) for waveform models that will be resampled on - // playback, and (X) for waveform models that will be played - // at the wrong rate because their rate differs from the - // current playback rate (which is not necessarily that of the - // main model). +void +Pane::drawMeasurementRect(Layer *topLayer, QPainter &paint) +{ + int fontHeight = paint.fontMetrics().height(); + int fontAscent = paint.fontMetrics().ascent(); - if (playbackRate != 0) { - if (modelRate == playbackRate) { - if (modelRate != outputRate) srNote = " " + tr("(R)"); - } else { - srNote = " " + tr("(X)"); - } - } + float v0, v1; + QString u0, u1; + bool b0, b1; - QString desc = tr("%1 / %2Hz%3") - .arg(RealTime::frame2RealTime(waveformModel->getEndFrame(), - sampleRate) - .toText(false).c_str()) - .arg(modelRate) - .arg(srNote); - - if (r.x() < m_scaleWidth + 5 + paint.fontMetrics().width(desc)) { - drawVisibleText(paint, m_scaleWidth + 5, - height() - fontHeight + fontAscent - 6, - desc, OutlinedText); - } + QString axs, ays, bxs, bys, dxs, dys; + + if ((b0 = topLayer->getXScaleValue(this, m_clickPos.x(), v0, u0))) { + axs = QString("%1 %2").arg(v0).arg(u0); + } + + if ((b1 = topLayer->getXScaleValue(this, m_mousePos.x(), v1, u1))) { + bxs = QString("%1 %2").arg(v1).arg(u1); + } + + if (b0 && b1 && u0 == u1) { + dxs = QString("(%1 %2)").arg(v1 - v0).arg(u1); + } + + if ((b0 = topLayer->getYScaleValue(this, m_clickPos.y(), v0, u0))) { + ays = QString("%1 %2").arg(v0).arg(u0); + } + + if ((b1 = topLayer->getYScaleValue(this, m_mousePos.y(), v1, u1))) { + bys = QString("%1 %2").arg(v1).arg(u1); + } + + if (b0 && b1 && u0 == u1) { + dys = QString("(%1 %2)").arg(v1 - v0).arg(u1); + } + + int x = m_clickPos.x() + 2; + int y = m_clickPos.y() + fontAscent + 2; + + if (axs != "") { + drawVisibleText(paint, x, y, axs, OutlinedText); + y += fontHeight; + } + + if (ays != "") { + drawVisibleText(paint, x, y, ays, OutlinedText); + y += fontHeight; } - if (m_manager && - m_manager->shouldShowLayerNames() && - r.y() + r.height() >= height() - int(m_layers.size()) * fontHeight - 6) { + x = m_mousePos.x() - paint.fontMetrics().width(bxs) - 2; + y = m_mousePos.y() - 2; - std::vector texts; - int maxTextWidth = 0; - - for (LayerList::iterator i = m_layers.begin(); i != m_layers.end(); ++i) { - - QString text = (*i)->getLayerPresentationName(); - int tw = paint.fontMetrics().width(text); - bool reduced = false; - while (tw > width() / 3 && text.length() > 4) { - if (!reduced && text.length() > 8) { - text = text.left(text.length() - 4); - } else { - text = text.left(text.length() - 2); - } - reduced = true; - tw = paint.fontMetrics().width(text + "..."); - } - if (reduced) { - texts.push_back(text + "..."); - } else { - texts.push_back(text); - } - if (tw > maxTextWidth) maxTextWidth = tw; - } + if (bys != "" && bxs != "") y -= fontHeight; - int lly = height() - 6; - int llx = width() - maxTextWidth - 5; - - if (m_manager->getZoomWheelsEnabled()) { - lly -= 20; - llx -= 36; - } - - if (r.x() + r.width() >= llx) { - - for (size_t i = 0; i < texts.size(); ++i) { - - if (i + 1 == texts.size()) { - paint.setPen(Qt::black); - } - - drawVisibleText(paint, llx, - lly - fontHeight + fontAscent, - texts[i], OutlinedText); - - lly -= fontHeight; - } - } + if (bxs != "") { + drawVisibleText(paint, x, y, bxs, OutlinedText); + y += fontHeight; } - if (m_clickedInRange && m_manager) { + x = m_mousePos.x() - paint.fontMetrics().width(bys) - 2; - //!!! be nice if this looked a bit more in keeping with the - //selection block + if (bys != "") { + drawVisibleText(paint, x, y, bys, OutlinedText); + y += fontHeight; + } - if (m_shiftPressed && toolMode == ViewManager::NavigateMode) { + paint.save(); + + paint.setPen(Qt::green); - paint.setPen(Qt::blue); - //!!! shouldn't use clickPos -- needs to use a clicked frame - paint.drawRect(m_clickPos.x(), m_clickPos.y(), - m_mousePos.x() - m_clickPos.x(), - m_mousePos.y() - m_clickPos.y()); + paint.drawRect(m_clickPos.x(), m_clickPos.y(), + m_mousePos.x() - m_clickPos.x(), + m_mousePos.y() - m_clickPos.y()); - } else if (toolMode == ViewManager::MeasureMode && topLayer) { + paint.restore(); +} - float v0, v1; - QString u0, u1; - bool b0, b1; - - if ((b0 = topLayer->getXScaleValue(this, m_clickPos.x(), v0, u0))) { - drawVisibleText(paint, - m_clickPos.x() + 2, - m_clickPos.y() + fontAscent + 2, - QString("%1 %2").arg(v0).arg(u0), - OutlinedText); - - if ((b1 = topLayer->getXScaleValue(this, m_mousePos.x(), v1, u1)) - && u1 == u0) { - QString t = QString("%1 %2").arg(v1 - v0).arg(u1); - drawVisibleText(paint, - m_mousePos.x() - paint.fontMetrics().width(t) - 2, - m_mousePos.y() - 2, - t, - OutlinedText); - } - } - - paint.setPen(Qt::green); - - //!!! shouldn't use clickPos -- needs to use a clicked frame - paint.drawRect(m_clickPos.x(), m_clickPos.y(), - m_mousePos.x() - m_clickPos.x(), - m_mousePos.y() - m_clickPos.y()); - } +void +Pane::drawEditingSelection(QPainter &paint) +{ + int offset = m_mousePos.x() - m_clickPos.x(); + int p0 = getXForFrame(m_editingSelection.getStartFrame()) + offset; + int p1 = getXForFrame(m_editingSelection.getEndFrame()) + offset; + + if (m_editingSelectionEdge < 0) { + p1 = getXForFrame(m_editingSelection.getEndFrame()); + } else if (m_editingSelectionEdge > 0) { + p0 = getXForFrame(m_editingSelection.getStartFrame()); } - if (selectionIsBeingEdited()) { + paint.save(); + if (hasLightBackground()) { + paint.setPen(QPen(Qt::black, 2)); + } else { + paint.setPen(QPen(Qt::white, 2)); + } + + //!!! duplicating display policy with View::drawSelections + + if (m_editingSelectionEdge < 0) { + paint.drawLine(p0, 1, p1, 1); + paint.drawLine(p0, 0, p0, height()); + paint.drawLine(p0, height() - 1, p1, height() - 1); + } else if (m_editingSelectionEdge > 0) { + paint.drawLine(p0, 1, p1, 1); + paint.drawLine(p1, 0, p1, height()); + paint.drawLine(p0, height() - 1, p1, height() - 1); + } else { + paint.setBrush(Qt::NoBrush); + paint.drawRect(p0, 1, p1 - p0, height() - 2); + } + paint.restore(); +} - int offset = m_mousePos.x() - m_clickPos.x(); - int p0 = getXForFrame(m_editingSelection.getStartFrame()) + offset; - int p1 = getXForFrame(m_editingSelection.getEndFrame()) + offset; +void +Pane::drawDurationAndRate(QRect r, const Model *waveformModel, + int sampleRate, QPainter &paint) +{ + int fontHeight = paint.fontMetrics().height(); + int fontAscent = paint.fontMetrics().ascent(); - if (m_editingSelectionEdge < 0) { - p1 = getXForFrame(m_editingSelection.getEndFrame()); - } else if (m_editingSelectionEdge > 0) { - p0 = getXForFrame(m_editingSelection.getStartFrame()); - } + if (r.y() + r.height() < height() - fontHeight - 6) return; - paint.save(); - if (hasLightBackground()) { - paint.setPen(QPen(Qt::black, 2)); - } else { - paint.setPen(QPen(Qt::white, 2)); - } + size_t modelRate = waveformModel->getSampleRate(); + size_t playbackRate = m_manager->getPlaybackSampleRate(); + size_t outputRate = m_manager->getOutputSampleRate(); + + QString srNote = ""; - //!!! duplicating display policy with View::drawSelections + // Show (R) for waveform models that will be resampled on + // playback, and (X) for waveform models that will be played + // at the wrong rate because their rate differs from the + // current playback rate (which is not necessarily that of the + // main model). - if (m_editingSelectionEdge < 0) { - paint.drawLine(p0, 1, p1, 1); - paint.drawLine(p0, 0, p0, height()); - paint.drawLine(p0, height() - 1, p1, height() - 1); - } else if (m_editingSelectionEdge > 0) { - paint.drawLine(p0, 1, p1, 1); - paint.drawLine(p1, 0, p1, height()); - paint.drawLine(p0, height() - 1, p1, height() - 1); - } else { - paint.setBrush(Qt::NoBrush); - paint.drawRect(p0, 1, p1 - p0, height() - 2); - } - paint.restore(); + if (playbackRate != 0) { + if (modelRate == playbackRate) { + if (modelRate != outputRate) srNote = " " + tr("(R)"); + } else { + srNote = " " + tr("(X)"); + } } - paint.end(); + QString desc = tr("%1 / %2Hz%3") + .arg(RealTime::frame2RealTime(waveformModel->getEndFrame(), + sampleRate) + .toText(false).c_str()) + .arg(modelRate) + .arg(srNote); + + if (r.x() < m_scaleWidth + 5 + paint.fontMetrics().width(desc)) { + drawVisibleText(paint, m_scaleWidth + 5, + height() - fontHeight + fontAscent - 6, + desc, OutlinedText); + } } bool diff -r 6d113226bb4c -r 11021509c4eb view/Pane.h --- a/view/Pane.h Thu Jun 14 15:20:49 2007 +0000 +++ b/view/Pane.h Thu Jun 14 16:28:27 2007 +0000 @@ -88,6 +88,14 @@ virtual void wheelEvent(QWheelEvent *e); virtual void resizeEvent(QResizeEvent *e); + void drawVerticalScale(QRect r, Layer *, QPainter &); + void drawFeatureDescription(Layer *, QPainter &); + void drawCentreLine(int, QPainter &); + void drawDurationAndRate(QRect, const Model *, int, QPainter &); + void drawLayerNames(QRect, QPainter &); + void drawMeasurementRect(Layer *, QPainter &); + void drawEditingSelection(QPainter &); + virtual bool render(QPainter &paint, int x0, size_t f0, size_t f1); Selection getSelectionAt(int x, bool &closeToLeft, bool &closeToRight) const;