# HG changeset patch # User Chris Cannam # Date 1396425093 -3600 # Node ID 9cfcb2924ee3594bf9700c64afd2217c23a7e51c # Parent ad01e7d4a956016453871ee0746dc0ee99c8c91d# Parent 09e2677e34e7156a1091fc37c4d24db6b83f5604 Merge from branch tonioni diff -r ad01e7d4a956 -r 9cfcb2924ee3 layer/FlexiNoteLayer.cpp --- a/layer/FlexiNoteLayer.cpp Wed Apr 02 08:50:18 2014 +0100 +++ b/layer/FlexiNoteLayer.cpp Wed Apr 02 08:51:33 2014 +0100 @@ -1043,7 +1043,7 @@ m_originalPoint = FlexiNote(m_editingPoint); if (m_editMode == RightBoundary) { - m_dragPointX = v->getXForFrame(m_editingPoint.frame + m_editingPoint.duration); + m_dragPointX = v->getXForFrame(m_editingPoint.frame + m_editingPoint.duration); } else { m_dragPointX = v->getXForFrame(m_editingPoint.frame); } @@ -1079,7 +1079,7 @@ break; } } - std::cerr << "note frame: " << onset << ", left boundary: " << m_greatestLeftNeighbourFrame << ", right boundary: " << m_smallestRightNeighbourFrame << std::endl; + std::cerr << "editStart: mode is " << m_editMode << ", note frame: " << onset << ", left boundary: " << m_greatestLeftNeighbourFrame << ", right boundary: " << m_smallestRightNeighbourFrame << std::endl; } void @@ -1214,39 +1214,55 @@ return; } - // MM: simpler declaration - FlexiNote note(0); - if (!getPointToDrag(v, e->x(), e->y(), note)) return; - long frame = v->getFrameForX(e->x()); - int gap = 0; // MM: I prefer a gap of 0, but we can decide later + splitNotesAt(v, frame, e); +} + +void +FlexiNoteLayer::splitNotesAt(View *v, int frame) +{ + splitNotesAt(v, frame, 0); +} + +void +FlexiNoteLayer::splitNotesAt(View *v, int frame, QMouseEvent *e) +{ + FlexiNoteModel::PointList onPoints = m_model->getPoints(frame); + if (onPoints.empty()) return; - // MM: changed this a bit, to make it slightly clearer (// GF: nice changes!) - FlexiNote newNote1(note.frame, note.value, - frame - note.frame - gap, - note.level, note.label); - - FlexiNote newNote2(frame, note.value, - note.duration - newNote1.duration, - note.level, note.label); - - if (m_intelligentActions) { - updateNoteValue(v,newNote1); - updateNoteValue(v,newNote2); - } + FlexiNote note(*onPoints.begin()); FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand (m_model, tr("Edit Point")); command->deletePoint(note); - if ((e->modifiers() & Qt::ShiftModifier)) { - finish(command); - return; + + if (!e || !(e->modifiers() & Qt::ShiftModifier)) { + + int gap = 0; // MM: I prefer a gap of 0, but we can decide later + + FlexiNote newNote1(note.frame, note.value, + frame - note.frame - gap, + note.level, note.label); + + FlexiNote newNote2(frame, note.value, + note.duration - newNote1.duration, + note.level, note.label); + + if (m_intelligentActions) { + if (updateNoteValue(v, newNote1)) { + command->addPoint(newNote1); + } + if (updateNoteValue(v, newNote2)) { + command->addPoint(newNote2); + } + } else { + command->addPoint(newNote1); + command->addPoint(newNote2); + } } - command->addPoint(newNote1); - command->addPoint(newNote2); + finish(command); - } void @@ -1276,8 +1292,7 @@ } if (!m_intelligentActions || - m_model->getPoints(frame).empty() && duration > 0) - { + (m_model->getPoints(frame).empty() && duration > 0)) { FlexiNote newNote(frame, value, duration, 100, "new note"); FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand (m_model, tr("Add Point")); @@ -1286,31 +1301,137 @@ } } +SparseTimeValueModel * +FlexiNoteLayer::getAssociatedPitchModel(View *v) const +{ + // Better than we used to do, but still not very satisfactory + + cerr << "FlexiNoteLayer::getAssociatedPitchModel()" << endl; + + for (int i = 0; i < v->getLayerCount(); ++i) { + Layer *layer = v->getLayer(i); + if (layer && !layer->isLayerDormant(v) && + layer->getLayerPresentationName() != "candidate") { + cerr << "FlexiNoteLayer::getAssociatedPitchModel: looks like our layer is " << layer << endl; + SparseTimeValueModel *model = qobject_cast + (layer->getModel()); + cerr << "FlexiNoteLayer::getAssociatedPitchModel: and its model is " << model << endl; + if (model && model->getScaleUnits() == "Hz") { + cerr << "FlexiNoteLayer::getAssociatedPitchModel: it's good, returning " << model << endl; + return model; + } + } + } + return 0; +} void +FlexiNoteLayer::snapSelectedNotesToPitchTrack(View *v, Selection s) +{ + if (!m_model) return; + + FlexiNoteModel::PointList points = + m_model->getPoints(s.getStartFrame(), s.getEndFrame()); + + FlexiNoteModel::EditCommand *command = new FlexiNoteModel::EditCommand + (m_model, tr("Snap Notes")); + + cerr << "snapSelectedNotesToPitchTrack: selection is from " << s.getStartFrame() << " to " << s.getEndFrame() << endl; + + for (FlexiNoteModel::PointList::iterator i = points.begin(); + i != points.end(); ++i) { + + FlexiNote note(*i); + + cerr << "snapSelectedNotesToPitchTrack: looking at note from " << note.frame << " to " << note.frame + note.duration << endl; + + if (!s.contains(note.frame) && + !s.contains(note.frame + note.duration - 1)) { + continue; + } + + FlexiNote newNote(note); + + command->deletePoint(note); + + if (updateNoteValue(v, newNote)) { + command->addPoint(newNote); + } + } + + finish(command); +} + +void +FlexiNoteLayer::mergeNotes(View *v, Selection s, bool inclusive) +{ + FlexiNoteModel::PointList points = + m_model->getPoints(s.getStartFrame(), s.getEndFrame()); + + FlexiNoteModel::PointList::iterator i = points.begin(); + if (inclusive) { + while (i != points.end() && i->frame + i->duration < s.getStartFrame()) { + ++i; + } + } else { + while (i != points.end() && i->frame < s.getStartFrame()) { + ++i; + } + } + + if (i == points.end()) return; + + FlexiNoteModel::EditCommand *command = + new FlexiNoteModel::EditCommand(m_model, tr("Merge Notes")); + + FlexiNote newNote(*i); + + while (i != points.end()) { + + if (inclusive) { + if (i->frame >= s.getEndFrame()) break; + } else { + if (i->frame + i->duration > s.getEndFrame()) break; + } + + newNote.duration = i->frame + i->duration - newNote.frame; + command->deletePoint(*i); + + ++i; + } + + updateNoteValue(v, newNote); + command->addPoint(newNote); + finish(command); +} + +bool FlexiNoteLayer::updateNoteValue(View *v, FlexiNoteModel::Point ¬e) const { - //GF: update the note value conforming the median of pitch values in the underlying note layer - Layer *layer = v->getLayer(1); // GF: !!! gross assumption about correct layer order - SparseTimeValueModel *model = 0; - if (layer && layer->getModel()) - model = dynamic_cast(layer->getModel()); - - if (!model) return; + SparseTimeValueModel *model = getAssociatedPitchModel(v); + if (!model) return false; std::cerr << model->getTypeName() << std::endl; - SparseModel::PointList dataPoints = model->getPoints(note.frame, note.frame + note.duration); - if (dataPoints.empty()) return; + SparseModel::PointList dataPoints = + model->getPoints(note.frame, note.frame + note.duration); - // std::cerr << "frame " << note.frame << ": " << dataPoints.size() << " candidate points" << std::endl; + std::cerr << "frame " << note.frame << ": " << dataPoints.size() << " candidate points" << std::endl; + if (dataPoints.empty()) return false; + std::vector pitchValues; - for (SparseModel::PointList::const_iterator i = dataPoints.begin(); - i != dataPoints.end(); ++i) { - pitchValues.push_back((*i).value); + for (SparseModel::PointList::const_iterator i = + dataPoints.begin(); i != dataPoints.end(); ++i) { + if (i->frame >= note.frame && + i->frame < note.frame + note.duration) { + pitchValues.push_back(i->value); + } } + + if (pitchValues.empty()) return false; + sort(pitchValues.begin(), pitchValues.end()); size_t size = pitchValues.size(); double median; @@ -1322,6 +1443,8 @@ } note.value = median; + + return true; } void diff -r ad01e7d4a956 -r 9cfcb2924ee3 layer/FlexiNoteLayer.h --- a/layer/FlexiNoteLayer.h Wed Apr 02 08:50:18 2014 +0100 +++ b/layer/FlexiNoteLayer.h Wed Apr 02 08:51:33 2014 +0100 @@ -28,7 +28,7 @@ class View; class QPainter; - +class SparseTimeValueModel; class FlexiNoteLayer : public SingleColourLayer, public VerticalScaleLayer @@ -78,6 +78,10 @@ virtual bool paste(View *v, const Clipboard &from, int frameOffset, bool interactive); + void splitNotesAt(View *v, int frame); + void snapSelectedNotesToPitchTrack(View *v, Selection s); + void mergeNotes(View *v, Selection s, bool inclusive); + virtual const Model *getModel() const { return m_model; } void setModel(FlexiNoteModel *model); @@ -169,7 +173,9 @@ bool getPointToDrag(View *v, int x, int y, FlexiNoteModel::Point &) const; bool getNoteToEdit(View *v, int x, int y, FlexiNoteModel::Point &) const; void getRelativeMousePosition(View *v, FlexiNoteModel::Point ¬e, int x, int y, bool &closeToLeft, bool &closeToRight, bool &closeToTop, bool &closeToBottom) const; - void updateNoteValue(View *v, FlexiNoteModel::Point ¬e) const; + SparseTimeValueModel *getAssociatedPitchModel(View *v) const; + bool updateNoteValue(View *v, FlexiNoteModel::Point ¬e) const; + void splitNotesAt(View *v, int frame, QMouseEvent *e); FlexiNoteModel *m_model; bool m_editing; diff -r ad01e7d4a956 -r 9cfcb2924ee3 view/Pane.cpp --- a/view/Pane.cpp Wed Apr 02 08:50:18 2014 +0100 +++ b/view/Pane.cpp Wed Apr 02 08:51:33 2014 +0100 @@ -344,10 +344,10 @@ } if (layer == getSelectedLayer() && - !shouldIlluminateLocalSelection(discard, b0, b1)) { - - pos = m_identifyPoint; - return m_identifyFeatures; + !shouldIlluminateLocalSelection(discard, b0, b1)) { + + pos = m_identifyPoint; + return m_identifyFeatures; } return false; @@ -364,17 +364,17 @@ !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; + Selection s(getSelectionAt(m_identifyPoint.x(), + closeToLeft, closeToRight)); + + if (!s.isEmpty()) { + if (getSelectedLayer() && getSelectedLayer()->isLayerEditable()) { + + pos = m_identifyPoint; + return true; + } } } - } return false; } @@ -1235,6 +1235,18 @@ tr("Show pane context menu")); } +Layer * +Pane::getTopFlexiNoteLayer() +{ + for (int i = int(m_layers.size()) - 1; i >= 0; --i) { + if (LayerFactory::getInstance()->getLayerType(m_layers[i]) == + LayerFactory::FlexiNotes) { + return m_layers[i]; + } + } + return 0; +} + void Pane::mousePressEvent(QMouseEvent *e) { @@ -1346,8 +1358,8 @@ } else if (mode == ViewManager::NoteEditMode) { std::cerr << "mouse pressed in note edit mode" << std::endl; - Layer *layer = getSelectedLayer(); - if (layer && layer->isLayerEditable()) { + Layer *layer = getTopFlexiNoteLayer(); + if (layer) { layer->splitStart(this, e); } @@ -1461,11 +1473,22 @@ } else if (mode == ViewManager::NoteEditMode) { //GF: handle mouse release for NoteEditMode (note: works but will need to re-think this a bit later) - Layer *layer = getSelectedLayer(); - if (layer && layer->isLayerEditable()) { + Layer *layer = getTopFlexiNoteLayer(); + + if (layer) { layer->splitEnd(this, e); - update(); } - + update(); + + if (m_editing) { + if (!editSelectionEnd(e)) { + layer->editEnd(this, e); + update(); + } + } + } + + } else if (mode == ViewManager::EditMode) { + if (m_editing) { if (!editSelectionEnd(e)) { Layer *layer = getSelectedLayer(); @@ -1476,19 +1499,6 @@ } } - } else if (mode == ViewManager::EditMode) { - - // GF: edited this previously, but restored to original state - if (m_editing) { - if (!editSelectionEnd(e)) { - Layer *layer = getSelectedLayer(); - if (layer && layer->isLayerEditable()) { - layer->editEnd(this, e); - update(); - } - } - } - } else if (mode == ViewManager::MeasureMode) { Layer *layer = getTopLayer(); @@ -1539,10 +1549,12 @@ // GF: handle mouse move for context sensitive cursor switching in NoteEditMode. // GF: Propagate the event to FlexiNoteLayer. I somehow feel it's best handeled there rather than here, but perhaps not if this will be needed elsewhere too. - if (mode == ViewManager::NoteEditMode && LayerFactory::getInstance()->getLayerType(getTopLayer()) == LayerFactory::FlexiNotes) { - - dynamic_cast(getTopLayer())->mouseMoveEvent(this, e); - + if (mode == ViewManager::NoteEditMode) { + FlexiNoteLayer *layer = qobject_cast(getTopFlexiNoteLayer()); + if (layer) { + layer->mouseMoveEvent(this, e); //!!! ew + return; + } } if (mode == ViewManager::SelectMode && hasTopLayerTimeXAxis()) { @@ -1651,8 +1663,8 @@ e->modifiers()); if (!editSelectionStart(&clickEvent)) { - Layer *layer = getSelectedLayer(); - if (layer && layer->isLayerEditable()) { + Layer *layer = getTopFlexiNoteLayer(); + if (layer) { std::cerr << "calling edit start" << std::endl; layer->editStart(this, &clickEvent); } diff -r ad01e7d4a956 -r 9cfcb2924ee3 view/Pane.h --- a/view/Pane.h Wed Apr 02 08:50:18 2014 +0100 +++ b/view/Pane.h Wed Apr 02 08:51:33 2014 +0100 @@ -136,6 +136,8 @@ void updateContextHelp(const QPoint *pos); void edgeScrollMaybe(int x); + Layer *getTopFlexiNoteLayer(); + bool m_identifyFeatures; QPoint m_identifyPoint; QPoint m_clickPos; diff -r ad01e7d4a956 -r 9cfcb2924ee3 widgets/ActivityLog.cpp --- a/widgets/ActivityLog.cpp Wed Apr 02 08:50:18 2014 +0100 +++ b/widgets/ActivityLog.cpp Wed Apr 02 08:51:33 2014 +0100 @@ -25,6 +25,13 @@ #include +#include "base/Debug.h" + +using std::cerr; +using std::endl; + +#define PRINT_ACTIVITY 1 + ActivityLog::ActivityLog() : QDialog() { setWindowTitle(tr("Activity Log")); @@ -53,9 +60,16 @@ ActivityLog::activityHappened(QString name) { name = name.replace("&", ""); -// SVDEBUG << "ActivityLog::activityHappened(" << name << ")" << endl; + +#ifdef PRINT_ACTIVITY + cerr << "ActivityLog: " << name; if (name == m_prevName) { -// cerr << "(ignoring duplicate)" << endl; + cerr << " (duplicate)"; + } + cerr << endl; +#endif + + if (name == m_prevName) { return; } m_prevName = name; diff -r ad01e7d4a956 -r 9cfcb2924ee3 widgets/CommandHistory.cpp --- a/widgets/CommandHistory.cpp Wed Apr 02 08:50:18 2014 +0100 +++ b/widgets/CommandHistory.cpp Wed Apr 02 08:51:33 2014 +0100 @@ -37,7 +37,7 @@ #include -//#define DEBUG_COMMAND_HISTORY 1 +#define DEBUG_COMMAND_HISTORY 1 CommandHistory *CommandHistory::m_instance = 0; @@ -101,7 +101,7 @@ CommandHistory::clear() { #ifdef DEBUG_COMMAND_HISTORY - SVDEBUG << "CommandHistory::clear()" << endl; + cerr << "CommandHistory::clear()" << endl; #endif closeBundle(); m_savedAt = -1; @@ -143,7 +143,7 @@ if (!command) return; #ifdef DEBUG_COMMAND_HISTORY - SVDEBUG << "CommandHistory::addCommand: " << command->getName() << " of type " << typeid(*command).name() << " at " << command << ": execute = " << execute << ", bundle = " << bundle << " (m_currentCompound = " << m_currentCompound << ", m_currentBundle = " << m_currentBundle << ")" << endl; + cerr << "CommandHistory::addCommand: " << command->getName() << " of type " << typeid(*command).name() << " at " << command << ": execute = " << execute << ", bundle = " << bundle << " (m_currentCompound = " << m_currentCompound << ", m_currentBundle = " << m_currentBundle << ")" << endl; #endif if (m_currentCompound) { @@ -160,7 +160,7 @@ #ifdef DEBUG_COMMAND_HISTORY if (!m_redoStack.empty()) { - SVDEBUG << "CommandHistory::clearing redo stack" << endl; + cerr << "CommandHistory::clearing redo stack" << endl; } #endif @@ -192,8 +192,8 @@ if (m_currentBundle) { if (!command || (command->getName() != m_currentBundleName)) { #ifdef DEBUG_COMMAND_HISTORY - SVDEBUG << "CommandHistory::addToBundle: " - << command->getName() << ": closing current bundle" << endl; + cerr << "CommandHistory::addToBundle: " << command->getName() + << ": closing current bundle" << endl; #endif closeBundle(); } @@ -204,8 +204,8 @@ if (!m_currentBundle) { #ifdef DEBUG_COMMAND_HISTORY - SVDEBUG << "CommandHistory::addToBundle: " - << command->getName() << ": creating new bundle" << endl; + cerr << "CommandHistory::addToBundle: " << command->getName() + << ": creating new bundle" << endl; #endif // need to addCommand before setting m_currentBundle, as addCommand @@ -219,8 +219,8 @@ } #ifdef DEBUG_COMMAND_HISTORY - SVDEBUG << "CommandHistory::addToBundle: " - << command->getName() << ": adding to bundle" << endl; + cerr << "CommandHistory::addToBundle: " << command->getName() + << ": adding to bundle" << endl; #endif if (execute) command->execute(); @@ -242,11 +242,12 @@ void CommandHistory::closeBundle() { + if (m_currentBundle) { #ifdef DEBUG_COMMAND_HISTORY - SVDEBUG << "CommandHistory::closeBundle" << endl; + cerr << "CommandHistory::closeBundle" << endl; #endif - - if (m_currentBundle) emit activity(m_currentBundle->getName()); + emit activity(m_currentBundle->getName()); + } m_currentBundle = 0; m_currentBundleName = ""; } @@ -255,7 +256,7 @@ CommandHistory::bundleTimerTimeout() { #ifdef DEBUG_COMMAND_HISTORY - SVDEBUG << "CommandHistory::bundleTimerTimeout: bundle is " << m_currentBundle << endl; + cerr << "CommandHistory::bundleTimerTimeout: bundle is " << m_currentBundle << endl; #endif closeBundle(); @@ -264,14 +265,15 @@ void CommandHistory::addToCompound(Command *command, bool execute) { -#ifdef DEBUG_COMMAND_HISTORY - SVDEBUG << "CommandHistory::addToCompound: " << command->getName() << endl; -#endif if (!m_currentCompound) { - SVDEBUG << "CommandHistory::addToCompound: ERROR: no compound operation in progress!" << endl; + cerr << "CommandHistory::addToCompound: ERROR: no compound operation in progress!" << endl; return; } +#ifdef DEBUG_COMMAND_HISTORY + cerr << "CommandHistory::addToCompound[" << m_currentCompound->getName() << "]: " << command->getName() << " (exec: " << execute << ")" << endl; +#endif + if (execute) command->execute(); m_currentCompound->addCommand(command); } @@ -280,13 +282,17 @@ CommandHistory::startCompoundOperation(QString name, bool execute) { if (m_currentCompound) { - SVDEBUG << "CommandHistory::startCompoundOperation: ERROR: compound operation already in progress!" << endl; + cerr << "CommandHistory::startCompoundOperation: ERROR: compound operation already in progress!" << endl; cerr << "(name is " << m_currentCompound->getName() << ")" << endl; return; } +#ifdef DEBUG_COMMAND_HISTORY + cerr << "CommandHistory::startCompoundOperation: " << name << " (exec: " << execute << ")" << endl; +#endif + closeBundle(); - + m_currentCompound = new MacroCommand(name); m_executeCompound = execute; } @@ -295,9 +301,13 @@ CommandHistory::endCompoundOperation() { if (!m_currentCompound) { - SVDEBUG << "CommandHistory::endCompoundOperation: ERROR: no compound operation in progress!" << endl; + cerr << "CommandHistory::endCompoundOperation: ERROR: no compound operation in progress!" << endl; return; } + +#ifdef DEBUG_COMMAND_HISTORY + cerr << "CommandHistory::endCompoundOperation: " << m_currentCompound->getName() << endl; +#endif MacroCommand *toAdd = m_currentCompound; m_currentCompound = 0; @@ -329,7 +339,7 @@ if (m_undoStack.empty()) return; #ifdef DEBUG_COMMAND_HISTORY - SVDEBUG << "CommandHistory::undo()" << endl; + cerr << "CommandHistory::undo()" << endl; #endif closeBundle(); @@ -355,7 +365,7 @@ if (m_redoStack.empty()) return; #ifdef DEBUG_COMMAND_HISTORY - SVDEBUG << "CommandHistory::redo()" << endl; + cerr << "CommandHistory::redo()" << endl; #endif closeBundle(); @@ -436,7 +446,7 @@ for (i = 0; i < limit; ++i) { #ifdef DEBUG_COMMAND_HISTORY Command *command = stack.top(); - SVDEBUG << "CommandHistory::clipStack: Saving recent command: " << command->getName() << " at " << command << endl; + cerr << "CommandHistory::clipStack: Saving recent command: " << command->getName() << " at " << command << endl; #endif tempStack.push(stack.top()); stack.pop(); @@ -458,7 +468,7 @@ Command *command = stack.top(); // Not safe to call getName() on a command about to be deleted #ifdef DEBUG_COMMAND_HISTORY - SVDEBUG << "CommandHistory::clearStack: About to delete command " << command << endl; + cerr << "CommandHistory::clearStack: About to delete command " << command << endl; #endif delete command; stack.pop(); diff -r ad01e7d4a956 -r 9cfcb2924ee3 widgets/KeyReference.cpp --- a/widgets/KeyReference.cpp Wed Apr 02 08:50:18 2014 +0100 +++ b/widgets/KeyReference.cpp Wed Apr 02 08:51:33 2014 +0100 @@ -172,7 +172,8 @@ m_text->setReadOnly(true); m_dialog = new QDialog; - m_dialog->setWindowTitle(tr("Sonic Visualiser: Key and Mouse Reference")); + m_dialog->setWindowTitle(tr("%1: Key and Mouse Reference") + .arg(QApplication::applicationName())); QVBoxLayout *layout = new QVBoxLayout; m_dialog->setLayout(layout);