# HG changeset patch # User Chris Cannam # Date 1183042258 0 # Node ID 1a49bd0d83754d36f0846f364f52241cc3f536f6 # Parent 61a7046544972013dd5af9c01b1e6541dc31579b * Change a number of keyboard shortcuts -- get rid of all the Alt+ shortcuts and introduce a few more Ctrl+ ones instead, as well as a number of plain single keypresses * Add Playback menu * Add time-ruler support for snap to feature, use it in ffwd/rewind (rewind still needs fixing) * restore layer hierarchy window prior to making it work correctly diff -r 61a704654497 -r 1a49bd0d8375 layer/TimeRulerLayer.cpp --- a/layer/TimeRulerLayer.cpp Tue Jun 26 14:57:29 2007 +0000 +++ b/layer/TimeRulerLayer.cpp Thu Jun 28 14:50:58 2007 +0000 @@ -22,6 +22,7 @@ #include #include +#include using std::cerr; using std::endl; @@ -133,6 +134,143 @@ } } +bool +TimeRulerLayer::snapToFeatureFrame(View *v, int &frame, + size_t &resolution, SnapType snap) const +{ + if (!m_model) { + resolution = 1; + return false; + } + + bool q; + int tick = getMajorTickSpacing(v, q); + RealTime rtick = RealTime::fromMilliseconds(tick); + int rate = m_model->getSampleRate(); + + RealTime rt = RealTime::frame2RealTime(frame, rate); + double ratio = rt / rtick; + + int rounded = lrint(ratio); + RealTime rdrt = rtick * rounded; + + int left = RealTime::realTime2Frame(rdrt, rate); + resolution = RealTime::realTime2Frame(rtick, rate); + int right = left + resolution; + + switch (snap) { + + case SnapLeft: + frame = left; + break; + + case SnapRight: + frame = right; + break; + + case SnapNearest: + { + if (abs(frame - left) > abs(right - frame)) { + frame = right; + } else { + frame = left; + } + break; + } + + case SnapNeighbouring: + { + int dl = -1, dr = -1; + int x = v->getXForFrame(frame); + + if (left > v->getStartFrame() && + left < v->getEndFrame()) { + dl = abs(v->getXForFrame(left) - x); + } + + if (right > v->getStartFrame() && + right < v->getEndFrame()) { + dr = abs(v->getXForFrame(right) - x); + } + + int fuzz = 2; + + if (dl >= 0 && dr >= 0) { + if (dl < dr) { + if (dl <= fuzz) { + frame = left; + } + } else { + if (dr < fuzz) { + frame = right; + } + } + } else if (dl >= 0) { + if (dl <= fuzz) { + frame = left; + } + } else if (dr >= 0) { + if (dr <= fuzz) { + frame = right; + } + } + } + } + + return true; +} + +int +TimeRulerLayer::getMajorTickSpacing(View *v, bool &quarterTicks) const +{ + // return value is in milliseconds + + if (!m_model || !v) return 1000; + + int sampleRate = m_model->getSampleRate(); + if (!sampleRate) return 1000; + + long startFrame = v->getStartFrame(); + long endFrame = v->getEndFrame(); + + int minPixelSpacing = 50; + + RealTime rtStart = RealTime::frame2RealTime(startFrame, sampleRate); + RealTime rtEnd = RealTime::frame2RealTime(endFrame, sampleRate); + + int count = v->width() / minPixelSpacing; + if (count < 1) count = 1; + RealTime rtGap = (rtEnd - rtStart) / count; + + int incms; + quarterTicks = false; + + if (rtGap.sec > 0) { + incms = 1000; + int s = rtGap.sec; + if (s > 0) { incms *= 5; s /= 5; } + if (s > 0) { incms *= 2; s /= 2; } + if (s > 0) { incms *= 6; s /= 6; quarterTicks = true; } + if (s > 0) { incms *= 5; s /= 5; quarterTicks = false; } + if (s > 0) { incms *= 2; s /= 2; } + if (s > 0) { incms *= 6; s /= 6; quarterTicks = true; } + while (s > 0) { + incms *= 10; + s /= 10; + quarterTicks = false; + } + } else { + incms = 1; + int ms = rtGap.msec(); + if (ms > 0) { incms *= 10; ms /= 10; } + if (ms > 0) { incms *= 10; ms /= 10; } + if (ms > 0) { incms *= 5; ms /= 5; } + if (ms > 0) { incms *= 2; ms /= 2; } + } + + return incms; +} + void TimeRulerLayer::paint(View *v, QPainter &paint, QRect rect) const { @@ -151,8 +289,6 @@ long rectStart = startFrame + (rect.x() - 100) * zoomLevel; long rectEnd = startFrame + (rect.x() + rect.width() + 100) * zoomLevel; -// if (rectStart < startFrame) rectStart = startFrame; -// if (rectEnd > endFrame) rectEnd = endFrame; // std::cerr << "TimeRulerLayer::paint: calling paint.save()" << std::endl; paint.save(); @@ -160,40 +296,8 @@ int minPixelSpacing = 50; - RealTime rtStart = RealTime::frame2RealTime(startFrame, sampleRate); - RealTime rtEnd = RealTime::frame2RealTime(endFrame, sampleRate); -// cerr << "startFrame " << startFrame << ", endFrame " << v->getEndFrame() << ", rtStart " << rtStart << ", rtEnd " << rtEnd << endl; - int count = v->width() / minPixelSpacing; - if (count < 1) count = 1; - RealTime rtGap = (rtEnd - rtStart) / count; -// cerr << "rtGap is " << rtGap << endl; - - int incms; bool quarter = false; - - if (rtGap.sec > 0) { - incms = 1000; - int s = rtGap.sec; - if (s > 0) { incms *= 5; s /= 5; } - if (s > 0) { incms *= 2; s /= 2; } - if (s > 0) { incms *= 6; s /= 6; quarter = true; } - if (s > 0) { incms *= 5; s /= 5; quarter = false; } - if (s > 0) { incms *= 2; s /= 2; } - if (s > 0) { incms *= 6; s /= 6; quarter = true; } - while (s > 0) { - incms *= 10; - s /= 10; - quarter = false; - } - } else { - incms = 1; - int ms = rtGap.msec(); - if (ms > 0) { incms *= 10; ms /= 10; } - if (ms > 0) { incms *= 10; ms /= 10; } - if (ms > 0) { incms *= 5; ms /= 5; } - if (ms > 0) { incms *= 2; ms /= 2; } - } -// cerr << "incms is " << incms << endl; + int incms = getMajorTickSpacing(v, quarter); RealTime rt = RealTime::frame2RealTime(rectStart, sampleRate); long ms = rt.sec * 1000 + rt.msec(); diff -r 61a704654497 -r 1a49bd0d8375 layer/TimeRulerLayer.h --- a/layer/TimeRulerLayer.h Tue Jun 26 14:57:29 2007 +0000 +++ b/layer/TimeRulerLayer.h Thu Jun 28 14:50:58 2007 +0000 @@ -44,6 +44,8 @@ void setLabelHeight(LabelHeight h) { m_labelHeight = h; } LabelHeight getLabelHeight() const { return m_labelHeight; } + virtual bool snapToFeatureFrame(View *, int &, size_t &, SnapType) const; + virtual PropertyList getProperties() const; virtual QString getPropertyLabel(const PropertyName &) const; virtual PropertyType getPropertyType(const PropertyName &) const; @@ -66,6 +68,8 @@ Model *m_model; QColor m_colour; LabelHeight m_labelHeight; + + int getMajorTickSpacing(View *, bool &quarterTicks) const; }; #endif diff -r 61a704654497 -r 1a49bd0d8375 view/PaneStack.cpp --- a/view/PaneStack.cpp Tue Jun 26 14:57:29 2007 +0000 +++ b/view/PaneStack.cpp Thu Jun 28 14:50:58 2007 +0000 @@ -115,6 +115,9 @@ connect(pane, SIGNAL(rightButtonMenuRequested(QPoint)), this, SLOT(rightButtonMenuRequested(QPoint))); + emit paneAdded(pane); + emit paneAdded(); + if (!m_currentPane) { setCurrentPane(pane); } @@ -208,6 +211,8 @@ } } + emit paneAboutToBeDeleted(pane); + delete pane->parent(); if (m_currentPane == pane) { @@ -217,6 +222,8 @@ setCurrentPane(0); } } + + emit paneDeleted(); } int diff -r 61a704654497 -r 1a49bd0d8375 view/PaneStack.h --- a/view/PaneStack.h Tue Jun 26 14:57:29 2007 +0000 +++ b/view/PaneStack.h Thu Jun 28 14:50:58 2007 +0000 @@ -72,6 +72,11 @@ void propertyStacksResized(); void contextHelpChanged(const QString &); + void paneAdded(Pane *pane); + void paneAdded(); + void paneAboutToBeDeleted(Pane *pane); + void paneDeleted(); + public slots: void propertyContainerAdded(PropertyContainer *); void propertyContainerRemoved(PropertyContainer *); diff -r 61a704654497 -r 1a49bd0d8375 view/ViewManager.cpp --- a/view/ViewManager.cpp Tue Jun 26 14:57:29 2007 +0000 +++ b/view/ViewManager.cpp Thu Jun 28 14:50:58 2007 +0000 @@ -188,6 +188,26 @@ CommandHistory::getInstance()->addCommand(command); } +size_t +ViewManager::constrainFrameToSelection(size_t frame) const +{ + MultiSelection::SelectionList sl = getSelections(); + if (sl.empty()) return frame; + + size_t selectionStartFrame = sl.begin()->getStartFrame(); + if (frame < selectionStartFrame) { + frame = selectionStartFrame; + return frame; + } + + MultiSelection::SelectionList::iterator i = sl.end(); + --i; + size_t selectionEndFrame = i->getEndFrame(); + if (frame > selectionEndFrame) frame = selectionEndFrame; + + return frame; +} + void ViewManager::signalSelectionChange() { diff -r 61a704654497 -r 1a49bd0d8375 view/ViewManager.h --- a/view/ViewManager.h Tue Jun 26 14:57:29 2007 +0000 +++ b/view/ViewManager.h Thu Jun 28 14:50:58 2007 +0000 @@ -76,6 +76,7 @@ void addSelection(const Selection &selection); void removeSelection(const Selection &selection); void clearSelections(); + size_t constrainFrameToSelection(size_t frame) const; /** * Return the selection that contains a given frame. diff -r 61a704654497 -r 1a49bd0d8375 widgets/AudioDial.h --- a/widgets/AudioDial.h Tue Jun 26 14:57:29 2007 +0000 +++ b/widgets/AudioDial.h Thu Jun 28 14:50:58 2007 +0000 @@ -75,6 +75,8 @@ const RangeMapper *rangeMapper() const { return m_rangeMapper; } float mappedValue() const; + int defaultValue() const { return m_defaultValue; } + void setShowToolTip(bool show); signals: diff -r 61a704654497 -r 1a49bd0d8375 widgets/LayerTree.cpp --- a/widgets/LayerTree.cpp Tue Jun 26 14:57:29 2007 +0000 +++ b/widgets/LayerTree.cpp Thu Jun 28 14:50:58 2007 +0000 @@ -27,9 +27,11 @@ class ViewObjectAssoc : public QObject { public: - ViewObjectAssoc(QObject *parent, View *v, QObject *o) : - QObject(parent), view(v), object(o) { + ViewObjectAssoc(View *v, QObject *o) : + QObject(0), view(v), object(o) { ++extantCount; + std::cerr << "ViewObjectAssoc (now " << extantCount << " extant)" + << std::endl; } virtual ~ViewObjectAssoc() { @@ -50,6 +52,8 @@ QAbstractItemModel(parent), m_stack(stack) { + connect(stack, SIGNAL(paneAdded()), this, SIGNAL(layoutChanged())); + connect(stack, SIGNAL(paneDeleted()), this, SIGNAL(layoutChanged())); } LayerTreeModel::~LayerTreeModel() @@ -156,12 +160,14 @@ if (column == 0) { std::cerr << "parent is pane, returning layer" << std::endl; ViewObjectAssoc *assoc = new ViewObjectAssoc - (const_cast(this), pane, layer); +// (const_cast(this), pane, layer); + (pane, layer); return createIndex(row, column, assoc); } else { std::cerr << "parent is pane, column != 0, returning model" << std::endl; ViewObjectAssoc *assoc = new ViewObjectAssoc - (const_cast(this), pane, layer->getModel()); +// (const_cast(this), pane, layer->getModel()); + (pane, layer->getModel()); return createIndex(row, column, assoc); } }