Mercurial > hg > svcore
changeset 24:bb9291d84810
* Add ffwd/rewind
* Abstract out MultiSelection
author | Chris Cannam |
---|---|
date | Wed, 08 Feb 2006 17:59:16 +0000 |
parents | 6ace4286ba06 |
children | 7dad8a310963 |
files | base/Layer.h base/Selection.cpp base/Selection.h base/View.cpp base/ViewManager.cpp base/ViewManager.h |
diffstat | 6 files changed, 180 insertions(+), 71 deletions(-) [+] |
line wrap: on
line diff
--- a/base/Layer.h Mon Feb 06 17:24:52 2006 +0000 +++ b/base/Layer.h Wed Feb 08 17:59:16 2006 +0000 @@ -194,6 +194,15 @@ */ virtual void setProperties(const QXmlAttributes &) = 0; + /** + * Indicate that a layer is not currently visible and is not + * expected to become visible in the near future (for example + * because the user has explicitly removed or hidden it). The + * layer may respond by (for example) freeing any cache memory it + * is using, until next time its paint method is called. + */ + virtual void setLayerDormant() { } + signals: void modelChanged(); void modelCompletionChanged();
--- a/base/Selection.cpp Mon Feb 06 17:24:52 2006 +0000 +++ b/base/Selection.cpp Wed Feb 08 17:59:16 2006 +0000 @@ -91,3 +91,98 @@ m_endFrame == s.m_endFrame); } + +MultiSelection::MultiSelection() +{ +} + +MultiSelection::~MultiSelection() +{ +} + +const MultiSelection::SelectionList & +MultiSelection::getSelections() const +{ + return m_selections; +} + +void +MultiSelection::setSelection(const Selection &selection) +{ + clearSelections(); + addSelection(selection); +} + +void +MultiSelection::addSelection(const Selection &selection) +{ + m_selections.insert(selection); + + // Cope with a sitation where the new selection overlaps one or + // more existing ones. This is a terribly inefficient way to do + // this, but that probably isn't significant in real life. + + // It's essential for the correct operation of + // getContainingSelection that the selections do not overlap, so + // this is not just a frill. + + for (SelectionList::iterator i = m_selections.begin(); + i != m_selections.end(); ) { + + SelectionList::iterator j = i; + if (++j == m_selections.end()) break; + + if (i->getEndFrame() >= j->getStartFrame()) { + Selection merged(i->getStartFrame(), + std::max(i->getEndFrame(), j->getEndFrame())); + m_selections.erase(i); + m_selections.erase(j); + m_selections.insert(merged); + i = m_selections.begin(); + } else { + ++i; + } + } +} + +void +MultiSelection::removeSelection(const Selection &selection) +{ + //!!! Likewise this needs to cope correctly with the situation + //where selection is not one of the original selection set but + //simply overlaps one of them (cutting down the original selection + //appropriately) + + if (m_selections.find(selection) != m_selections.end()) { + m_selections.erase(selection); + } +} + +void +MultiSelection::clearSelections() +{ + if (!m_selections.empty()) { + m_selections.clear(); + } +} + +Selection +MultiSelection::getContainingSelection(size_t frame, bool defaultToFollowing) +{ + // This scales very badly with the number of selections, but it's + // more efficient for very small numbers of selections than a more + // scalable method, and I think that may be what we need + + for (SelectionList::const_iterator i = m_selections.begin(); + i != m_selections.end(); ++i) { + + if (i->contains(frame)) return *i; + + if (i->getStartFrame() > frame) { + if (defaultToFollowing) return *i; + else return Selection(); + } + } + + return Selection(); +}
--- a/base/Selection.h Mon Feb 06 17:24:52 2006 +0000 +++ b/base/Selection.h Wed Feb 08 17:59:16 2006 +0000 @@ -11,6 +11,7 @@ #define _SELECTION_H_ #include <cstddef> +#include <set> class Selection { @@ -34,4 +35,31 @@ size_t m_endFrame; }; +class MultiSelection +{ +public: + MultiSelection(); + virtual ~MultiSelection(); + + typedef std::set<Selection> SelectionList; + + const SelectionList &getSelections() const; + void setSelection(const Selection &selection); + void addSelection(const Selection &selection); + void removeSelection(const Selection &selection); + void clearSelections(); + + /** + * Return the selection that contains a given frame. + * If defaultToFollowing is true, and if the frame is not in a + * selected area, return the next selection after the given frame. + * Return the empty selection if no appropriate selection is found. + */ + Selection getContainingSelection(size_t frame, bool defaultToFollowing); + +protected: + SelectionList m_selections; +}; + + #endif
--- a/base/View.cpp Mon Feb 06 17:24:52 2006 +0000 +++ b/base/View.cpp Wed Feb 08 17:59:16 2006 +0000 @@ -544,7 +544,7 @@ if (m_manager && m_manager->isPlaying() && m_manager->getPlaySelectionMode()) { - ViewManager::SelectionList selections = m_manager->getSelections(); + MultiSelection::SelectionList selections = m_manager->getSelections(); if (!selections.empty()) { size_t selectionStart = selections.begin()->getStartFrame(); if (sf < long(selectionStart) - w / 10) { @@ -1110,7 +1110,7 @@ void View::drawSelections(QPainter &paint) { - ViewManager::SelectionList selections; + MultiSelection::SelectionList selections; if (m_manager) { selections = m_manager->getSelections(); @@ -1131,7 +1131,7 @@ const QFontMetrics &metrics = paint.fontMetrics(); - for (ViewManager::SelectionList::iterator i = selections.begin(); + for (MultiSelection::SelectionList::iterator i = selections.begin(); i != selections.end(); ++i) { int p0 = getXForFrame(i->getStartFrame());
--- a/base/ViewManager.cpp Mon Feb 06 17:24:52 2006 +0000 +++ b/base/ViewManager.cpp Wed Feb 08 17:59:16 2006 +0000 @@ -20,6 +20,7 @@ m_playSource(0), m_globalCentreFrame(0), m_globalZoom(1024), + m_playbackFrame(0), m_lastLeft(0), m_lastRight(0), m_inProgressExclusive(true), @@ -54,6 +55,27 @@ return m_globalZoom; } +unsigned long +ViewManager::getPlaybackFrame() const +{ + if (m_playSource && m_playSource->isPlaying()) { + m_playbackFrame = m_playSource->getCurrentPlayingFrame(); + } + return m_playbackFrame; +} + +void +ViewManager::setPlaybackFrame(unsigned long f) +{ + if (m_playbackFrame != f) { + m_playbackFrame = f; + if (m_playSource && m_playSource->isPlaying()) { + m_playSource->play(f); + } + emit playbackFrameChanged(f); + } +} + bool ViewManager::haveInProgressSelection() const { @@ -83,95 +105,44 @@ emit inProgressSelectionChanged(); } -const ViewManager::SelectionList & +const MultiSelection::SelectionList & ViewManager::getSelections() const { - return m_selections; + return m_selections.getSelections(); } void ViewManager::setSelection(const Selection &selection) { - clearSelections(); - addSelection(selection); + m_selections.setSelection(selection); + emit selectionChanged(); } void ViewManager::addSelection(const Selection &selection) { - m_selections.insert(selection); - - // Cope with a sitation where the new selection overlaps one or - // more existing ones. This is a terribly inefficient way to do - // this, but that probably isn't significant in real life. - - // It's essential for the correct operation of - // getContainingSelection that the selections do not overlap, so - // this is not just a frill. - - for (SelectionList::iterator i = m_selections.begin(); - i != m_selections.end(); ) { - - SelectionList::iterator j = i; - if (++j == m_selections.end()) break; - - if (i->getEndFrame() >= j->getStartFrame()) { - Selection merged(i->getStartFrame(), - std::max(i->getEndFrame(), j->getEndFrame())); - m_selections.erase(i); - m_selections.erase(j); - m_selections.insert(merged); - i = m_selections.begin(); - } else { - ++i; - } - } - + m_selections.addSelection(selection); emit selectionChanged(); } void ViewManager::removeSelection(const Selection &selection) { - //!!! Likewise this needs to cope correctly with the situation - //where selection is not one of the original selection set but - //simply overlaps one of them (cutting down the original selection - //appropriately) - - if (m_selections.find(selection) != m_selections.end()) { - m_selections.erase(selection); - emit selectionChanged(); - } + m_selections.removeSelection(selection); + emit selectionChanged(); } void ViewManager::clearSelections() { - if (!m_selections.empty()) { - m_selections.clear(); - emit selectionChanged(); - } + m_selections.clearSelections(); + emit selectionChanged(); } Selection ViewManager::getContainingSelection(size_t frame, bool defaultToFollowing) { - // This scales very badly with the number of selections, but it's - // more efficient for very small numbers of selections than a more - // scalable method, and I think that may be what we need - - for (SelectionList::const_iterator i = m_selections.begin(); - i != m_selections.end(); ++i) { - - if (i->contains(frame)) return *i; - - if (i->getStartFrame() > frame) { - if (defaultToFollowing) return *i; - else return Selection(); - } - } - - return Selection(); + return m_selections.getContainingSelection(frame, defaultToFollowing); } void @@ -247,13 +218,13 @@ } } - m_globalCentreFrame = m_playSource->getCurrentPlayingFrame(); + m_playbackFrame = m_playSource->getCurrentPlayingFrame(); #ifdef DEBUG_VIEW_MANAGER - std::cout << "ViewManager::checkPlayStatus: Playing, frame " << m_globalCentreFrame << ", levels " << m_lastLeft << "," << m_lastRight << std::endl; + std::cout << "ViewManager::checkPlayStatus: Playing, frame " << m_playbackFrame << ", levels " << m_lastLeft << "," << m_lastRight << std::endl; #endif - emit playbackFrameChanged(m_globalCentreFrame); + emit playbackFrameChanged(m_playbackFrame); QTimer::singleShot(20, this, SLOT(checkPlayStatus())); @@ -296,11 +267,14 @@ unsigned long playFrame = m_playSource->getCurrentPlayingFrame(); unsigned long diff = std::max(f, playFrame) - std::min(f, playFrame); if (diff > 20000) { + m_playbackFrame = f; m_playSource->play(f); #ifdef DEBUG_VIEW_MANAGER std::cout << "ViewManager::considerSeek: reseeking from " << playFrame << " to " << f << std::endl; #endif } + } else { + m_playbackFrame = f; //!!! only if that view is in scroll mode? } }
--- a/base/ViewManager.h Mon Feb 06 17:24:52 2006 +0000 +++ b/base/ViewManager.h Wed Feb 08 17:59:16 2006 +0000 @@ -14,7 +14,6 @@ #include <QTimer> #include <map> -#include <set> #include "Selection.h" @@ -50,14 +49,17 @@ unsigned long getGlobalCentreFrame() const; unsigned long getGlobalZoom() const; - typedef std::set<Selection> SelectionList; + unsigned long getPlaybackFrame() const; + void setPlaybackFrame(unsigned long frame); bool haveInProgressSelection() const; const Selection &getInProgressSelection(bool &exclusive) const; void setInProgressSelection(const Selection &selection, bool exclusive); void clearInProgressSelection(); - const SelectionList &getSelections() const; + const MultiSelection &getSelection() const; + + const MultiSelection::SelectionList &getSelections() const; void setSelection(const Selection &selection); void addSelection(const Selection &selection); void removeSelection(const Selection &selection); @@ -125,11 +127,12 @@ AudioPlaySource *m_playSource; unsigned long m_globalCentreFrame; unsigned long m_globalZoom; + mutable unsigned long m_playbackFrame; float m_lastLeft; float m_lastRight; - SelectionList m_selections; + MultiSelection m_selections; Selection m_inProgressSelection; bool m_inProgressExclusive;