# HG changeset patch # User Chris Cannam # Date 1138035777 0 # Node ID 01849cd277e6a76322ed512936ee32ea6f310552 # Parent 484e7320f59fabfef2f0bc7a5d82149b945308b9 * Hook up tool selection buttons to switch the cursor mode * Implement simple and multi-selection, snapping to the resolution of the current layer. You can't actually do anything with a selection yet diff -r 484e7320f59f -r 01849cd277e6 layer/SpectrogramLayer.cpp --- a/layer/SpectrogramLayer.cpp Thu Jan 19 17:59:11 2006 +0000 +++ b/layer/SpectrogramLayer.cpp Mon Jan 23 17:02:57 2006 +0000 @@ -1636,6 +1636,17 @@ ybase + 9 + fontAscent + fontHeight * 2, dBMaxText); } +int +SpectrogramLayer::getNearestFeatureFrame(int frame, + size_t &resolution, + bool snapRight) const +{ + resolution = getWindowIncrement(); + int snapFrame = (frame / resolution) * resolution; + if (snapRight) snapFrame += resolution; + return snapFrame; +} + /*!!! bool diff -r 484e7320f59f -r 01849cd277e6 layer/SpectrogramLayer.h --- a/layer/SpectrogramLayer.h Thu Jan 19 17:59:11 2006 +0000 +++ b/layer/SpectrogramLayer.h Mon Jan 23 17:02:57 2006 +0000 @@ -54,6 +54,10 @@ virtual QRect getFeatureDescriptionRect(QPainter &, QPoint) const; virtual void paintLocalFeatureDescription(QPainter &, QRect, QPoint) const; + virtual int getNearestFeatureFrame(int frame, + size_t &resolution, + bool snapRight = true) const; + void setModel(const DenseTimeValueModel *model); virtual PropertyList getProperties() const; diff -r 484e7320f59f -r 01849cd277e6 layer/TimeInstantLayer.cpp --- a/layer/TimeInstantLayer.cpp Thu Jan 19 17:59:11 2006 +0000 +++ b/layer/TimeInstantLayer.cpp Mon Jan 23 17:02:57 2006 +0000 @@ -224,6 +224,38 @@ points.begin()->label); } +int +TimeInstantLayer::getNearestFeatureFrame(int frame, + size_t &resolution, + bool snapRight) const +{ + if (!m_model) { + return Layer::getNearestFeatureFrame(frame, resolution, snapRight); + } + + resolution = m_model->getResolution(); + SparseOneDimensionalModel::PointList points(m_model->getPoints(frame, frame)); + + int returnFrame = frame; + + for (SparseOneDimensionalModel::PointList::const_iterator i = points.begin(); + i != points.end(); ++i) { + + if (snapRight) { + if (i->frame > frame) { + returnFrame = i->frame; + break; + } + } else { + if (i->frame <= frame) { + returnFrame = i->frame; + } + } + } + + return returnFrame; +} + void TimeInstantLayer::paint(QPainter &paint, QRect rect) const { diff -r 484e7320f59f -r 01849cd277e6 layer/TimeInstantLayer.h --- a/layer/TimeInstantLayer.h Thu Jan 19 17:59:11 2006 +0000 +++ b/layer/TimeInstantLayer.h Mon Jan 23 17:02:57 2006 +0000 @@ -31,6 +31,10 @@ virtual QRect getFeatureDescriptionRect(QPainter &, QPoint) const; virtual void paintLocalFeatureDescription(QPainter &, QRect, QPoint) const; + virtual int getNearestFeatureFrame(int frame, + size_t &resolution, + bool snapRight = true) const; + virtual const Model *getModel() const { return m_model; } void setModel(SparseOneDimensionalModel *model); diff -r 484e7320f59f -r 01849cd277e6 layer/TimeValueLayer.cpp --- a/layer/TimeValueLayer.cpp Thu Jan 19 17:59:11 2006 +0000 +++ b/layer/TimeValueLayer.cpp Mon Jan 23 17:02:57 2006 +0000 @@ -268,6 +268,38 @@ points.begin()->label); } +int +TimeValueLayer::getNearestFeatureFrame(int frame, + size_t &resolution, + bool snapRight) const +{ + if (!m_model) { + return Layer::getNearestFeatureFrame(frame, resolution, snapRight); + } + + resolution = m_model->getResolution(); + SparseTimeValueModel::PointList points(m_model->getPoints(frame, frame)); + + int returnFrame = frame; + + for (SparseTimeValueModel::PointList::const_iterator i = points.begin(); + i != points.end(); ++i) { + + if (snapRight) { + if (i->frame > frame) { + returnFrame = i->frame; + break; + } + } else { + if (i->frame <= frame) { + returnFrame = i->frame; + } + } + } + + return returnFrame; +} + void TimeValueLayer::paint(QPainter &paint, QRect rect) const { diff -r 484e7320f59f -r 01849cd277e6 layer/TimeValueLayer.h --- a/layer/TimeValueLayer.h Thu Jan 19 17:59:11 2006 +0000 +++ b/layer/TimeValueLayer.h Mon Jan 23 17:02:57 2006 +0000 @@ -31,6 +31,10 @@ virtual QRect getFeatureDescriptionRect(QPainter &, QPoint) const; virtual void paintLocalFeatureDescription(QPainter &, QRect, QPoint) const; + virtual int getNearestFeatureFrame(int frame, + size_t &resolution, + bool snapRight = true) const; + virtual const Model *getModel() const { return m_model; } void setModel(SparseTimeValueModel *model); diff -r 484e7320f59f -r 01849cd277e6 layer/WaveformLayer.cpp --- a/layer/WaveformLayer.cpp Thu Jan 19 17:59:11 2006 +0000 +++ b/layer/WaveformLayer.cpp Mon Jan 23 17:02:57 2006 +0000 @@ -385,6 +385,8 @@ paint->setPen(Qt::black); paint->setBrush(Qt::NoBrush); + paint->setRenderHint(QPainter::Antialiasing, false); + } else { paint = &viewPainter; } diff -r 484e7320f59f -r 01849cd277e6 widgets/Pane.cpp --- a/widgets/Pane.cpp Thu Jan 19 17:59:11 2006 +0000 +++ b/widgets/Pane.cpp Mon Jan 23 17:02:57 2006 +0000 @@ -13,6 +13,7 @@ #include "base/ZoomConstraint.h" #include "base/RealTime.h" #include "base/Profiler.h" +#include "base/ViewManager.h" #include #include @@ -27,6 +28,7 @@ m_identifyFeatures(false), m_clickedInRange(false), m_shiftPressed(false), + m_ctrlPressed(false), m_centreLineVisible(true) { setObjectName("Pane"); @@ -223,6 +225,8 @@ } if (m_clickedInRange && m_shiftPressed) { + //!!! be nice if this looked a bit more in keeping with the + //selection block paint.setPen(Qt::blue); paint.drawRect(m_clickPos.x(), m_clickPos.y(), m_mousePos.x() - m_clickPos.x(), @@ -238,7 +242,36 @@ m_clickPos = e->pos(); m_clickedInRange = true; m_shiftPressed = (e->modifiers() & Qt::ShiftModifier); - m_dragCentreFrame = m_centreFrame; + m_ctrlPressed = (e->modifiers() & Qt::ControlModifier); + + ViewManager::ToolMode mode = ViewManager::NavigateMode; + if (m_manager) mode = m_manager->getToolMode(); + + if (mode == ViewManager::NavigateMode) { + + m_dragCentreFrame = m_centreFrame; + + } else if (mode == ViewManager::SelectMode) { + + int mouseFrame = e->x() * m_zoomLevel + getStartFrame(); + size_t resolution = 1; + int snapFrame = mouseFrame; + + Layer *layer = getSelectedLayer(); + if (layer) { + snapFrame = layer->getNearestFeatureFrame(mouseFrame, resolution, + false); + } + + if (snapFrame < 0) snapFrame = 0; + m_selectionStartFrame = snapFrame; + if (m_manager) { + m_manager->setInProgressSelection(Selection(snapFrame, + snapFrame + resolution), + !m_ctrlPressed); + } + update(); + } emit paneInteractedWith(); } @@ -246,37 +279,67 @@ void Pane::mouseReleaseEvent(QMouseEvent *e) { + ViewManager::ToolMode mode = ViewManager::NavigateMode; + if (m_manager) mode = m_manager->getToolMode(); + if (m_clickedInRange) { mouseMoveEvent(e); } - if (m_shiftPressed) { - int x0 = std::min(m_clickPos.x(), m_mousePos.x()); - int x1 = std::max(m_clickPos.x(), m_mousePos.x()); - int w = x1 - x0; + if (mode == ViewManager::NavigateMode) { - long newStartFrame = getStartFrame() + m_zoomLevel * x0; + if (m_shiftPressed) { - if (newStartFrame <= -long(width() * m_zoomLevel)) { - newStartFrame = -long(width() * m_zoomLevel) + 1; + int x0 = std::min(m_clickPos.x(), m_mousePos.x()); + int x1 = std::max(m_clickPos.x(), m_mousePos.x()); + int w = x1 - x0; + + long newStartFrame = getStartFrame() + m_zoomLevel * x0; + + if (newStartFrame <= -long(width() * m_zoomLevel)) { + newStartFrame = -long(width() * m_zoomLevel) + 1; + } + + if (newStartFrame >= long(getModelsEndFrame())) { + newStartFrame = getModelsEndFrame() - 1; + } + + float ratio = float(w) / float(width()); +// std::cerr << "ratio: " << ratio << std::endl; + size_t newZoomLevel = (size_t)nearbyint(m_zoomLevel * ratio); + if (newZoomLevel < 1) newZoomLevel = 1; + +// std::cerr << "start: " << m_startFrame << ", level " << m_zoomLevel << std::endl; + setZoomLevel(getZoomConstraintBlockSize(newZoomLevel)); + setStartFrame(newStartFrame); + + //cerr << "mouseReleaseEvent: start frame now " << m_startFrame << endl; +// update(); } - if (newStartFrame >= long(getModelsEndFrame())) { - newStartFrame = getModelsEndFrame() - 1; + } else if (mode == ViewManager::SelectMode) { + + if (m_manager && m_manager->haveInProgressSelection()) { + + bool exclusive; + Selection selection = m_manager->getInProgressSelection(exclusive); + + if (selection.getEndFrame() < selection.getStartFrame() + 2) { + selection = Selection(); + } + + m_manager->clearInProgressSelection(); + + if (exclusive) { + m_manager->setSelection(selection); + } else { + m_manager->addSelection(selection); + } } + + update(); + } - float ratio = float(w) / float(width()); -// std::cerr << "ratio: " << ratio << std::endl; - size_t newZoomLevel = (size_t)nearbyint(m_zoomLevel * ratio); - if (newZoomLevel < 1) newZoomLevel = 1; - -// std::cerr << "start: " << m_startFrame << ", level " << m_zoomLevel << std::endl; - setZoomLevel(getZoomConstraintBlockSize(newZoomLevel)); - setStartFrame(newStartFrame); - - //cerr << "mouseReleaseEvent: start frame now " << m_startFrame << endl; -// update(); - } m_clickedInRange = false; emit paneInteractedWith(); @@ -285,6 +348,9 @@ void Pane::mouseMoveEvent(QMouseEvent *e) { + ViewManager::ToolMode mode = ViewManager::NavigateMode; + if (m_manager) mode = m_manager->getToolMode(); + if (!m_clickedInRange) { // std::cerr << "Pane: calling identifyLocalFeatures" << std::endl; @@ -302,35 +368,90 @@ update(); } - } else if (m_shiftPressed) { + return; + + } - m_mousePos = e->pos(); - update(); + if (mode == ViewManager::NavigateMode) { - } else { + if (m_shiftPressed) { - long xoff = int(e->x()) - int(m_clickPos.x()); - long frameOff = xoff * m_zoomLevel; + m_mousePos = e->pos(); + update(); - size_t newCentreFrame = m_dragCentreFrame; - - if (frameOff < 0) { - newCentreFrame -= frameOff; - } else if (newCentreFrame >= size_t(frameOff)) { - newCentreFrame -= frameOff; } else { - newCentreFrame = 0; + + long xoff = int(e->x()) - int(m_clickPos.x()); + long frameOff = xoff * m_zoomLevel; + + size_t newCentreFrame = m_dragCentreFrame; + + if (frameOff < 0) { + newCentreFrame -= frameOff; + } else if (newCentreFrame >= size_t(frameOff)) { + newCentreFrame -= frameOff; + } else { + newCentreFrame = 0; + } + + if (newCentreFrame >= getModelsEndFrame()) { + newCentreFrame = getModelsEndFrame(); + if (newCentreFrame > 0) --newCentreFrame; + } + + if (std::max(m_centreFrame, newCentreFrame) - + std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) { + setCentreFrame(newCentreFrame); + } } - if (newCentreFrame >= getModelsEndFrame()) { - newCentreFrame = getModelsEndFrame(); - if (newCentreFrame > 0) --newCentreFrame; + } else if (mode == ViewManager::SelectMode) { + + int mouseFrame = e->x() * m_zoomLevel + getStartFrame(); + size_t resolution = 1; + int snapFrameLeft = mouseFrame; + int snapFrameRight = mouseFrame; + + Layer *layer = getSelectedLayer(); + if (layer) { + snapFrameLeft = layer->getNearestFeatureFrame(mouseFrame, resolution, + false); + snapFrameRight = layer->getNearestFeatureFrame(mouseFrame, resolution, + true); + } + + if (snapFrameLeft < 0) snapFrameLeft = 0; + if (snapFrameRight < 0) snapFrameRight = 0; + + size_t min, max; + + if (m_selectionStartFrame > snapFrameLeft) { + min = snapFrameLeft; + max = m_selectionStartFrame; + } else if (snapFrameRight > m_selectionStartFrame) { + min = m_selectionStartFrame; + max = snapFrameRight; + } else { + min = snapFrameLeft; + max = snapFrameRight; } - if (std::max(m_centreFrame, newCentreFrame) - - std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) { - setCentreFrame(newCentreFrame); + if (m_manager) { + m_manager->setInProgressSelection(Selection(min, max), + !m_ctrlPressed); } + + if (!m_manager || !m_manager->isPlaying()) { + int offset = mouseFrame - getStartFrame(); + int available = getEndFrame() - getStartFrame(); + if (offset >= available * 0.9) { + setCentreFrame(m_centreFrame + int(offset - available * 0.9) + 1); + } else if (offset <= available * 0.15) { + setCentreFrame(m_centreFrame - int(available * 0.15 - offset) - 1); + } + } + + update(); } } @@ -390,6 +511,36 @@ emit paneInteractedWith(); } +void +Pane::toolModeChanged() +{ + ViewManager::ToolMode mode = m_manager->getToolMode(); + std::cerr << "Pane::toolModeChanged(" << mode << ")" << std::endl; + + switch (mode) { + + case ViewManager::NavigateMode: + setCursor(Qt::PointingHandCursor); + break; + + case ViewManager::SelectMode: + setCursor(Qt::ArrowCursor); + break; + + case ViewManager::EditMode: + setCursor(Qt::SizeAllCursor); + break; + + case ViewManager::DrawMode: + setCursor(Qt::CrossCursor); + break; + + case ViewManager::TextMode: + setCursor(Qt::IBeamCursor); + break; + } +} + QString Pane::toXmlString(QString indent, QString extraAttributes) const { diff -r 484e7320f59f -r 01849cd277e6 widgets/Pane.h --- a/widgets/Pane.h Thu Jan 19 17:59:11 2006 +0000 +++ b/widgets/Pane.h Mon Jan 23 17:02:57 2006 +0000 @@ -16,6 +16,7 @@ #include "base/ZoomConstraint.h" #include "base/View.h" +#include "base/Selection.h" class QWidget; class QPaintEvent; @@ -40,6 +41,9 @@ signals: void paneInteractedWith(); +public slots: + virtual void toolModeChanged(); + protected: virtual void paintEvent(QPaintEvent *e); virtual void mousePressEvent(QMouseEvent *e); @@ -55,8 +59,10 @@ QPoint m_mousePos; bool m_clickedInRange; bool m_shiftPressed; + bool m_ctrlPressed; size_t m_dragCentreFrame; bool m_centreLineVisible; + size_t m_selectionStartFrame; }; #endif