diff options
author | Florian Jung <flo@windfisch.org> | 2011-04-12 13:24:35 +0000 |
---|---|---|
committer | Florian Jung <flo@windfisch.org> | 2011-04-12 13:24:35 +0000 |
commit | 533f81167c006932a3bd7d95c62abbbd59157228 (patch) | |
tree | 02a6e6697b831402699611147c7f526ae7f29efc /muse2 | |
parent | 384e0d2f6d77ab107268921511dd91464d4accb3 (diff) |
first approach of displaying multiple staves in one score window
this revision is fully functional (or at least should be), but
maybe new bugs were introduced.
TODO: some things in the source are done pretty ugly, need to beautify that
and some features (e.g. grand staves) still need to be done
Diffstat (limited to 'muse2')
-rw-r--r-- | muse2/muse/midiedit/scoreedit.cpp | 379 | ||||
-rw-r--r-- | muse2/muse/midiedit/scoreedit.h | 32 |
2 files changed, 240 insertions, 171 deletions
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index 72b0c4de..c7e68f0b 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -68,6 +68,21 @@ using namespace std; +//TODO: all das unten richtig machen! +#define TICKS_PER_WHOLE (config.division*4) +#define SONG_LENGTH (song->len()) + +#define quant_max 3 //whole, half, quarter = 0,1,2 +#define quant_max_fraction (1 << quant_max) //whole, half, quarter= 1,2,4 +#define FLO_QUANT (TICKS_PER_WHOLE/quant_max_fraction) +//FLO_QUANT = how many ticks has a single quantisation area? + + +//FINDMICH MARKER +//TODO: quant_max richtig setzen! + + + //do NOT put parentheses around this! #define PAGESTEP 3/4 @@ -78,6 +93,10 @@ using namespace std; #define SCROLL_SPEED_MAX 500 //SCROLL_SPEED_MAX is in scroll_pixels_per_second + + +#define STAFF_DISTANCE 100 + //--------------------------------------------------------- // ScoreEdit //--------------------------------------------------------- @@ -93,18 +112,13 @@ connect(hscroll, SIGNAL(valueChanged(int)), test, SLOT(scroll_event(int))); connect(test, SIGNAL(xpos_changed(int)), hscroll, SLOT(setValue(int)));connect(song, SIGNAL(songChanged(int)), test, SLOT(song_changed(int))); connect(test, SIGNAL(canvas_width_changed(int)), SLOT(canvas_width_changed(int))); connect(test, SIGNAL(viewport_width_changed(int)), SLOT(viewport_width_changed(int))); -// mainGrid->setRowStretch(0, 100); -// mainGrid->setColumnStretch(1, 100); + mainGrid->addWidget(test, 0, 0); mainGrid->addWidget(hscroll,1,0); hscroll->setMinimum(0); test->song_changed(0); test->goto_tick(initPos,true); -// gridS1->addWidget(test,0,0); - -// gridS1->addWidget(canvas, 0, 0); - // hsplitter->addWidget(test); } @@ -172,8 +186,26 @@ ScoreCanvas::ScoreCanvas(MidiEditor* pr, QWidget* parent, last_len=384; new_len=-1; -//fertig mit aufbereiten - cout << "---------------- CALCULATING DONE ------------------" << endl; + + + //each track gets its own staff + staff_t staff; + set<Track*> tracks; + + for (ciPart it=editor->parts()->begin(); it!=editor->parts()->end(); it++) + tracks.insert(it->second->track()); + + for (set<Track*>::iterator it=tracks.begin(); it!=tracks.end(); it++) + { + staff.parts.clear(); + for (ciPart part_it=editor->parts()->begin(); part_it!=editor->parts()->end(); part_it++) + if (part_it->second->track() == *it) + staff.parts.insert(part_it->second); + + staffs.push_back(staff); + } + + scroll_speed=0; @@ -186,11 +218,15 @@ ScoreCanvas::ScoreCanvas(MidiEditor* pr, QWidget* parent, void ScoreCanvas::song_changed(int) { cout << "song changed!" << endl; - pos_add_list.clear(); - eventlist=create_appropriate_eventlist(editor->parts()); - itemlist=create_itemlist(eventlist); - process_itemlist(itemlist); // do note- and rest-grouping and collision avoiding - calc_item_pos(itemlist); + for (list<staff_t>::iterator it=staffs.begin(); it!=staffs.end(); it++) + { + pos_add_list.clear(); //FINDMICHJETZT schöner machen + it->eventlist=create_appropriate_eventlist(it->parts); + it->itemlist=create_itemlist(it->eventlist); + process_itemlist(it->itemlist); // do note- and rest-grouping and collision avoiding + calc_item_pos(it->itemlist); + } + redraw(); cout << "song had changed, recalculation complete" << endl; @@ -199,7 +235,8 @@ void ScoreCanvas::song_changed(int) int ScoreCanvas::canvas_width() { - return tick_to_x(itemlist.rbegin()->first); + //return tick_to_x(staffs.begin()->itemlist.rbegin()->first); + return tick_to_x(SONG_LENGTH); } int ScoreCanvas::viewport_width() @@ -336,31 +373,6 @@ bool operator< (const note_pos_t& a, const note_pos_t& b) } -//TODO: all das unten richtig machen! -#define TICKS_PER_WHOLE (config.division*4) -#define SONG_LENGTH (song->len()) - -#define quant_max 3 //whole, half, quarter = 0,1,2 -#define quant_max_fraction (1 << quant_max) //whole, half, quarter= 1,2,4 -#define FLO_QUANT (TICKS_PER_WHOLE/quant_max_fraction) -//FLO_QUANT = how many ticks has a single quantisation area? - - -//FINDMICH MARKER -//TODO: quant_max richtig setzen! - -/* builds the event list used by the score editor. - * that list contains only note-on and -off, time-sig- and - * key-change events. - * it stores them sorted by their time (quantized); if more - * events with the same time occur, the NOTE-OFFs are - * put before the NOTE-ONs - * it only operates on parts which were selected in the - * arranger when the score viewer was started - * - * this abstracts the rest of the renderer from muse's internal - * data structures, making this easy to port to another application - */ int flo_quantize(int tick) { @@ -373,8 +385,21 @@ int flo_quantize_floor(int tick) //TODO quantizing must be done with the proper functions, see above return int(tick / FLO_QUANT) * FLO_QUANT; } + -ScoreEventList ScoreCanvas::create_appropriate_eventlist(PartList* pl) +/* builds the event list used by the score editor. + * that list contains only note-on and -off, time-sig- and + * key-change events. + * it stores them sorted by their time (quantized); if more + * events with the same time occur, the NOTE-OFFs are + * put before the NOTE-ONs + * it only operates on parts which were selected in the + * arranger when the score viewer was started + * + * this abstracts the rest of the renderer from muse's internal + * data structures, making this easy to port to another application + */ +ScoreEventList ScoreCanvas::create_appropriate_eventlist(const set<Part*>& parts) { using AL::sigmap; using AL::iSigEvent; @@ -384,9 +409,9 @@ ScoreEventList ScoreCanvas::create_appropriate_eventlist(PartList* pl) // phase one: fill the list ----------------------------------------- //insert note on events - for (iPart partIt=pl->begin(); partIt!=pl->end(); partIt++) + for (set<Part*>::const_iterator part_it=parts.begin(); part_it!=parts.end(); part_it++) { - Part* part=partIt->second; + Part* part=*part_it; EventList* el=part->events(); for (iEvent it=el->begin(); it!=el->end(); it++) @@ -845,14 +870,14 @@ void ScoreCanvas::draw_tie (QPainter& p, int x1, int x4, int yo, bool up, QColor p.drawPath(path); } -void ScoreCanvas::draw_accidentials(QPainter& p, int x, const list<int>& acc_list, const QPixmap& pix) +void ScoreCanvas::draw_accidentials(QPainter& p, int x, int y_offset, const list<int>& acc_list, const QPixmap& pix) { int n_acc_drawn=0; for (list<int>::const_iterator acc_it=acc_list.begin(); acc_it!=acc_list.end(); acc_it++) { int y_coord=YDIST+4*YLEN - ( *acc_it -2)*YLEN/2; //Y_MARKER - draw_pixmap(p,x + n_acc_drawn*KEYCHANGE_ACC_DIST,y_coord,pix); + draw_pixmap(p,x + n_acc_drawn*KEYCHANGE_ACC_DIST,y_offset + y_coord,pix); n_acc_drawn++; } } @@ -1470,14 +1495,14 @@ QRect FloItem::bbox() const return bbox_center(x,y,pix->size()); } -void ScoreCanvas::draw_note_lines(QPainter& p) +void ScoreCanvas::draw_note_lines(QPainter& p, int y) { int xend=width(); p.setPen(Qt::black); for (int i=0;i<5;i++) - p.drawLine(0,YDIST+i*YLEN,xend,YDIST+i*YLEN); + p.drawLine(0,y + YDIST+i*YLEN,xend,y + YDIST+i*YLEN); } @@ -1576,7 +1601,7 @@ void ScoreCanvas::calc_item_pos(ScoreItemList& itemlist) } } -void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, int x1, int x2) +void ScoreCanvas::draw_items(QPainter& p, int y, ScoreItemList& itemlist, int x1, int x2) { int from_tick, to_tick; ScoreItemList::iterator from_it, to_it; @@ -1605,15 +1630,15 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, int x1, int x //actually drawn. if (to_it!=itemlist.end()) to_it++; //do one tick more than neccessary. this will draw ties - draw_items(p,itemlist,from_it, to_it); + draw_items(p,y, from_it, to_it); } -void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist) +void ScoreCanvas::draw_items(QPainter& p, int y, ScoreItemList& itemlist) { - draw_items(p,itemlist,x_pos,x_pos+width()-x_left); + draw_items(p,y, itemlist,x_pos,x_pos+width()-x_left); } -void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList::iterator from_it, ScoreItemList::iterator to_it) +void ScoreCanvas::draw_items(QPainter& p, int y_offset, ScoreItemList::iterator from_it, ScoreItemList::iterator to_it) { // init accidentials properly vorzeichen_t curr_accidential[7]; @@ -1696,13 +1721,13 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList { //Y_MARKER p.setPen(Qt::black); for (int i=0; i>=it->pos.height; i-=2) - p.drawLine(it->x-it->pix->width()*AUX_LINE_LEN/2 -x_pos+x_left,YDIST+4*YLEN - (i-2)*YLEN/2,it->x+it->pix->width()*AUX_LINE_LEN/2-x_pos+x_left,YDIST+4*YLEN - (i-2)*YLEN/2); + p.drawLine(it->x-it->pix->width()*AUX_LINE_LEN/2 -x_pos+x_left,y_offset + YDIST+4*YLEN - (i-2)*YLEN/2,it->x+it->pix->width()*AUX_LINE_LEN/2-x_pos+x_left,y_offset + YDIST+4*YLEN - (i-2)*YLEN/2); } else if (it->pos.height >= 12) //we need auxiliary lines on the top? { //Y_MARKER p.setPen(Qt::black); for (int i=12; i<=it->pos.height; i+=2) - p.drawLine(it->x-it->pix->width()*AUX_LINE_LEN/2 -x_pos+x_left,YDIST+4*YLEN - (i-2)*YLEN/2,it->x+it->pix->width()*AUX_LINE_LEN/2-x_pos+x_left,YDIST+4*YLEN - (i-2)*YLEN/2); + p.drawLine(it->x-it->pix->width()*AUX_LINE_LEN/2 -x_pos+x_left,y_offset + YDIST+4*YLEN - (i-2)*YLEN/2,it->x+it->pix->width()*AUX_LINE_LEN/2-x_pos+x_left,y_offset + YDIST+4*YLEN - (i-2)*YLEN/2); } it->is_active= ( (song->cpos() >= it->source_event->tick() + it->source_part->tick()) && @@ -1713,7 +1738,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList if (audio->isPlaying() && it->is_active) color_index=HIGHLIGHTED_PIXMAP; - draw_pixmap(p,it->x -x_pos+x_left,it->y,it->pix[color_index]); + draw_pixmap(p,it->x -x_pos+x_left,y_offset + it->y,it->pix[color_index]); //TODO FINDMICH maybe draw a margin around bright colors? //maybe draw the default color in black? @@ -1732,7 +1757,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList for (int i=0;i<it->dots;i++) { - draw_pixmap(p,it->x+x_dot -x_pos+x_left,it->y+y_dot,pix_dot[color_index]); + draw_pixmap(p,it->x+x_dot -x_pos+x_left,y_offset + it->y+y_dot,pix_dot[color_index]); x_dot+=DOT_XDIST; } @@ -1748,7 +1773,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList case SHARP: acc_pix=pix_sharp; break; case B: acc_pix=pix_b; break; } - draw_pixmap(p,it->x-ACCIDENTIAL_DIST -x_pos+x_left,it->y, acc_pix[color_index]); + draw_pixmap(p,it->x-ACCIDENTIAL_DIST -x_pos+x_left,y_offset + it->y, acc_pix[color_index]); curr_accidential[modulo(it->pos.height,7)]=it->pos.vorzeichen; } @@ -1758,7 +1783,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList if (it->is_tie_dest) { cout << "drawing tie" << endl; - draw_tie(p,it->tie_from_x-x_pos+x_left,it->x -x_pos+x_left,it->y, (it->len==0) ? true : (it->stem==DOWNWARDS) , config.partColors[color_index]); + 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) , config.partColors[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" } @@ -1769,7 +1794,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList for (int i=0;i<it->dots;i++) cout << "."; cout << " , ausweich="<<it->ausweich<<endl; - draw_pixmap(p,it->x -x_pos+x_left,it->y,*it->pix); + draw_pixmap(p,it->x -x_pos+x_left,y_offset + it->y,*it->pix); //draw dots @@ -1786,7 +1811,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList for (int i=0;i<it->dots;i++) { - draw_pixmap(p,it->x+x_dot -x_pos+x_left,it->y+y_dot,pix_dot[BLACK_PIXMAP]); + draw_pixmap(p,it->x+x_dot -x_pos+x_left,y_offset + it->y+y_dot,pix_dot[BLACK_PIXMAP]); x_dot+=DOT_XDIST; } } @@ -1795,7 +1820,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList cout << "\tBAR" << endl; p.setPen(Qt::black); //Y_MARKER - p.drawLine(it->x -x_pos+x_left,YDIST,it->x -x_pos+x_left,YDIST+4*YLEN); + p.drawLine(it->x -x_pos+x_left,y_offset + YDIST,it->x -x_pos+x_left,y_offset + YDIST+4*YLEN); for (int i=0;i<7;i++) curr_accidential[i]=default_accidential[i]; @@ -1804,7 +1829,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList { cout << "\tTIME SIGNATURE: "<<it->num<<"/"<<it->denom<<endl; - draw_timesig(p, it->x - x_pos+x_left, it->num, it->denom); + draw_timesig(p, it->x - x_pos+x_left, y_offset, it->num, it->denom); } else if (it->type==FloItem::KEY_CHANGE) { @@ -1815,13 +1840,13 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList list<int> new_acc_list=calc_accidentials(new_key, USED_CLEF); // vorzeichen aus curr_key auflösen - draw_accidentials(p, it->x + KEYCHANGE_ACC_LEFTDIST - x_pos+x_left, aufloes_list, pix_noacc[BLACK_PIXMAP]); + draw_accidentials(p, it->x + KEYCHANGE_ACC_LEFTDIST - x_pos+x_left, y_offset, aufloes_list, pix_noacc[BLACK_PIXMAP]); // alle vorzeichen aus new_key zeichnen QPixmap* pix = is_sharp_key(new_key) ? &pix_sharp[BLACK_PIXMAP] : &pix_b[BLACK_PIXMAP]; vorzeichen_t new_accidential = is_sharp_key(new_key) ? SHARP : B; - draw_accidentials(p, it->x + aufloes_list.size()*KEYCHANGE_ACC_DIST + KEYCHANGE_ACC_LEFTDIST - x_pos+x_left, new_acc_list, *pix); + draw_accidentials(p, it->x + aufloes_list.size()*KEYCHANGE_ACC_DIST + KEYCHANGE_ACC_LEFTDIST - x_pos+x_left, y_offset, new_acc_list, *pix); for (int i=0;i<7;i++) curr_accidential[i]=default_accidential[i]=NONE; @@ -1838,28 +1863,36 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList if (upstem_x!=-1) { upstem_x=upstem_x-pix_quarter[0].width()/2 +pix_quarter[0].width() -1; - p.drawLine(upstem_x -x_pos+x_left, upstem_y1, upstem_x -x_pos+x_left, upstem_y2-STEM_LEN); + p.drawLine(upstem_x -x_pos+x_left, y_offset + upstem_y1, upstem_x -x_pos+x_left, y_offset + upstem_y2-STEM_LEN); if (upflag>=3) //if the note needs a flag - p.drawPixmap(upstem_x -x_pos+x_left,upstem_y2-STEM_LEN,pix_flag_up[upflag-3]); + p.drawPixmap(upstem_x -x_pos+x_left,y_offset + upstem_y2-STEM_LEN,pix_flag_up[upflag-3]); } if (downstem_x!=-1) { downstem_x=downstem_x-pix_quarter[0].width()/2; - p.drawLine(downstem_x -x_pos+x_left, downstem_y1+STEM_LEN, downstem_x -x_pos+x_left, downstem_y2); + p.drawLine(downstem_x -x_pos+x_left, y_offset + downstem_y1+STEM_LEN, downstem_x -x_pos+x_left, y_offset + downstem_y2); if (downflag>=3) //if the note needs a flag - p.drawPixmap(downstem_x -x_pos+x_left,downstem_y1+STEM_LEN-pix_flag_down[downflag-3].height(),pix_flag_down[downflag-3]); + p.drawPixmap(downstem_x -x_pos+x_left,y_offset + downstem_y1+STEM_LEN-pix_flag_down[downflag-3].height(),pix_flag_down[downflag-3]); } } } bool ScoreCanvas::need_redraw_for_hilighting() { - return need_redraw_for_hilighting(x_pos,x_pos+width()-x_left); + for (list<staff_t>::iterator it=staffs.begin(); it!=staffs.end(); it++) + if (need_redraw_for_hilighting(it->itemlist)) return true; + + return false; } -bool ScoreCanvas::need_redraw_for_hilighting(int x1, int x2) +bool ScoreCanvas::need_redraw_for_hilighting(ScoreItemList& itemlist) +{ + return need_redraw_for_hilighting(itemlist, x_pos,x_pos+width()-x_left); +} + +bool ScoreCanvas::need_redraw_for_hilighting(ScoreItemList& itemlist, int x1, int x2) { int from_tick, to_tick; ScoreItemList::iterator from_it, to_it; @@ -1917,8 +1950,7 @@ int ScoreCanvas::clef_height(clef_t clef) #define CLEF_LEFTMARGIN 5 #define CLEF_RIGHTMARGIN 5 - -void ScoreCanvas::draw_preamble(QPainter& p) +void ScoreCanvas::draw_preamble(QPainter& p, int y_offset) { int x_left_old=x_left; int tick=x_to_tick(x_pos); @@ -1927,7 +1959,7 @@ void ScoreCanvas::draw_preamble(QPainter& p) QPixmap* pix_clef= (USED_CLEF==BASS) ? pix_clef_bass : pix_clef_violin; int y_coord=YDIST+4*YLEN - ( clef_height(USED_CLEF) -2)*YLEN/2; //Y_MARKER - draw_pixmap(p,CLEF_LEFTMARGIN + pix_clef->width()/2,y_coord,*pix_clef); + draw_pixmap(p,CLEF_LEFTMARGIN + pix_clef->width()/2,y_offset + y_coord,*pix_clef); x_left= CLEF_LEFTMARGIN + pix_clef->width() + CLEF_RIGHTMARGIN + KEYCHANGE_ACC_LEFTDIST; @@ -1937,7 +1969,7 @@ void ScoreCanvas::draw_preamble(QPainter& p) QPixmap* pix_acc=is_sharp_key(key) ? &pix_sharp[BLACK_PIXMAP] : &pix_b[BLACK_PIXMAP]; list<int> acclist=calc_accidentials(key,USED_CLEF); - draw_accidentials(p,x_left,acclist ,*pix_acc); + draw_accidentials(p,x_left, y_offset, acclist ,*pix_acc); x_left+=acclist.size()*KEYCHANGE_ACC_DIST + KEYCHANGE_ACC_RIGHTDIST + TIMESIG_LEFTMARGIN; @@ -1945,13 +1977,13 @@ void ScoreCanvas::draw_preamble(QPainter& p) // draw time signature ---------------------------------------------- timesig_t timesig=timesig_at_tick(tick); - draw_timesig(p, x_left, timesig.num, timesig.denom); + draw_timesig(p, x_left, y_offset, timesig.num, timesig.denom); x_left+=calc_timesig_width(timesig.num, timesig.denom)+TIMESIG_RIGHTMARGIN; // draw bar --------------------------------------------------------- p.setPen(Qt::black); //Y_MARKER - p.drawLine(x_left,YDIST,x_left,YDIST+4*YLEN); + p.drawLine(x_left,y_offset + YDIST,x_left,y_offset + YDIST+4*YLEN); if (x_left_old!=x_left) @@ -1959,7 +1991,7 @@ void ScoreCanvas::draw_preamble(QPainter& p) } -void ScoreCanvas::draw_timesig(QPainter& p, int x, int num, int denom) +void ScoreCanvas::draw_timesig(QPainter& p, int x, int y_offset, int num, int denom) { int num_width=calc_number_width(num); int denom_width=calc_number_width(denom); @@ -1968,8 +2000,8 @@ void ScoreCanvas::draw_timesig(QPainter& p, int x, int num, int denom) int denom_indent=(width-denom_width)/2 + TIMESIG_LEFTMARGIN; int y=YDIST+2*YLEN; - draw_number(p, x+num_indent, y-DIGIT_YDIST, num); - draw_number(p, x+denom_indent, y+DIGIT_YDIST, denom); + draw_number(p, x+num_indent, y_offset + y-DIGIT_YDIST, num); + draw_number(p, x+denom_indent, y_offset + y+DIGIT_YDIST, denom); } int ScoreCanvas::calc_timesig_width(int num, int denom) @@ -1999,7 +2031,7 @@ void ScoreCanvas::draw_number(QPainter& p, int x, int y, int n) } -void ScoreCanvas::draw(QPainter& p, const QRect& rect) +void ScoreCanvas::draw(QPainter& p, const QRect&) { cout <<"now in ScoreCanvas::draw"<<endl; @@ -2007,11 +2039,17 @@ void ScoreCanvas::draw(QPainter& p, const QRect& rect) p.setPen(Qt::black); - draw_note_lines(p); - draw_preamble(p); - p.setClipRect(x_left+1,0,p.device()->width(),p.device()->height()); - draw_items(p, itemlist); - p.setClipping(false); + int y=0; + for (list<staff_t>::iterator it=staffs.begin(); it!=staffs.end(); it++) + { + draw_note_lines(p,y); + draw_preamble(p,y); + p.setClipRect(x_left+1,0,p.device()->width(),p.device()->height()); + draw_items(p,y, it->itemlist); + p.setClipping(false); + + y+=STAFF_DISTANCE; + } } @@ -2091,24 +2129,24 @@ int ScoreCanvas::x_to_tick(int x) return t > min_t ? t : min_t; } -tonart_t ScoreCanvas::key_at_tick(int t_) +tonart_t ScoreCanvas::key_at_tick(int t_) //FINDMICHJETZT besser lösen! nur übergangslösung! { tonart_t tmp; unsigned int t= (t_>=0) ? t_ : 0; - for (ScoreEventList::iterator it=eventlist.begin(); it!=eventlist.end() && it->first<=t; it++) + for (ScoreEventList::iterator it=staffs.begin()->eventlist.begin(); it!=staffs.begin()->eventlist.end() && it->first<=t; it++) if (it->second.type==FloEvent::KEY_CHANGE) tmp=it->second.tonart; return tmp; } -timesig_t ScoreCanvas::timesig_at_tick(int t_) +timesig_t ScoreCanvas::timesig_at_tick(int t_) //FINDMICHJETZT besser lösen! nur übergangslösung! { timesig_t tmp; unsigned int t= (t_>=0) ? t_ : 0; - for (ScoreEventList::iterator it=eventlist.begin(); it!=eventlist.end() && it->first<=t; it++) + for (ScoreEventList::iterator it=staffs.begin()->eventlist.begin(); it!=staffs.begin()->eventlist.end() && it->first<=t; it++) if (it->second.type==FloEvent::TIME_SIG) { tmp.num=it->second.num; @@ -2170,89 +2208,100 @@ void ScoreCanvas::mousePressEvent (QMouseEvent* event) // denn der "bereich" eines schlags geht von schlag_begin bis nächsterschlag_begin-1 // noten werden aber genau in die mitte dieses bereiches gezeichnet - int y=event->y(); + int staff_no= event->y() / STAFF_DISTANCE; + + cout << "STAFF NO = " << staff_no << endl; + + int y=event->y() - staff_no*STAFF_DISTANCE; int x=event->x()+x_pos-x_left; int tick=flo_quantize_floor(x_to_tick(x)); //TODO quantizing must (maybe?) be done with the proper functions - - cout << "mousePressEvent at "<<x<<"/"<<y<<"; tick="<<tick<<endl; - set<FloItem, floComp>::iterator it; - for (it=itemlist[tick].begin(); it!=itemlist[tick].end(); it++) - if (it->type==FloItem::NOTE) - if (it->bbox().contains(x,y)) - break; + list<staff_t>::iterator it=staffs.begin(); + for (int i=0; i<staff_no && it!=staffs.end(); i++) + it++; - if (it!=itemlist[tick].end()) //we found something? + if (it!=staffs.end()) { - mouse_down_pos=event->pos(); - mouse_operation=NO_OP; - - int t=tick; - set<FloItem, floComp>::iterator found; + ScoreItemList& itemlist=it->itemlist; + + cout << "mousePressEvent at "<<x<<"/"<<y<<"; tick="<<tick<<endl; + set<FloItem, floComp>::iterator it; + for (it=itemlist[tick].begin(); it!=itemlist[tick].end(); it++) + if (it->type==FloItem::NOTE) + if (it->bbox().contains(x,y)) + break; - do + if (it!=itemlist[tick].end()) //we found something? { - found=itemlist[t].find(FloItem(FloItem::NOTE, it->pos)); - if (found == itemlist[t].end()) + mouse_down_pos=event->pos(); + mouse_operation=NO_OP; + + int t=tick; + set<FloItem, floComp>::iterator found; + + do { - cout << "FATAL: THIS SHOULD NEVER HAPPEN: could not find the note's tie-destination" << endl; - break; + found=itemlist[t].find(FloItem(FloItem::NOTE, it->pos)); + if (found == itemlist[t].end()) + { + cout << "FATAL: THIS SHOULD NEVER HAPPEN: could not find the note's tie-destination" << endl; + break; + } + else + { + t+=calc_len(found->len, found->dots); + } + } while (found->tied); + + int total_begin=it->begin_tick; + int total_end=t; + + int this_begin=tick; + int this_end=this_begin+calc_len(it->len, it->dots); + + //that's the only note corresponding to the event? + if (this_begin==total_begin && this_end==total_end) + { + if (x < it->x) + mouse_x_drag_operation=BEGIN; + else + mouse_x_drag_operation=LENGTH; } + //that's NOT the only note? else { - t+=calc_len(found->len, found->dots); + if (this_begin==total_begin) + mouse_x_drag_operation=BEGIN; + else if (this_end==total_end) + mouse_x_drag_operation=LENGTH; + else + mouse_x_drag_operation=NO_OP; + } + + cout << "you clicked at a note with begin at "<<it->begin_tick<<" and end at "<<t<<endl; + cout << "x-drag-operation will be "<<mouse_x_drag_operation<<endl; + cout << "pointer to part is "<<it->source_part; + if (!it->source_part) cout << " (WARNING! THIS SHOULD NEVER HAPPEN!)"; + cout << endl; + + dragged_event=*it->source_event; + dragged_event_part=it->source_part; + dragged_event_original_pitch=dragged_event.pitch(); + + if ((mouse_erases_notes) || (event->button()==Qt::MidButton)) //erase? + { + audio->msgDeleteEvent(dragged_event, dragged_event_part, true, false, false); + } + else if (event->button()==Qt::LeftButton) //edit? + { + setMouseTracking(true); + dragging=true; + song->startUndo(); } - } while (found->tied); - - int total_begin=it->begin_tick; - int total_end=t; - - int this_begin=tick; - int this_end=this_begin+calc_len(it->len, it->dots); - - //that's the only note corresponding to the event? - if (this_begin==total_begin && this_end==total_end) - { - if (x < it->x) - mouse_x_drag_operation=BEGIN; - else - mouse_x_drag_operation=LENGTH; - } - //that's NOT the only note? - else - { - if (this_begin==total_begin) - mouse_x_drag_operation=BEGIN; - else if (this_end==total_end) - mouse_x_drag_operation=LENGTH; - else - mouse_x_drag_operation=NO_OP; - } - - cout << "you clicked at a note with begin at "<<it->begin_tick<<" and end at "<<t<<endl; - cout << "x-drag-operation will be "<<mouse_x_drag_operation<<endl; - cout << "pointer to part is "<<it->source_part; - if (!it->source_part) cout << " (WARNING! THIS SHOULD NEVER HAPPEN!)"; - cout << endl; - - dragged_event=*it->source_event; - dragged_event_part=it->source_part; - dragged_event_original_pitch=dragged_event.pitch(); - - if ((mouse_erases_notes) || (event->button()==Qt::MidButton)) //erase? - { - audio->msgDeleteEvent(dragged_event, dragged_event_part, true, false, false); } - else if (event->button()==Qt::LeftButton) //edit? + else //we found nothing? { - setMouseTracking(true); - dragging=true; - song->startUndo(); - } - } - else //we found nothing? - { if ((event->button()==Qt::LeftButton) && (mouse_inserts_notes)) { signed int relative_tick=(signed) tick - curr_part->tick(); @@ -2288,7 +2337,7 @@ void ScoreCanvas::mousePressEvent (QMouseEvent* event) } } } - + } } void ScoreCanvas::mouseReleaseEvent (QMouseEvent* event) @@ -2545,9 +2594,16 @@ void ScoreCanvas::pos_changed(int index, unsigned tick, bool scroll) * o when changing color of a displayed part, note heads aren't redrawn * o when pressing "STOP", the active note isn't redrawn "normally" * + * CURRENT TODO + * o menu entries etc for creating new staves etc. + * o proper mouse.y -> staff_no translation + * * IMPORTANT TODO - * o support violin and bass clefs at one time - * o support multiple note systems + * o support adding staves to existing score window + * o support changing between "all into one" and "each gets one staff" + * o do the STAFF_DISTANCE thingy better + * (grand staffs have to be nearer, user-definable distance etc) + * o support grand staves * o let the user select which clef to use * o removing the part the score's working on isn't handled * o let the user select the currently edited part @@ -2587,6 +2643,8 @@ void ScoreCanvas::pos_changed(int index, unsigned tick, bool scroll) * o refuse to resize so that width gets smaller or equal than x_left * o set distances properly [looks okay, doesn't it?] * o maybe eliminate all the compiler warnings + * o change iterators into const iterators + * o add tracks in correct order to score * * stuff for the other muse developers * o check if dragging notes is done correctly @@ -2633,5 +2691,8 @@ void ScoreCanvas::pos_changed(int index, unsigned tick, bool scroll) * (the systems have enough space in between, so there won't be notes * from sys1 in sys2. if there are, they're ignored for simplicity) * then we proceed as usual (adding, removing, changing notes) + * + * + * pos_add_list stays the same for each staff, so we only need one */ diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h index 53bcae66..84a74cb0 100644 --- a/muse2/muse/midiedit/scoreedit.h +++ b/muse2/muse/midiedit/scoreedit.h @@ -24,6 +24,7 @@ #include "event.h" #include "view.h" #include "gconfig.h" +#include "part.h" #include <set> #include <map> @@ -48,7 +49,6 @@ class QToolBar; class QPushButton; class CtrlEdit; class Splitter; -class PartList; class Toolbar1; class Xml; class QuantConfig; @@ -415,6 +415,13 @@ struct timesig_t int denom; }; +struct staff_t +{ + set<Part*> parts; + ScoreEventList eventlist; + ScoreItemList itemlist; +}; + class ScoreCanvas : public View { Q_OBJECT @@ -423,10 +430,10 @@ class ScoreCanvas : public View static void draw_pixmap(QPainter& p, int x, int y, const QPixmap& pm); static void draw_tie (QPainter& p, int x1, int x4, int yo, bool up=true, QColor color=Qt::black); - static void draw_accidentials(QPainter& p, int x, const list<int>& acc_list, const QPixmap& pix); + static void draw_accidentials(QPainter& p, int x, int y_offset, const list<int>& acc_list, const QPixmap& pix); static list<int> calc_accidentials(tonart_t key, clef_t clef, tonart_t next_key=C); - static void draw_timesig(QPainter& p, int x, int num, int denom); + static void draw_timesig(QPainter& p, int x, int y_offset, int num, int denom); static int calc_timesig_width(int num, int denom); static void draw_number(QPainter& p, int x, int y, int n); @@ -434,7 +441,7 @@ class ScoreCanvas : public View - static ScoreEventList create_appropriate_eventlist(PartList* pl); + static ScoreEventList create_appropriate_eventlist(const set<Part*>& parts); static ScoreItemList create_itemlist(ScoreEventList& eventlist); static note_pos_t note_pos_(int note, tonart_t key); @@ -454,11 +461,11 @@ class ScoreCanvas : public View void process_itemlist(ScoreItemList& itemlist); - void draw_note_lines(QPainter& p); - void draw_preamble(QPainter& p); - void draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList::iterator from_it, ScoreItemList::iterator to_it); - void draw_items(QPainter& p, ScoreItemList& itemlist, int x1, int x2); - void draw_items(QPainter& p, ScoreItemList& itemlist); + void draw_note_lines(QPainter& p, int y); + void draw_preamble(QPainter& p, int y); + void draw_items(QPainter& p, int y, ScoreItemList::iterator from_it, ScoreItemList::iterator to_it); + void draw_items(QPainter& p, int y, ScoreItemList& itemlist, int x1, int x2); + void draw_items(QPainter& p, int y, ScoreItemList& itemlist); void calc_item_pos(ScoreItemList& itemlist); @@ -473,7 +480,8 @@ class ScoreCanvas : public View bool need_redraw_for_hilighting(ScoreItemList::iterator from_it, ScoreItemList::iterator to_it); - bool need_redraw_for_hilighting(int x1, int x2); + bool need_redraw_for_hilighting(ScoreItemList& itemlist, int x1, int x2); + bool need_redraw_for_hilighting(ScoreItemList& itemlist); bool need_redraw_for_hilighting(); int canvas_width(); @@ -491,8 +499,8 @@ class ScoreCanvas : public View static bool pixmaps_loaded; std::map<int,int> pos_add_list; - ScoreEventList eventlist; - ScoreItemList itemlist; + + list<staff_t> staffs; // the drawing area is split into a "preamble" containing clef, // key and time signature, and the "item's area" containing the |