Mercurial > hg > svgui
changeset 42:1bdf285c4eac
* Add "Export Audio File" option
* Make note layer align in frequency with any spectrogram layer on the same
view (if it's set to frequency mode)
* Start to implement mouse editing for ranges of points by dragging the
selection
* First scrappy attempt at a vertical scale for time value layer
author | Chris Cannam |
---|---|
date | Mon, 27 Feb 2006 17:34:41 +0000 |
parents | f2c416cbdaa9 |
children | 78515b1e29eb |
files | layer/NoteLayer.cpp layer/SpectrogramLayer.cpp layer/SpectrogramLayer.h layer/TimeValueLayer.cpp layer/TimeValueLayer.h widgets/Pane.cpp widgets/Pane.h |
diffstat | 7 files changed, 205 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/layer/NoteLayer.cpp Fri Feb 24 17:26:11 2006 +0000 +++ b/layer/NoteLayer.cpp Mon Feb 27 17:34:41 2006 +0000 @@ -17,6 +17,8 @@ #include "model/NoteModel.h" +#include "SpectrogramLayer.h" // for optional frequency alignment + #include <QPainter> #include <QPainterPath> #include <QMouseEvent> @@ -353,7 +355,7 @@ NoteLayer::getYForValue(float value) const { float min, max, h = m_view->height(); - + switch (m_verticalScale) { case MIDIRangeScale: @@ -367,12 +369,26 @@ break; case FrequencyScale: + + value = Pitch::getFrequencyForPitch(lrintf(value), + value - lrintf(value)); + + // If we have a spectrogram layer on the same view as us, align + // ourselves with it... + for (int i = 0; i < m_view->getLayerCount(); ++i) { + SpectrogramLayer *spectrogram = dynamic_cast<SpectrogramLayer *> + (m_view->getLayer(i)); + if (spectrogram) { + return spectrogram->getYForFrequency(value); + } + } + + // ...otherwise just interpolate std::cerr << "FrequencyScale: value in = " << value << std::endl; min = m_model->getValueMinimum(); min = Pitch::getFrequencyForPitch(lrintf(min), min - lrintf(min)); max = m_model->getValueMaximum(); max = Pitch::getFrequencyForPitch(lrintf(max), max - lrintf(max)); - value = Pitch::getFrequencyForPitch(lrintf(value), value - lrintf(value)); std::cerr << "FrequencyScale: min = " << min << ", max = " << max << ", value = " << value << std::endl; break; }
--- a/layer/SpectrogramLayer.cpp Fri Feb 24 17:26:11 2006 +0000 +++ b/layer/SpectrogramLayer.cpp Mon Feb 27 17:34:41 2006 +0000 @@ -2031,6 +2031,24 @@ #endif } +float +SpectrogramLayer::getYForFrequency(float frequency) const +{ + return m_view->getYForFrequency(frequency, + getEffectiveMinFrequency(), + getEffectiveMaxFrequency(), + m_frequencyScale == LogFrequencyScale); +} + +float +SpectrogramLayer::getFrequencyForY(int y) const +{ + return m_view->getFrequencyForY(y, + getEffectiveMinFrequency(), + getEffectiveMaxFrequency(), + m_frequencyScale == LogFrequencyScale); +} + int SpectrogramLayer::getCompletion() const {
--- a/layer/SpectrogramLayer.h Fri Feb 24 17:26:11 2006 +0000 +++ b/layer/SpectrogramLayer.h Mon Feb 27 17:34:41 2006 +0000 @@ -169,6 +169,9 @@ virtual bool isLayerOpaque() const { return true; } + float getYForFrequency(float frequency) const; + float getFrequencyForY(int y) const; + virtual int getCompletion() const; virtual QString toXmlString(QString indent = "",
--- a/layer/TimeValueLayer.cpp Fri Feb 24 17:26:11 2006 +0000 +++ b/layer/TimeValueLayer.cpp Mon Feb 27 17:34:41 2006 +0000 @@ -543,6 +543,32 @@ paint.setRenderHint(QPainter::Antialiasing, false); } +int +TimeValueLayer::getVerticalScaleWidth(QPainter &paint) const +{ + return 100; //!!! +} + +void +TimeValueLayer::paintVerticalScale(QPainter &paint, QRect rect) const +{ + if (!m_model) return; + + float v = m_model->getValueMinimum(); + float inc = (m_model->getValueMaximum() - v) / 10; + + while (v < m_model->getValueMaximum()) { + int y = getYForValue(v); + QString label = QString("%1").arg(v); + paint.drawLine(100 - 10, y, 100, y); + paint.drawText(100 - 15 - paint.fontMetrics().width(label), + y - paint.fontMetrics().height() /2 + paint.fontMetrics().ascent(), + label); + v += inc; + } + +} + void TimeValueLayer::drawStart(QMouseEvent *e) {
--- a/layer/TimeValueLayer.h Fri Feb 24 17:26:11 2006 +0000 +++ b/layer/TimeValueLayer.h Mon Feb 27 17:34:41 2006 +0000 @@ -28,6 +28,9 @@ 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 bool snapToFeatureFrame(int &frame,
--- a/widgets/Pane.cpp Fri Feb 24 17:26:11 2006 +0000 +++ b/widgets/Pane.cpp Mon Feb 27 17:34:41 2006 +0000 @@ -41,7 +41,12 @@ bool Pane::shouldIlluminateLocalFeatures(const Layer *layer, QPoint &pos) { - if (layer == getSelectedLayer()) { + QPoint discard; + bool b0, b1; + + if (layer == getSelectedLayer() && + !shouldIlluminateLocalSelection(discard, b0, b1)) { + pos = m_identifyPoint; return m_identifyFeatures; } @@ -49,6 +54,44 @@ return false; } +bool +Pane::shouldIlluminateLocalSelection(QPoint &pos, + bool &closeToLeft, + bool &closeToRight) +{ + if (m_identifyFeatures && + m_manager && + m_manager->getToolMode() == ViewManager::EditMode && + !m_manager->getSelections().empty() && + !selectionIsBeingEdited()) { + + Selection s(getSelectionAt(m_identifyPoint.x(), + closeToLeft, closeToRight)); + + if (!s.isEmpty()) { + if (getSelectedLayer() && getSelectedLayer()->isLayerEditable()) { + + pos = m_identifyPoint; + return true; + } + } + } + + return false; +} + +bool +Pane::selectionIsBeingEdited() const +{ + if (!m_editingSelection.isEmpty()) { + if (m_mousePos != m_clickPos && + getFrameForX(m_mousePos.x()) != getFrameForX(m_clickPos.x())) { + return true; + } + } + return false; +} + void Pane::setCentreLineVisible(bool visible) { @@ -281,6 +324,42 @@ } } + if (selectionIsBeingEdited()) { + + 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()); + } + + 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(); + } + paint.end(); } @@ -322,6 +401,8 @@ { m_clickPos = e->pos(); m_clickedInRange = true; + m_editingSelection = Selection(); + m_editingSelectionEdge = 0; m_shiftPressed = (e->modifiers() & Qt::ShiftModifier); m_ctrlPressed = (e->modifiers() & Qt::ControlModifier); @@ -390,9 +471,11 @@ } else if (mode == ViewManager::EditMode) { - Layer *layer = getSelectedLayer(); - if (layer && layer->isLayerEditable()) { - layer->editStart(e); + if (!editSelectionStart(e)) { + Layer *layer = getSelectedLayer(); + if (layer && layer->isLayerEditable()) { + layer->editStart(e); + } } } @@ -480,10 +563,12 @@ } else if (mode == ViewManager::EditMode) { - Layer *layer = getSelectedLayer(); - if (layer && layer->isLayerEditable()) { - layer->editEnd(e); - update(); + if (!editSelectionEnd(e)) { + Layer *layer = getSelectedLayer(); + if (layer && layer->isLayerEditable()) { + layer->editEnd(e); + update(); + } } } @@ -626,9 +711,11 @@ } else if (mode == ViewManager::EditMode) { - Layer *layer = getSelectedLayer(); - if (layer && layer->isLayerEditable()) { - layer->editDrag(e); + if (!editSelectionDrag(e)) { + Layer *layer = getSelectedLayer(); + if (layer && layer->isLayerEditable()) { + layer->editDrag(e); + } } } } @@ -727,6 +814,35 @@ emit paneInteractedWith(); } +bool +Pane::editSelectionStart(QMouseEvent *e) +{ + bool closeToLeft, closeToRight; + Selection s(getSelectionAt(e->x(), closeToLeft, closeToRight)); + if (s.isEmpty()) return false; + m_editingSelection = s; + m_editingSelectionEdge = (closeToLeft ? -1 : closeToRight ? 1 : 0); + m_mousePos = e->pos(); + return true; +} + +bool +Pane::editSelectionDrag(QMouseEvent *e) +{ + if (m_editingSelection.isEmpty()) return false; + m_mousePos = e->pos(); + update(); + return true; +} + +bool +Pane::editSelectionEnd(QMouseEvent *e) +{ + if (m_editingSelection.isEmpty()) return false; + m_editingSelection = Selection(); + return true; +} + void Pane::toolModeChanged() {
--- a/widgets/Pane.h Fri Feb 24 17:26:11 2006 +0000 +++ b/widgets/Pane.h Mon Feb 27 17:34:41 2006 +0000 @@ -31,6 +31,9 @@ virtual QString getPropertyContainerIconName() const { return "pane"; } virtual bool shouldIlluminateLocalFeatures(const Layer *layer, QPoint &pos); + virtual bool shouldIlluminateLocalSelection(QPoint &pos, + bool &closeToLeft, + bool &closeToRight); void setCentreLineVisible(bool visible); bool getCentreLineVisible() const { return m_centreLineVisible; } @@ -55,6 +58,11 @@ Selection getSelectionAt(int x, bool &closeToLeft, bool &closeToRight); + bool editSelectionStart(QMouseEvent *e); + bool editSelectionDrag(QMouseEvent *e); + bool editSelectionEnd(QMouseEvent *e); + bool selectionIsBeingEdited() const; + bool m_identifyFeatures; QPoint m_identifyPoint; QPoint m_clickPos; @@ -67,6 +75,8 @@ size_t m_dragCentreFrame; bool m_centreLineVisible; size_t m_selectionStartFrame; + Selection m_editingSelection; + int m_editingSelectionEdge; }; #endif