Mercurial > hg > svgui
changeset 25:dcdb21b62dbb
* Refactor sparse models. Previously the 1D and time-value models duplicated
a lot of code; now there is a base class (SparseModel) templated on the
stored point type, and the subclasses define point types with the necessary
characteristics.
* Add NoteModel, a new SparseModel subclass.
* Reorganise local feature description display. Instead of asking the layer
to draw its own, just query it for a textual description and draw that in
Pane. Greatly simplifies this part of the layer code.
* Add local feature descriptions to colour 3D plot and waveform layers.
* Add pitch in MIDI-pitch-and-cents to spectrogram layer.
* Give AudioGenerator its own mutex to shorten lock times in CallbackPlaySource.
* Minor adjustments to layers menu &c
author | Chris Cannam |
---|---|
date | Thu, 02 Feb 2006 16:10:19 +0000 |
parents | 6b794a2af3d9 |
children | 94381052a6c9 |
files | layer/Colour3DPlotLayer.cpp layer/Colour3DPlotLayer.h layer/SpectrogramLayer.cpp layer/SpectrogramLayer.h layer/TimeInstantLayer.cpp layer/TimeInstantLayer.h layer/TimeValueLayer.cpp layer/TimeValueLayer.h layer/WaveformLayer.cpp layer/WaveformLayer.h widgets/Pane.cpp |
diffstat | 11 files changed, 322 insertions(+), 253 deletions(-) [+] |
line wrap: on
line diff
--- a/layer/Colour3DPlotLayer.cpp Wed Feb 01 14:49:49 2006 +0000 +++ b/layer/Colour3DPlotLayer.cpp Thu Feb 02 16:10:19 2006 +0000 @@ -66,6 +66,96 @@ cacheInvalid(); } +bool +Colour3DPlotLayer::isLayerScrollable() const +{ + QPoint discard; + return !m_view->shouldIlluminateLocalFeatures(this, discard); +} + +QString +Colour3DPlotLayer::getFeatureDescription(QPoint &pos) const +{ + if (!m_model) return ""; + + int x = pos.x(); + int y = pos.y(); + + size_t modelStart = m_model->getStartFrame(); + size_t modelWindow = m_model->getWindowSize(); + + int sx0 = modelWindow * + int((getFrameForX(x) - long(modelStart)) / long(modelWindow)); + int sx1 = sx0 + modelWindow; + + float binHeight = float(m_view->height()) / m_model->getYBinCount(); + int sy = (m_view->height() - y) / binHeight; + + float value = m_model->getBinValue(sx0, sy); + + QString binName = m_model->getBinName(sy); + if (binName == "") binName = QString("[%1]").arg(sy + 1); + else binName = QString("%1 [%2]").arg(binName).arg(sy + 1); + + QString text = tr("Time:\t%1 - %2\nBin:\t%3\nValue:\t%4") + .arg(RealTime::frame2RealTime(sx0, m_model->getSampleRate()) + .toText(true).c_str()) + .arg(RealTime::frame2RealTime(sx1, m_model->getSampleRate()) + .toText(true).c_str()) + .arg(binName) + .arg(value); + + return text; +} + +int +Colour3DPlotLayer::getVerticalScaleWidth(QPainter &paint) const +{ + if (!m_model) return 0; + + QString sampleText("123"); + int tw = paint.fontMetrics().width(sampleText); + + for (size_t i = 0; i < m_model->getYBinCount(); ++i) { + if (m_model->getBinName(i).length() > sampleText.length()) { + sampleText = m_model->getBinName(i); + } + } + if (sampleText != "123") { + tw = std::max(tw, paint.fontMetrics().width(sampleText)); + } + + return tw + 13; +} + +void +Colour3DPlotLayer::paintVerticalScale(QPainter &paint, QRect rect) const +{ + if (!m_model) return; + + int h = rect.height(), w = rect.width(); + float binHeight = float(m_view->height()) / m_model->getYBinCount(); + +// int textHeight = paint.fontMetrics().height(); +// int toff = -textHeight + paint.fontMetrics().ascent() + 2; + + for (size_t i = 0; i < m_model->getYBinCount(); ++i) { + + int y0 = m_view->height() - (i * binHeight) - 1; + + QString text = m_model->getBinName(i); + if (text == "") text = QString("[%1]").arg(i + 1); + + paint.drawLine(0, y0, w, y0); + + int cy = y0 - binHeight/2; + int ty = cy + paint.fontMetrics().ascent()/2; + +// int tx = w - 10 - paint.fontMetrics().width(text); + paint.drawText(10, ty, text); + } +} + void Colour3DPlotLayer::paint(QPainter &paint, QRect rect) const { @@ -193,6 +283,9 @@ std::cerr << "Colour3DPlotLayer: sample rate is " << m_model->getSampleRate() << ", window size " << m_model->getWindowSize() << std::endl; */ + QPoint illuminatePos; + bool illuminate = m_view->shouldIlluminateLocalFeatures(this, illuminatePos); + for (int sx = sx0 - 1; sx <= sx1; ++sx) { int fx = sx * int(modelWindow); @@ -223,7 +316,16 @@ int w = rx1 - rx0; if (w < 1) w = 1; - paint.drawRect(rx0, ry0 - h / sh - 1, w, h / sh + 1); + + QRect r(rx0, ry0 - h / sh - 1, w, h / sh + 1); + + if (illuminate) { + if (r.contains(illuminatePos)) { + paint.setPen(Qt::black);//!!! + } + } + + paint.drawRect(r); if (sx >= 0 && sx < m_cache->width() && sy >= 0 && sy < m_cache->height()) {
--- a/layer/Colour3DPlotLayer.h Wed Feb 01 14:49:49 2006 +0000 +++ b/layer/Colour3DPlotLayer.h Thu Feb 02 16:10:19 2006 +0000 @@ -43,10 +43,17 @@ virtual const Model *getModel() const { return m_model; } virtual void paint(QPainter &paint, QRect rect) const; + virtual int getVerticalScaleWidth(QPainter &) const; + virtual void paintVerticalScale(QPainter &paint, QRect rect) const; + + virtual QString getFeatureDescription(QPoint &) const; + virtual int getNearestFeatureFrame(int frame, size_t &resolution, bool snapRight = true) const; + virtual bool isLayerScrollable() const; + void setModel(const DenseThreeDimensionalModel *model); virtual int getCompletion() const { return m_model->getCompletion(); }
--- a/layer/SpectrogramLayer.cpp Wed Feb 01 14:49:49 2006 +0000 +++ b/layer/SpectrogramLayer.cpp Thu Feb 02 16:10:19 2006 +0000 @@ -1472,8 +1472,6 @@ #ifdef DEBUG_SPECTROGRAM_REPAINT std::cerr << "SpectrogramLayer::paint() returning" << std::endl; #endif - -//!!! drawLocalFeatureDescription(paint); } int @@ -1485,141 +1483,6 @@ return completion; } -QRect -SpectrogramLayer::getFeatureDescriptionRect(QPainter &paint, QPoint pos) const -{ - if (!m_model || !m_model->isOK()) return QRect(); - - QString timeLabel = tr("Time: "); - QString freqLabel = tr("Hz: "); - QString dBLabel = tr("dB: "); - - // assume time is widest - RealTime rtMin, rtMax; - if (!getXBinSourceRange(pos.x(), rtMin, rtMax)) return QRect(); - QString timeMinText = QString("%1").arg(rtMin.toText(true).c_str()); - QString timeMaxText = QString(" - %1").arg(rtMax.toText(true).c_str()); - - QFontMetrics metrics = paint.fontMetrics(); - - int labelwidth = - std::max(std::max(metrics.width(timeLabel), - metrics.width(freqLabel)), - metrics.width(dBLabel)); - - int boxwidth = labelwidth + - metrics.width(timeMinText) + metrics.width(timeMaxText); - - int fontHeight = metrics.height(); - int boxheight = fontHeight * 3 + 4; - - return QRect(0, 0, boxwidth + 20, boxheight + 15); -} - -void -SpectrogramLayer::paintLocalFeatureDescription(QPainter &paint, - QRect rect, QPoint pos) const -{ - int x = pos.x(); - int y = pos.y(); - - if (!m_model || !m_model->isOK()) return; - - float dbMin = 0, dbMax = 0; - float freqMin = 0, freqMax = 0; - RealTime rtMin, rtMax; - - bool haveDb = false; - - if (!getXBinSourceRange(x, rtMin, rtMax)) return; - if (!getYBinSourceRange(y, freqMin, freqMax)) return; - if (getXYBinSourceRange(x, y, dbMin, dbMax)) haveDb = true; - - QString timeLabel = tr("Time: "); - QString freqLabel = tr("Hz: "); - QString dBLabel = tr("dB: "); - - QString timeMinText = QString("%1").arg(rtMin.toText(true).c_str()); - QString timeMaxText = QString(" - %1").arg(rtMax.toText(true).c_str()); - - QString freqMinText = QString("%1").arg(freqMin); - QString freqMaxText = ""; - if (freqMax != freqMin) { - freqMaxText = QString(" - %1").arg(freqMax); - } - - QString dBMinText = ""; - QString dBMaxText = ""; - - if (haveDb) { - int dbmxi = int(dbMax - 0.001); - int dbmni = int(dbMin - 0.001); - dBMinText = QString("%1").arg(dbmni); - if (dbmxi != dbmni) dBMaxText = QString(" - %1").arg(dbmxi); - } - - QFontMetrics metrics = paint.fontMetrics(); - - int labelwidth = - std::max(std::max(metrics.width(timeLabel), - metrics.width(freqLabel)), - metrics.width(dBLabel)); - - int minwidth = - std::max(std::max(metrics.width(timeMinText), - metrics.width(freqMinText)), - metrics.width(dBMinText)); - - int maxwidth = - std::max(std::max(metrics.width(timeMaxText), - metrics.width(freqMaxText)), - metrics.width(dBMaxText)); - - int boxwidth = labelwidth + minwidth + maxwidth; - - int fontAscent = metrics.ascent(); - int fontHeight = metrics.height(); - - int boxheight = fontHeight * 3 + 4; - -// paint.setPen(Qt::white); -// paint.setBrush(Qt::NoBrush); - -//!!! int xbase = m_view->width() - boxwidth - 20; - int xbase = rect.x() + 5; - int ybase = rect.y() + 5; - - paint.drawRect(xbase, ybase, boxwidth + 10, - boxheight + 10 - metrics.descent() + 1); - - paint.drawText(xbase + 5 + labelwidth - metrics.width(timeLabel), - ybase + 5 + fontAscent, timeLabel); - - paint.drawText(xbase + 5 + labelwidth - metrics.width(freqLabel), - ybase + 7 + fontAscent + fontHeight, freqLabel); - - paint.drawText(xbase + 5 + labelwidth - metrics.width(dBLabel), - ybase + 9 + fontAscent + fontHeight * 2, dBLabel); - - paint.drawText(xbase + 5 + labelwidth + minwidth - metrics.width(timeMinText), - ybase + 5 + fontAscent, timeMinText); - - paint.drawText(xbase + 5 + labelwidth + minwidth - metrics.width(freqMinText), - ybase + 7 + fontAscent + fontHeight, freqMinText); - - paint.drawText(xbase + 5 + labelwidth + minwidth - metrics.width(dBMinText), - ybase + 9 + fontAscent + fontHeight * 2, dBMinText); - - paint.drawText(xbase + 5 + labelwidth + minwidth, - ybase + 5 + fontAscent, timeMaxText); - - paint.drawText(xbase + 5 + labelwidth + minwidth, - ybase + 7 + fontAscent + fontHeight, freqMaxText); - - paint.drawText(xbase + 5 + labelwidth + minwidth, - ybase + 9 + fontAscent + fontHeight * 2, dBMaxText); -} - int SpectrogramLayer::getNearestFeatureFrame(int frame, size_t &resolution, @@ -1631,48 +1494,61 @@ return snapFrame; } -/*!!! +QString +SpectrogramLayer::getFeatureDescription(QPoint &pos) const +{ + int x = pos.x(); + int y = pos.y(); -bool -SpectrogramLayer::identifyLocalFeatures(bool on, int x, int y) -{ - return true; //!!! - - m_identify = on; - m_identifyX = x; - m_identifyY = y; - - m_view->update(); -*/ -/* - if (!m_model || !m_model->isOK()) return false; - - std::cerr << "SpectrogramLayer::identifyLocalFeatures(" << on << "," << x << "," << y << ")" << std::endl; + if (!m_model || !m_model->isOK()) return ""; float dbMin = 0, dbMax = 0; float freqMin = 0, freqMax = 0; + QString pitchMin, pitchMax; RealTime rtMin, rtMax; - if (getXBinSourceRange(x, rtMin, rtMax)) { - std::cerr << "Times: " << rtMin << " -> " << rtMax << std::endl; - } else return false; + bool haveDb = false; - if (getYBinSourceRange(y, freqMin, freqMax)) { - std::cerr << "Frequencies: " << freqMin << " -> " << freqMax << std::endl; - } else return false; + if (!getXBinSourceRange(x, rtMin, rtMax)) return ""; + if (!getYBinSourceRange(y, freqMin, freqMax)) return ""; + if (getXYBinSourceRange(x, y, dbMin, dbMax)) haveDb = true; - if (getXYBinSourceRange(x, y, dbMin, dbMax)) { - std::cerr << "dB: " << dbMin << " -> " << dbMax << std::endl; + //!!! want to actually do a one-off FFT to recalculate the dB value! + + QString text; + + if (rtMin != rtMax) { + text += tr("Time:\t%1 - %2\n") + .arg(rtMin.toText(true).c_str()) + .arg(rtMax.toText(true).c_str()); + } else { + text += tr("Time:\t%1\n") + .arg(rtMin.toText(true).c_str()); } - m_identifyX = x; - m_identifyY = y; - m_identify = true; -*/ - /*!!! - return true; + if (freqMin != freqMax) { + text += tr("Frequency:\t%1 - %2 Hz\nPitch:\t%3 - %4\n") + .arg(freqMin) + .arg(freqMax) + .arg(Pitch::getPitchLabelForFrequency(freqMin)) + .arg(Pitch::getPitchLabelForFrequency(freqMax)); + } else { + text += tr("Frequency:\t%1 Hz\nPitch:\t%2\n") + .arg(freqMin) + .arg(Pitch::getPitchLabelForFrequency(freqMin)); + } + + if (haveDb) { + if (lrintf(dbMin) != lrintf(dbMax)) { + text += tr("dB:\t%1 - %2").arg(lrintf(dbMin)).arg(lrintf(dbMax)); + } else { + text += tr("dB:\t%1").arg(lrintf(dbMin)); + } + } + + return text; } - */ + int SpectrogramLayer::getVerticalScaleWidth(QPainter &paint) const {
--- a/layer/SpectrogramLayer.h Wed Feb 01 14:49:49 2006 +0000 +++ b/layer/SpectrogramLayer.h Thu Feb 02 16:10:19 2006 +0000 @@ -51,8 +51,7 @@ virtual int getVerticalScaleWidth(QPainter &) const; virtual void paintVerticalScale(QPainter &paint, QRect rect) const; - virtual QRect getFeatureDescriptionRect(QPainter &, QPoint) const; - virtual void paintLocalFeatureDescription(QPainter &, QRect, QPoint) const; + virtual QString getFeatureDescription(QPoint &) const; virtual int getNearestFeatureFrame(int frame, size_t &resolution,
--- a/layer/TimeInstantLayer.cpp Wed Feb 01 14:49:49 2006 +0000 +++ b/layer/TimeInstantLayer.cpp Thu Feb 02 16:10:19 2006 +0000 @@ -139,14 +139,6 @@ return !m_view->shouldIlluminateLocalFeatures(this, discard); } -QRect -TimeInstantLayer::getFeatureDescriptionRect(QPainter &paint, QPoint pos) const -{ - return QRect(0, 0, - std::max(100, paint.fontMetrics().width(tr("No local points"))), - 50); //!!! cruddy -} - SparseOneDimensionalModel::PointList TimeInstantLayer::getLocalPoints(int x) const { @@ -181,48 +173,40 @@ return usePoints; } -void -TimeInstantLayer::paintLocalFeatureDescription(QPainter &paint, QRect rect, - QPoint pos) const +QString +TimeInstantLayer::getFeatureDescription(QPoint &pos) const { - //!!! bleagh + int x = pos.x(); - int x = pos.x(); - - if (!m_model || !m_model->getSampleRate()) return; + if (!m_model || !m_model->getSampleRate()) return ""; SparseOneDimensionalModel::PointList points = getLocalPoints(x); - QFontMetrics metrics = paint.fontMetrics(); - int xbase = rect.x() + 5; - int ybase = rect.y() + 5; - if (points.empty()) { - QString label = tr("No local points"); if (!m_model->isReady()) { - label = tr("In progress"); + return tr("In progress"); + } else { + return tr("No local points"); } - paint.drawText(xbase + 5, ybase + 5 + metrics.ascent(), label); - return; } long useFrame = points.begin()->frame; RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); - QString timeText = QString(tr("Time %1")).arg(rt.toText(true).c_str()); + + QString text; - int timewidth = metrics.width(timeText); - int labelwidth = metrics.width(points.begin()->label); + if (points.begin()->label == "") { + text = QString(tr("Time:\t%1\nNo label")) + .arg(rt.toText(true).c_str()); + } else { + text = QString(tr("Time:\t%1\nLabel:\t%2")) + .arg(rt.toText(true).c_str()) + .arg(points.begin()->label); + } - int boxheight = metrics.height() * 2 + 3; - int boxwidth = std::max(timewidth, labelwidth); - - paint.drawRect(xbase, ybase, boxwidth + 10, - boxheight + 10 - metrics.descent() + 1); - - paint.drawText(xbase + 5, ybase + 5 + metrics.ascent(), timeText); - paint.drawText(xbase + 5, ybase + 7 + metrics.ascent() + metrics.height(), - points.begin()->label); + pos = QPoint(getXForFrame(useFrame), pos.y()); + return text; } int
--- a/layer/TimeInstantLayer.h Wed Feb 01 14:49:49 2006 +0000 +++ b/layer/TimeInstantLayer.h Thu Feb 02 16:10:19 2006 +0000 @@ -28,8 +28,7 @@ virtual void paint(QPainter &paint, QRect rect) const; - virtual QRect getFeatureDescriptionRect(QPainter &, QPoint) const; - virtual void paintLocalFeatureDescription(QPainter &, QRect, QPoint) const; + virtual QString getFeatureDescription(QPoint &) const; virtual int getNearestFeatureFrame(int frame, size_t &resolution,
--- a/layer/TimeValueLayer.cpp Wed Feb 01 14:49:49 2006 +0000 +++ b/layer/TimeValueLayer.cpp Thu Feb 02 16:10:19 2006 +0000 @@ -178,16 +178,6 @@ return !m_view->shouldIlluminateLocalFeatures(this, discard); } -QRect -TimeValueLayer::getFeatureDescriptionRect(QPainter &paint, QPoint pos) const -{ - return QRect(0, 0, - std::max(100, paint.fontMetrics().width(tr("No local points"))), - 70); //!!! -} - -//!!! too much in common with TimeInstantLayer - SparseTimeValueModel::PointList TimeValueLayer::getLocalPoints(int x) const { @@ -222,52 +212,42 @@ return usePoints; } -void -TimeValueLayer::paintLocalFeatureDescription(QPainter &paint, QRect rect, - QPoint pos) const +QString +TimeValueLayer::getFeatureDescription(QPoint &pos) const { - //!!! bleagh + int x = pos.x(); - int x = pos.x(); - - if (!m_model || !m_model->getSampleRate()) return; + if (!m_model || !m_model->getSampleRate()) return ""; SparseTimeValueModel::PointList points = getLocalPoints(x); - QFontMetrics metrics = paint.fontMetrics(); - int xbase = rect.x() + 5; - int ybase = rect.y() + 5; - if (points.empty()) { - QString label = tr("No local points"); if (!m_model->isReady()) { - label = tr("In progress"); + return tr("In progress"); + } else { + return tr("No local points"); } - paint.drawText(xbase + 5, ybase + 5 + metrics.ascent(), label); - return; } long useFrame = points.begin()->frame; RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); - QString timeText = QString("%1").arg(rt.toText(true).c_str()); - QString valueText = QString("%1").arg(points.begin()->value); + + QString text; - int timewidth = metrics.width(timeText); - int valuewidth = metrics.width(valueText); - int labelwidth = metrics.width(points.begin()->label); + 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")) + .arg(rt.toText(true).c_str()) + .arg(points.begin()->value) + .arg(points.begin()->label); + } - int boxheight = metrics.height() * 3 + 4; - int boxwidth = std::max(std::max(timewidth, labelwidth), valuewidth); - - paint.drawRect(xbase, ybase, boxwidth + 10, - boxheight + 10 - metrics.descent() + 1); - - paint.drawText(xbase + 5, ybase + 5 + metrics.ascent(), timeText); - paint.drawText(xbase + 5, ybase + 7 + metrics.ascent() + metrics.height(), - valueText); - paint.drawText(xbase + 5, ybase + 9 + metrics.ascent() + 2*metrics.height(), - points.begin()->label); + pos = QPoint(getXForFrame(useFrame), getYForValue(points.begin()->value)); + return text; } int
--- a/layer/TimeValueLayer.h Wed Feb 01 14:49:49 2006 +0000 +++ b/layer/TimeValueLayer.h Thu Feb 02 16:10:19 2006 +0000 @@ -28,8 +28,7 @@ virtual void paint(QPainter &paint, QRect rect) const; - virtual QRect getFeatureDescriptionRect(QPainter &, QPoint) const; - virtual void paintLocalFeatureDescription(QPainter &, QRect, QPoint) const; + virtual QString getFeatureDescription(QPoint &) const; virtual int getNearestFeatureFrame(int frame, size_t &resolution,
--- a/layer/WaveformLayer.cpp Wed Feb 01 14:49:49 2006 +0000 +++ b/layer/WaveformLayer.cpp Thu Feb 02 16:10:19 2006 +0000 @@ -399,8 +399,8 @@ y0 = rect.top(); y1 = rect.bottom(); - long frame0 = startFrame + x0 * zoomLevel; - long frame1 = startFrame + (x1 + 1) * zoomLevel; + long frame0 = getFrameForX(x0); + long frame1 = getFrameForX(x1 + 1); #ifdef DEBUG_WAVEFORM_PAINT std::cerr << "Painting waveform from " << frame0 << " to " << frame1 << " (" << (x1-x0+1) << " pixels at zoom " << zoomLevel << ")" << std::endl; @@ -646,6 +646,74 @@ } } +QString +WaveformLayer::getFeatureDescription(QPoint &pos) const +{ + int x = pos.x(); + + if (!m_model || !m_model->isOK()) return ""; + + long f0 = getFrameForX(x); + long f1 = getFrameForX(x + 1); + + if (f0 < 0) f0 = 0; + if (f1 <= f0) return ""; + + QString text; + + RealTime rt0 = RealTime::frame2RealTime(f0, m_model->getSampleRate()); + RealTime rt1 = RealTime::frame2RealTime(f1, m_model->getSampleRate()); + + if (f1 != f0 + 1 && (rt0.sec != rt1.sec || rt0.msec() != rt1.msec())) { + text += tr("Time:\t%1 - %2") + .arg(rt0.toText(true).c_str()) + .arg(rt1.toText(true).c_str()); + } else { + text += tr("Time:\t%1") + .arg(rt0.toText(true).c_str()); + } + + size_t channels = 0, minChannel = 0, maxChannel = 0; + bool mergingChannels = false; + + channels = getChannelArrangement(minChannel, maxChannel, mergingChannels); + if (channels == 0) return ""; + + for (size_t ch = minChannel; ch <= maxChannel; ++ch) { + + size_t blockSize = m_view->getZoomLevel(); + RangeSummarisableTimeValueModel::RangeBlock ranges = + m_model->getRanges(ch, f0, f1, blockSize); + + if (ranges.empty()) continue; + + RangeSummarisableTimeValueModel::Range range = ranges[0]; + + QString label = tr("Level:"); + if (minChannel != maxChannel) { + if (ch == 0) label = tr("Left:"); + else if (ch == 1) label = tr("Right:"); + else label = tr("Channel %1").arg(ch + 1); + } + + int min = int(range.min * 1000); + int max = int(range.max * 1000); + int db = int(AudioLevel::multiplier_to_dB(std::max(fabsf(range.min), + fabsf(range.max))) + * 100); + + if (min != max) { + text += tr("\n%1\t%2 - %3 (%4 dB peak)") + .arg(label).arg(float(min)/1000).arg(float(max)/1000).arg(float(db)/100); + } else { + text += tr("\n%1\t%2 (%3 dB peak)") + .arg(label).arg(float(min)/1000).arg(float(db)/100); + } + } + + return text; +} + int WaveformLayer::getVerticalScaleWidth(QPainter &paint) const {
--- a/layer/WaveformLayer.h Wed Feb 01 14:49:49 2006 +0000 +++ b/layer/WaveformLayer.h Thu Feb 02 16:10:19 2006 +0000 @@ -33,6 +33,8 @@ virtual const Model *getModel() const { return m_model; } virtual void paint(QPainter &paint, QRect rect) const; + virtual QString getFeatureDescription(QPoint &) const; + virtual int getVerticalScaleWidth(QPainter &) const; virtual void paintVerticalScale(QPainter &paint, QRect rect) const;
--- a/widgets/Pane.cpp Wed Feb 01 14:49:49 2006 +0000 +++ b/widgets/Pane.cpp Thu Feb 02 16:10:19 2006 +0000 @@ -113,6 +113,57 @@ } if (m_identifyFeatures) { + + QPoint pos = m_identifyPoint; + QString desc = (*vi)->getFeatureDescription(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(); + } + +/*!!! QRect descRect = (*vi)->getFeatureDescriptionRect(paint, m_identifyPoint); if (descRect.width() > 0 && descRect.height() > 0 && @@ -137,6 +188,8 @@ paint.restore(); } + +*/ } break;