From fb0fbe8f65cca18487567fd1e2db63c99c024bd8 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Tue, 13 Sep 2011 13:35:43 +0000 Subject: when splitting or pasting into new parts, the new newly created parts are automatically added to all editors which also display the "origin" parts --- muse2/muse/functions.cpp | 7 +- muse2/muse/midiedit/scoreedit.cpp | 166 +++++++++++++++++++++----------------- muse2/muse/midiedit/scoreedit.h | 2 + muse2/muse/midieditor.cpp | 28 ++++++- muse2/muse/midieditor.h | 9 ++- muse2/muse/part.cpp | 7 +- muse2/muse/song.cpp | 23 ++++++ muse2/muse/song.h | 6 ++ muse2/muse/structure.cpp | 2 + 9 files changed, 171 insertions(+), 79 deletions(-) (limited to 'muse2') diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp index a8b7ea1d..d6cfa7d0 100644 --- a/muse2/muse/functions.cpp +++ b/muse2/muse/functions.cpp @@ -1000,6 +1000,7 @@ void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part { Undo operations; map expand_map; + map > new_part_map; Xml xml(pt.toLatin1().constData()); for (;;) @@ -1041,11 +1042,13 @@ void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part ( ( (dest_part->endTick() + max_distance < first_paste_tick) || // dest_part is too far away always_new_part ) && !never_new_part ) ) { + Part* old_dest_part=dest_part; dest_part = dest_track->newPart(); dest_part->events()->incARef(-1); // the later song->applyOperationGroup() will increment it // so we must decrement it first :/ - dest_part->setTick(AL::sigmap.raster1(first_paste_tick, config.division)); + + new_part_map[old_dest_part].insert(dest_part); operations.push_back(UndoOp(UndoOp::AddPart, dest_part)); } @@ -1104,6 +1107,8 @@ void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part if (it->second != it->first->lenTick()) schedule_resize_all_same_len_clone_parts(it->first, it->second, operations); + song->informAboutNewParts(new_part_map); // must be called before apply. otherwise + // pointer changes (by resize) screw it up song->applyOperationGroup(operations); song->update(SC_SELECTION); } diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index e4a3994a..d49658ae 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -75,6 +75,9 @@ using namespace std; //#include "../ctrl/ctrledit.h" +using MusEGlobal::debugMsg; +using MusEGlobal::heavyDebugMsg; + string IntToStr(int i); QString IntToQStr(int i); @@ -480,6 +483,7 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos) selection_changed(); connect(song, SIGNAL(songChanged(int)), SLOT(song_changed(int))); + connect(song, SIGNAL(newPartsCreated(const std::map< Part*, std::set >&)), score_canvas, SLOT(add_new_parts(const std::map< Part*, std::set >&))); score_canvas->fully_recalculate(); score_canvas->goto_tick(initPos,true); @@ -762,11 +766,11 @@ Part* read_part(Xml& xml, QString tag_name="part") else { sscanf(tag.toLatin1().constData(), "%d:%d", &trackIdx, &partIdx); - if (MusEGlobal::debugMsg) cout << "read_part: trackIdx="<tick(), parent->quant_ticks()); if (end==begin) { - if (MusEGlobal::heavyDebugMsg) cout << "note len would be quantized to zero. using minimal possible length" << endl; + if (heavyDebugMsg) cout << "note len would be quantized to zero. using minimal possible length" << endl; end=begin+parent->quant_ticks(); } - if (MusEGlobal::heavyDebugMsg) cout << "inserting note on at "<second->sig.z<<"/"<second->sig.n<<"; ticks per measure = "<second->sig.z<<"/"<second->sig.n<<"; ticks per measure = "<(from, FloEvent(from, FloEvent::TIME_SIG, it->second->sig.z, it->second->sig.n) ) ); for (unsigned t=from; t(t, FloEvent(t,0,0,ticks_per_measure,FloEvent::BAR) ) ); @@ -1899,7 +1903,7 @@ int calc_measure_len(const list& nums, int denom) vector create_emphasize_list(const list& nums, int denom) { - if (MusEGlobal::heavyDebugMsg) + if (heavyDebugMsg) { cout << "creating emphasize list for "; for (list::const_iterator it=nums.begin(); it!=nums.end(); it++) @@ -1927,7 +1931,7 @@ vector create_emphasize_list(const list& nums, int denom) result[0]=0; - if (MusEGlobal::heavyDebugMsg) + if (heavyDebugMsg) { for (int i=0;i parse_note_len(int len_ticks, int begin_tick, vector& foo, len_now=len_now*TICKS_PER_WHOLE/64; - if (MusEGlobal::heavyDebugMsg) cout << "add " << len_now << " ticks" << endl; + if (heavyDebugMsg) cout << "add " << len_now << " ticks" << endl; if (allow_dots) { for (int i=0;i<=MAX_QUANT_POWER;i++) @@ -2152,7 +2156,7 @@ void staff_t::create_itemlist() note_pos_t notepos=note_pos(pitch,tmp_key,clef); - if (MusEGlobal::heavyDebugMsg) + if (heavyDebugMsg) { printf("FLO: t=%i\ttype=%i\tpitch=%i\tvel=%i\tlen=%i\n",it->first, it->second.type, it->second.pitch, it->second.vel, it->second.len); cout << "\tline="<quant_ticks())/2; - if (MusEGlobal::heavyDebugMsg) cout << "\tend-of-measure: this was an empty measure. inserting rest in between at t="< lens=parse_note_len(rest,lastevent-last_measure,emphasize_list,DOTTED_RESTS,UNSPLIT_RESTS); unsigned tmppos=lastevent; for (list::iterator x=lens.begin(); x!=lens.end(); x++) { - if (MusEGlobal::heavyDebugMsg) cout << "\t\tpartial rest with len="<len<<", dots="<dots<::iterator x=lens.begin(); x!=lens.end(); x++) { - if (MusEGlobal::heavyDebugMsg) cout << "\t\tpartial rest with len="<len<<", dots="<dots<(next_measure, FloEvent(actual_tick,pitch, velo,0,FloEvent::NOTE_OFF, it->second.source_part, it->second.source_event))); eventlist.insert(pair(next_measure, FloEvent(actual_tick,pitch, velo,newlen,FloEvent::NOTE_ON, it->second.source_part, it->second.source_event))); - if (MusEGlobal::heavyDebugMsg) cout << "\t\tnote was split to length "<(t+len, FloEvent(t+len,pitch, velo,0,FloEvent::NOTE_OFF,it->second.source_part, it->second.source_event))); } @@ -2252,7 +2256,7 @@ void staff_t::create_itemlist() int count=0; for (list::iterator x=lens.begin(); x!=lens.end(); x++) { - if (MusEGlobal::heavyDebugMsg) cout << "\t\tpartial note with len="<len<<", dots="<dots<second.num<<"/"<second.denom<<" at "<second.num<<"/"<second.denom<<" at "<second.num, it->second.denom) ); emphasize_list=create_emphasize_list(it->second.num, it->second.denom); } else if (type==FloEvent::KEY_CHANGE) { - if (MusEGlobal::heavyDebugMsg) cout << "inserting KEY CHANGE ("<second.key<<") at "<second.key<<") at "<second.key) ); tmp_key=it->second.key; } @@ -2298,7 +2302,7 @@ void staff_t::process_itemlist() { set& curr_items=it2->second; - if (MusEGlobal::heavyDebugMsg) cout << "at t="<first<::iterator i=occupied.begin(); i!=occupied.end(); i++) @@ -2341,7 +2345,7 @@ void staff_t::process_itemlist() //(can be seen on already_grouped) if ((it->type==FloItem::REST) && (it->already_grouped==false)) { - if (MusEGlobal::heavyDebugMsg) cout << "trying to group" << endl; + if (heavyDebugMsg) cout << "trying to group" << endl; int lastheight; int height_cumulative=0; @@ -2352,12 +2356,12 @@ void staff_t::process_itemlist() set::iterator tmp; for (tmp=it; tmp!=curr_items.end();) { - if (MusEGlobal::heavyDebugMsg) cout << "checking if we can proceed with an item at height="<pos.height<::iterator it=lengths.begin(); it!=lengths.end(); it++) @@ -2522,14 +2526,14 @@ group_them_again: if (lengths.size()==0) { - if (MusEGlobal::heavyDebugMsg) cout << "no notes other than wholes, or no notes at all. we can relax" << endl; + if (heavyDebugMsg) cout << "no notes other than wholes, or no notes at all. we can relax" << endl; } else if (lengths.size()==1) { pair& group=*(lengths.begin()); stem_t stem; int shift=0; - if (MusEGlobal::heavyDebugMsg) cout << "only one non-whole note group (len="<::iterator it=curr_items.begin(); it!=curr_items.end();) if (it->type==FloItem::NOTE) { //if *it belongs to group1 and has not already its destination length - if (MusEGlobal::heavyDebugMsg) cout << "\tprocessing note-item with len="<len<::iterator x=lens.begin(); x!=lens.end(); x++) { - if (MusEGlobal::heavyDebugMsg) cout << "\t\twhile regrouping: partial note with len="<len<<", dots="<dots<::iterator x=lens.begin(); x!=lens.end(); x++) { - if (MusEGlobal::heavyDebugMsg) cout << "\t\twhile regrouping: partial note with len="<len<<", dots="<dots<pos.height<<" with acc.="<pos.vorzeichen<<", len="<len); for (int i=0;idots;i++) cout << "."; @@ -3092,7 +3096,7 @@ void ScoreCanvas::draw_items(QPainter& p, int y_offset, staff_t& staff, ScoreIte //if needed, draw tie if (it->is_tie_dest) { - if (MusEGlobal::heavyDebugMsg) cout << "drawing tie" << endl; + if (heavyDebugMsg) cout << "drawing tie" << endl; draw_tie(p,it->tie_from_x-x_pos+x_left,it->x -x_pos+x_left,y_offset + it->y, (it->len==0) ? true : (it->stem==DOWNWARDS) , mycolors[color_index]); // in english: "if it's a whole note, tie is upwards (true). if not, tie is upwards if // stem is downwards and vice versa" @@ -3100,7 +3104,7 @@ void ScoreCanvas::draw_items(QPainter& p, int y_offset, staff_t& staff, ScoreIte } else if (it->type==FloItem::REST) { - if (MusEGlobal::heavyDebugMsg) + if (heavyDebugMsg) { cout << "\tREST at line"<pos.height<<" with len="<len); for (int i=0;idots;i++) cout << "."; @@ -3130,7 +3134,7 @@ void ScoreCanvas::draw_items(QPainter& p, int y_offset, staff_t& staff, ScoreIte } else if (it->type==FloItem::BAR) { - if (MusEGlobal::heavyDebugMsg) cout << "\tBAR" << endl; + if (heavyDebugMsg) cout << "\tBAR" << endl; p.setPen(Qt::black); p.drawLine(it->x -x_pos+x_left,y_offset -2*YLEN,it->x -x_pos+x_left,y_offset +2*YLEN); @@ -3140,14 +3144,14 @@ void ScoreCanvas::draw_items(QPainter& p, int y_offset, staff_t& staff, ScoreIte } else if (it->type==FloItem::TIME_SIG) { - if (MusEGlobal::heavyDebugMsg) cout << "\tTIME SIGNATURE: "<num<<"/"<denom<num<<"/"<denom<x - x_pos+x_left, y_offset, it->num, it->denom); } else if (it->type==FloItem::KEY_CHANGE) { key_enum new_key=it->key; - if (MusEGlobal::heavyDebugMsg) cout << "\tKEY CHANGE: from "< aufloes_list=calc_accidentials(curr_key, staff.clef, new_key); list new_acc_list=calc_accidentials(new_key, staff.clef); @@ -3358,7 +3362,7 @@ void ScoreCanvas::draw_number(QPainter& p, int x, int y, int n) void ScoreCanvas::draw(QPainter& p, const QRect&) { - if (MusEGlobal::debugMsg) cout <<"now in ScoreCanvas::draw"<itemlist; - if (MusEGlobal::debugMsg) cout << "mousePressEvent at "<begin_tick<<" and end at "<source_part << endl; @@ -3688,13 +3692,13 @@ void ScoreCanvas::mousePressEvent (QMouseEvent* event) if (flo_quantize(newevent.lenTick(), quant_ticks()) <= 0) { newevent.setLenTick(quant_ticks()); - if (MusEGlobal::debugMsg) cout << "inserted note's length would be invisible after quantisation (too short)." << endl << + if (debugMsg) cout << "inserted note's length would be invisible after quantisation (too short)." << endl << " setting it to " << newevent.lenTick() << endl; } if (newevent.endTick() > curr_part->lenTick()) { - if (MusEGlobal::debugMsg) cout << "clipping inserted note from len="<undo(); audio->msgDeleteEvent(dragged_event, dragged_event_part, true, false, false); } @@ -3843,13 +3847,13 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) { if ((abs(dx)>DRAG_INIT_DISTANCE) && (mouse_x_drag_operation!=NO_OP)) { - if (MusEGlobal::debugMsg) cout << "mouse-operation is now "<DRAG_INIT_DISTANCE) { - if (MusEGlobal::debugMsg) cout << "mouse-operation is now PITCH" << endl; + if (debugMsg) cout << "mouse-operation is now PITCH" << endl; mouse_operation=PITCH; setCursor(Qt::SizeVerCursor); } @@ -3880,7 +3884,7 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) break; case PITCH: - if (MusEGlobal::heavyDebugMsg) cout << "trying to change pitch, delta="<<-nearbyint((float)dy/PITCH_DELTA)<lenTick(); @@ -3941,12 +3945,12 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event) if (dragged_event_part->hasHiddenEvents()) // do not allow autoexpand { tmp.setLenTick(dragged_event_part->lenTick() - tmp.tick()); - if (MusEGlobal::debugMsg) cout << "resized note would exceed its part; limiting length to " << tmp.lenTick() << endl; + if (debugMsg) cout << "resized note would exceed its part; limiting length to " << tmp.lenTick() << endl; } else { newpartlen=tmp.endTick(); - if (MusEGlobal::debugMsg) cout << "resized note would exceeds its part; expanding the part..." << endl; + if (debugMsg) cout << "resized note would exceeds its part; expanding the part..." << endl; } } @@ -4053,14 +4057,14 @@ void ScoreCanvas::heartbeat_timer_event() void ScoreCanvas::x_scroll_event(int x) { - if (MusEGlobal::debugMsg) cout << "SCROLL EVENT: x="< >& param) +{ + for (list::iterator staff=staves.begin(); staff!=staves.end(); staff++) + { + for (std::map< Part*, set >::const_iterator it = param.begin(); it!=param.end(); it++) + if (staff->parts.find(it->first)!=staff->parts.end()) + staff->parts.insert(it->second.begin(), it->second.end()); + + //staff->cleanup_parts(); // don't cleanup here, because at this point, the parts may only exist + // in the operation group. cleanup could remove them immediately + staff->update_part_indices(); + } + + fully_recalculate(); +} + //the following assertions are made: // pix_quarter.width() == pix_half.width() @@ -4513,12 +4533,12 @@ void ScoreEdit::keyPressEvent(QKeyEvent* event) * CURRENT TODO * o pasting in editors sometimes fails oO? ( ERROR: reading eventlist from clipboard failed. ignoring this one... ) * o ctrl+shift+c for editors - * o when pasting and creating new parts, inform the editors about that! * o TEST pasting in editors! * o sane default for raster * o use raster and amount in paste_notes! * x clone-bug * x pasting in editors: add dialogs + * x when pasting and creating new parts, inform the editors about that! * * o ticks-to-quarter spinboxes * diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h index b436f85a..9227389f 100644 --- a/muse2/muse/midiedit/scoreedit.h +++ b/muse2/muse/midiedit/scoreedit.h @@ -762,6 +762,8 @@ class ScoreCanvas : public MusEWidget::View void deselect_all(); void midi_note(int pitch, int velo); + + void add_new_parts(const std::map< Part*, std::set >&); public slots: void x_scroll_event(int); diff --git a/muse2/muse/midieditor.cpp b/muse2/muse/midieditor.cpp index 218c0615..d4a16eda 100644 --- a/muse2/muse/midieditor.cpp +++ b/muse2/muse/midieditor.cpp @@ -45,7 +45,7 @@ MidiEditor::MidiEditor(ToplevelType t, int r, PartList* pl, _pl = pl; if (_pl) for (iPart i = _pl->begin(); i != _pl->end(); ++i) - _parts.push_back(i->second->sn()); + _parts.insert(i->second->sn()); _raster = r; canvas = 0; wview = 0; @@ -59,6 +59,8 @@ MidiEditor::MidiEditor(ToplevelType t, int r, PartList* pl, mainGrid->setContentsMargins(0, 0, 0, 0); mainGrid->setSpacing(0); setCentralWidget(mainw); + + connect(song, SIGNAL(newPartsCreated(const std::map< Part*, std::set >&)), SLOT(addNewParts(const std::map< Part*, std::set >&))); } //--------------------------------------------------------- @@ -68,7 +70,7 @@ MidiEditor::MidiEditor(ToplevelType t, int r, PartList* pl, void MidiEditor::genPartlist() { _pl->clear(); - for (std::list::iterator i = _parts.begin(); i != _parts.end(); ++i) { + for (std::set::iterator i = _parts.begin(); i != _parts.end(); ++i) { TrackList* tl = song->tracks(); for (iTrack it = tl->begin(); it != tl->end(); ++it) { PartList* pl = (*it)->parts(); @@ -85,6 +87,17 @@ void MidiEditor::genPartlist() } } +//--------------------------------------------------------- +// addPart +//--------------------------------------------------------- + +void MidiEditor::addPart(Part* p) +{ + _pl->add(p); + _parts.insert(p->sn()); +} + + //--------------------------------------------------------- // MidiEditor //--------------------------------------------------------- @@ -266,3 +279,14 @@ void MidiEditor::horizontalZoomOut() hscroll->setMag(newmag); } + +void MidiEditor::addNewParts(const std::map< Part*, std::set >& param) +{ + using std::map; + using std::set; + + for (map< Part*, set >::const_iterator it = param.begin(); it!=param.end(); it++) + if (_pl->index(it->first) != -1) + for (set::const_iterator it2=it->second.begin(); it2!=it->second.end(); it2++) + addPart(*it2); +} diff --git a/muse2/muse/midieditor.h b/muse2/muse/midieditor.h index af681075..84597cd3 100644 --- a/muse2/muse/midieditor.h +++ b/muse2/muse/midieditor.h @@ -27,6 +27,9 @@ #include "al/sig.h" #include "cobject.h" + +#include + class QGridLayout; class QWidget; @@ -51,7 +54,7 @@ class MidiEditor : public TopWin { Q_OBJECT PartList* _pl; - std::list _parts; + std::set _parts; int _curDrumInstrument; // currently selected instrument if drum // editor protected: @@ -70,6 +73,9 @@ class MidiEditor : public TopWin { void writePartList(int, Xml&) const; void genPartlist(); + private slots: + void addNewParts(const std::map< Part*, std::set >&); + public slots: void songChanged(int type); void setCurDrumInstrument(int instr); @@ -100,6 +106,7 @@ class MidiEditor : public TopWin { Part* curCanvasPart(); WavePart* curWavePart(); void setCurCanvasPart(Part*); + void addPart(Part*); }; #endif diff --git a/muse2/muse/part.cpp b/muse2/muse/part.cpp index 51478928..6d273c82 100644 --- a/muse2/muse/part.cpp +++ b/muse2/muse/part.cpp @@ -648,8 +648,8 @@ int PartList::index(Part* part) } if(MusEGlobal::debugMsg) printf("PartList::index(): not found!\n"); - //return 0; - return -1; + //return 0; // don't comment this in again + return -1; // don't change that value. at least MidiEditor::addNewParts relies on this } //--------------------------------------------------------- @@ -1044,6 +1044,9 @@ void Song::cmdSplitPart(Track* track, Part* part, int tick) Part* p1; Part* p2; track->splitPart(part, tick, p1, p2); + + //song->informAboutNewParts(part, p1); // is unneccessary because of ChangePart below + song->informAboutNewParts(part, p2); startUndo(); // Indicate no undo, and do port controller values but not clone parts. diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp index e5381884..af5b0489 100644 --- a/muse2/muse/song.cpp +++ b/muse2/muse/song.cpp @@ -3927,3 +3927,26 @@ QString Song::getScriptPath(int id, bool isdelivered) return path; } +void Song::informAboutNewParts(const std::map< Part*, std::set >& param) +{ + emit newPartsCreated(param); +} + +void Song::informAboutNewParts(Part* orig, Part* p1, Part* p2, Part* p3, Part* p4, Part* p5, Part* p6, Part* p7, Part* p8, Part* p9) +{ + std::map< Part*, std::set > temp; + + temp[orig].insert(p1); + temp[orig].insert(p2); + temp[orig].insert(p3); + temp[orig].insert(p4); + temp[orig].insert(p5); + temp[orig].insert(p6); + temp[orig].insert(p7); + temp[orig].insert(p8); + temp[orig].insert(p9); + temp[orig].erase(static_cast(NULL)); + temp[orig].erase(orig); + + informAboutNewParts(temp); +} diff --git a/muse2/muse/song.h b/muse2/muse/song.h index 872993e5..09174f71 100644 --- a/muse2/muse/song.h +++ b/muse2/muse/song.h @@ -27,6 +27,9 @@ #include #include +#include +#include + #include "pos.h" #include "globaldefs.h" #include "tempo.h" @@ -163,6 +166,8 @@ class Song : public QObject { ~Song(); bool applyOperationGroup(Undo& group, bool doUndo=true); + void informAboutNewParts(const std::map< Part*, std::set >&); + void informAboutNewParts(Part* orig, Part* p1, Part* p2=NULL, Part* p3=NULL, Part* p4=NULL, Part* p5=NULL, Part* p6=NULL, Part* p7=NULL, Part* p8=NULL, Part* p9=NULL); void putEvent(int pv); void endMsgCmd(); @@ -421,6 +426,7 @@ class Song : public QObject { void midiPortsChanged(); void midiNote(int pitch, int velo); void controllerChanged(Track* t); + void newPartsCreated(const std::map< Part*, std::set >&); }; extern Song* song; diff --git a/muse2/muse/structure.cpp b/muse2/muse/structure.cpp index 9665ce5e..6c9d25dd 100644 --- a/muse2/muse/structure.cpp +++ b/muse2/muse/structure.cpp @@ -347,6 +347,8 @@ void globalSplit() p1->events()->incARef(-1); // the later song->applyOperationGroup() will increment it p2->events()->incARef(-1); // so we must decrement it first :/ + //song->informAboutNewParts(part, p1); // is unneccessary because of ModifyPart + song->informAboutNewParts(part, p2); operations.push_back(UndoOp(UndoOp::ModifyPart,part, p1, true, false)); operations.push_back(UndoOp(UndoOp::AddPart,p2)); break; -- cgit v1.2.3