diff options
Diffstat (limited to 'muse2')
| -rw-r--r-- | muse2/muse/midiedit/scoreedit.cpp | 391 | ||||
| -rw-r--r-- | muse2/muse/midiedit/scoreedit.h | 93 | 
2 files changed, 319 insertions, 165 deletions
| diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index 8393ce97..d76f5510 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -67,6 +67,10 @@ using namespace std;  #include "sig.h" +#define SPLIT_NOTE 60 +//TODO: let the user specify that somehow? + +  //TODO: all das unten richtig machen!  #define TICKS_PER_WHOLE (config.division*4)  @@ -95,8 +99,8 @@ using namespace std; -#define STAFF_DISTANCE 100 -#define GRANDSTAFF_DISTANCE 30 +#define STAFF_DISTANCE (10*YLEN) +#define GRANDSTAFF_DISTANCE (8*YLEN)  KeyList keymap; @@ -128,6 +132,26 @@ tonart_t KeyList::key_at_tick(unsigned tick)  	return it->second.key;  } + + + + + +QPixmap *pix_whole, *pix_half, *pix_quarter; // arrays [NUM_PARTCOLORS+2] +QPixmap *pix_dot, *pix_b, *pix_sharp, *pix_noacc; // arrays [NUM_PARTCOLORS+2] +QPixmap *pix_r1, *pix_r2, *pix_r4, *pix_r8, *pix_r16; // pointers +QPixmap *pix_flag_up, *pix_flag_down; // arrays [4] +QPixmap *pix_num; // array [10] +QPixmap *pix_clef_violin, *pix_clef_bass; //pointers +bool pixmaps_loaded=false; + + + + + + + +  //---------------------------------------------------------  //   ScoreEdit  //--------------------------------------------------------- @@ -184,14 +208,6 @@ void ScoreEdit::closeEvent(QCloseEvent* e) -//creation of the static variables -QPixmap *ScoreCanvas::pix_whole, *ScoreCanvas::pix_half, *ScoreCanvas::pix_quarter; -QPixmap *ScoreCanvas::pix_dot, *ScoreCanvas::pix_b, *ScoreCanvas::pix_sharp, *ScoreCanvas::pix_noacc; -QPixmap *ScoreCanvas::pix_r1, *ScoreCanvas::pix_r2, *ScoreCanvas::pix_r4, *ScoreCanvas::pix_r8, *ScoreCanvas::pix_r16; -QPixmap *ScoreCanvas::pix_flag_up, *ScoreCanvas::pix_flag_down; -QPixmap *ScoreCanvas::pix_num; -QPixmap *ScoreCanvas::pix_clef_violin, *ScoreCanvas::pix_clef_bass; -bool ScoreCanvas::pixmaps_loaded=false; @@ -221,7 +237,6 @@ ScoreCanvas::ScoreCanvas(MidiEditor* pr, QWidget* parent,  	//each track gets its own staff  	staff_t staff; -	staff.type=NORMAL;  	set<Track*> tracks;  	for (ciPart it=editor->parts()->begin(); it!=editor->parts()->end(); it++) @@ -234,6 +249,14 @@ ScoreCanvas::ScoreCanvas(MidiEditor* pr, QWidget* parent,  			if (part_it->second->track() == *it)  				staff.parts.insert(part_it->second); +		staff.split_note=SPLIT_NOTE; + +		staff.type=GRAND_TOP; +		staff.clef=VIOLIN; +		staffs.push_back(staff); + +		staff.type=GRAND_BOTTOM; +		staff.clef=BASS;  		staffs.push_back(staff);  	} @@ -245,8 +268,88 @@ ScoreCanvas::ScoreCanvas(MidiEditor* pr, QWidget* parent,  	connect (heartBeatTimer, SIGNAL(timeout()), SLOT(heartbeat_timer_event()));  	connect(song, SIGNAL(posChanged(int, unsigned, bool)), SLOT(pos_changed(int,unsigned,bool))); +	 +	 +	 +	staff_menu=new QMenu(this); + +	staffmode_treble_action = staff_menu->addAction(tr("Treble")); +	connect(staffmode_treble_action, SIGNAL(triggered()), SLOT(staffmode_treble_slot())); + +	staffmode_bass_action = staff_menu->addAction(tr("Bass")); +	connect(staffmode_bass_action, SIGNAL(triggered()), SLOT(staffmode_bass_slot())); + +	staffmode_both_action = staff_menu->addAction(tr("Grand Staff")); +	connect(staffmode_both_action, SIGNAL(triggered()), SLOT(staffmode_both_slot())); +  } +void ScoreCanvas::staffmode_treble_slot() +{ +	cout << "DEBUG: treble" << endl; +	set_staffmode(staff_menu_staff, MODE_TREBLE); +} + +void ScoreCanvas::staffmode_bass_slot() +{ +	cout << "DEBUG: bass" << endl; +	set_staffmode(staff_menu_staff, MODE_BASS); +} + +void ScoreCanvas::staffmode_both_slot() +{ +	cout << "DEBUG: both" << endl; +	set_staffmode(staff_menu_staff, MODE_BOTH); +} + +void ScoreCanvas::set_staffmode(list<staff_t>::iterator it, staff_mode_t mode) +{ +	cout << "DEBUG: in set_staffmode" << endl; +	if (it->type == GRAND_BOTTOM) +	{ +		it--; +		if (it->type!=GRAND_TOP) +			cout << "THIS SHOULD NEVER HAPPEN: grand_bottom without top!"<<endl; +	} +	 +	if (it->type==GRAND_TOP) +	{ +		list<staff_t>::iterator tmp=it; +		tmp++; +		if (tmp->type!=GRAND_BOTTOM) +			cout << "THIS SHOULD NEVER HAPPEN: grand_top without bottom!"<<endl; +		staffs.erase(tmp); +	} +	 +	switch (mode) +	{ +		case MODE_TREBLE: +			it->type=NORMAL; +			it->clef=VIOLIN; +			break; +			 +		case MODE_BASS: +			it->type=NORMAL; +			it->clef=BASS; +			break; +		 +		case MODE_BOTH: +			it->type=GRAND_BOTTOM; +			it->clef=BASS; +			it->split_note=SPLIT_NOTE; +			 +			staffs.insert(it, staff_t(GRAND_TOP, VIOLIN, it->parts, it->split_note)); +			break; +		 +		default: +			cout << "ILLEGAL FUNCTION CALL: invalid mode in set_staffmode" << endl; +	} +	 +	recalc_staff_pos(); +	song_changed(0); +} + +  void ScoreCanvas::song_changed(int)  {  	cout << "song changed!" << endl; @@ -255,10 +358,10 @@ void ScoreCanvas::song_changed(int)  	for (list<staff_t>::iterator it=staffs.begin(); it!=staffs.end(); it++)  	{ -		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); +		it->create_appropriate_eventlist(it->parts); +		it->create_itemlist(); +		it->process_itemlist(); // do note- and rest-grouping and collision avoiding +		it->calc_item_pos();  	}  	redraw(); @@ -433,13 +536,13 @@ int flo_quantize_floor(int tick)   * 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) +void staff_t::create_appropriate_eventlist(const set<Part*>& parts)  {  	using AL::sigmap;  	using AL::iSigEvent; -	ScoreEventList result; -	 +	eventlist.clear(); +  	// phase one: fill the list -----------------------------------------  	//insert note on events @@ -452,13 +555,16 @@ ScoreEventList ScoreCanvas::create_appropriate_eventlist(const set<Part*>& parts  		{  			Event& event=it->second; -			if (event.isNote() && !event.isNoteOff()) +			if ( (event.isNote() && !event.isNoteOff()) && +			     ( ((type==GRAND_TOP) && (event.pitch() >= split_note)) || +			       ((type==GRAND_BOTTOM) && (event.pitch() < split_note)) || +			       (type==NORMAL) )                          )  			{  				unsigned begin, end;  				begin=flo_quantize(event.tick()+part->tick());  				end=flo_quantize(event.endTick()+part->tick());  				cout <<"inserting note on at "<<begin<<" with pitch="<<event.pitch()<<" and len="<<end-begin<<endl; -				result.insert(pair<unsigned, FloEvent>(begin, FloEvent(begin,event.pitch(), event.velo(),end-begin,FloEvent::NOTE_ON,part,&it->second))); +				eventlist.insert(pair<unsigned, FloEvent>(begin, FloEvent(begin,event.pitch(), event.velo(),end-begin,FloEvent::NOTE_ON,part,&it->second)));  			}  			//else ignore it  		} @@ -478,41 +584,39 @@ ScoreEventList ScoreCanvas::create_appropriate_eventlist(const set<Part*>& parts  		}  		cout << "new signature from tick "<<from<<" to " << to << ": "<<it->second->sig.z<<"/"<<it->second->sig.n<<"; ticks per measure = "<<ticks_per_measure<<endl; -		result.insert(pair<unsigned, FloEvent>(from,  FloEvent(from, FloEvent::TIME_SIG, it->second->sig.z, it->second->sig.n) ) ); +		eventlist.insert(pair<unsigned, FloEvent>(from,  FloEvent(from, FloEvent::TIME_SIG, it->second->sig.z, it->second->sig.n) ) );  		for (unsigned t=from; t<to; t+=ticks_per_measure) -			result.insert(pair<unsigned, FloEvent>(t,  FloEvent(t,0,0,ticks_per_measure,FloEvent::BAR) ) ); +			eventlist.insert(pair<unsigned, FloEvent>(t,  FloEvent(t,0,0,ticks_per_measure,FloEvent::BAR) ) );  	}  	//insert key changes  	for (iKeyEvent it=keymap.begin(); it!=keymap.end(); it++) -		result.insert(pair<unsigned, FloEvent>(it->second.tick,  FloEvent(it->second.tick,FloEvent::KEY_CHANGE, it->second.key ) ) ); +		eventlist.insert(pair<unsigned, FloEvent>(it->second.tick,  FloEvent(it->second.tick,FloEvent::KEY_CHANGE, it->second.key ) ) );  	// phase two: deal with overlapping notes ---------------------------  	ScoreEventList::iterator it, it2;  	//iterate through all note_on - events -	for (it=result.begin(); it!=result.end(); it++) +	for (it=eventlist.begin(); it!=eventlist.end(); it++)  		if (it->second.type==FloEvent::NOTE_ON)  		{  			unsigned end_tick=it->first + it->second.len;  			//iterate though all (relevant) later note_ons which are  			//at the same pitch. if there's a collision, shorten it's len -			for (it2=it, it2++; it2!=result.end() && it2->first < end_tick; it2++) +			for (it2=it, it2++; it2!=eventlist.end() && it2->first < end_tick; it2++)  				if ((it2->second.type==FloEvent::NOTE_ON) && (it2->second.pitch == it->second.pitch))  					it->second.len=it2->first - it->first;  		}  		// phase three: eliminate zero-length-notes ------------------------- -		for (it=result.begin(); it!=result.end();) +		for (it=eventlist.begin(); it!=eventlist.end();)  			if ((it->second.type==FloEvent::NOTE_ON) && (it->second.len<=0)) -				result.erase(it++); +				eventlist.erase(it++);  			else  				it++; -	 -	return result;  } @@ -537,7 +641,7 @@ int n_accidentials(tonart_t t)  //note needs to be 0..11  //always assumes violin clef  //only for internal use -note_pos_t ScoreCanvas::note_pos_(int note, tonart_t key) +note_pos_t note_pos_(int note, tonart_t key)  {  	note_pos_t result;  	           //C CIS D DIS E F FIS G GIS A AIS H @@ -604,7 +708,7 @@ note_pos_t ScoreCanvas::note_pos_(int note, tonart_t key)  // in violin clef, line 2 is E4  // in bass clef, line 2 is G2 -note_pos_t ScoreCanvas::note_pos (unsigned note, tonart_t key, clef_t clef) +note_pos_t note_pos (unsigned note, tonart_t key, clef_t clef)  {  	int octave=(note/12)-1; //integer division. note is unsigned  	note=note%12; @@ -631,7 +735,7 @@ note_pos_t ScoreCanvas::note_pos (unsigned note, tonart_t key, clef_t clef)  } -int ScoreCanvas::calc_len(int l, int d) +int calc_len(int l, int d)  {  	// l=0,1,2 -> whole, half, quarter (think of 2^0, 2^1, 2^2)  	// d=number of dots @@ -729,7 +833,7 @@ vector<int> create_emphasize_list(int num, int denom) //TODO FINDMICH  //whole, half, quarter, eighth = 0,1,2,3  //NOT:  1,2,4,8! (think of 2^foo)  //len is in ticks -list<note_len_t> ScoreCanvas::parse_note_len(int len_ticks, int begin_tick, vector<int>& foo, bool allow_dots, bool allow_normal) +list<note_len_t> parse_note_len(int len_ticks, int begin_tick, vector<int>& foo, bool allow_dots, bool allow_normal)  {  	list<note_len_t> retval; @@ -914,15 +1018,16 @@ void ScoreCanvas::draw_accidentials(QPainter& p, int x, int y_offset, const list  	}  } -ScoreItemList ScoreCanvas::create_itemlist(ScoreEventList& eventlist) +void staff_t::create_itemlist()  { -	ScoreItemList itemlist;  	tonart_t tmp_key=C;  	int lastevent=0;  	int next_measure=-1;  	int last_measure=-1;  	vector<int> emphasize_list=create_emphasize_list(4,4); //actually unneccessary, for safety +	itemlist.clear(); +  	for (ScoreEventList::iterator it=eventlist.begin(); it!=eventlist.end(); it++)  	{  		int t, pitch, len, velo, actual_tick; @@ -935,7 +1040,7 @@ ScoreItemList ScoreCanvas::create_itemlist(ScoreEventList& eventlist)  		actual_tick=it->second.tick;  		if (actual_tick==-1) actual_tick=t; -		note_pos_t notepos=note_pos(pitch,tmp_key,USED_CLEF); //TODO einstellmöglichkeiten +		note_pos_t notepos=note_pos(pitch,tmp_key,clef); //TODO einstellmöglichkeiten  		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="<<notepos.height<<"\tvorzeichen="<<notepos.vorzeichen << endl; @@ -1068,11 +1173,9 @@ ScoreItemList ScoreCanvas::create_itemlist(ScoreEventList& eventlist)  			tmp_key=it->second.tonart; // TODO FINDMICH MARKER das muss schöner werden  		}  	}	 - -	return itemlist;  } -void ScoreCanvas::process_itemlist(ScoreItemList& itemlist) +void staff_t::process_itemlist()  {  	stdmap<int,int> occupied;  	int last_measure=0; @@ -1538,7 +1641,7 @@ void ScoreCanvas::draw_note_lines(QPainter& p, int y)  } -void ScoreCanvas::calc_item_pos(ScoreItemList& itemlist) +void staff_t::calc_item_pos()  {  	tonart_t curr_key=C;  	int pos_add=0; @@ -1615,8 +1718,8 @@ void ScoreCanvas::calc_item_pos(ScoreItemList& itemlist)  			{  				tonart_t new_key=it->tonart; -				list<int> aufloes_list=calc_accidentials(curr_key, USED_CLEF, new_key); -				list<int> new_acc_list=calc_accidentials(new_key, USED_CLEF); +				list<int> aufloes_list=calc_accidentials(curr_key, clef, new_key); +				list<int> new_acc_list=calc_accidentials(new_key, clef);  				int n_acc_drawn=aufloes_list.size() + new_acc_list.size();  				pos_add+=n_acc_drawn*KEYCHANGE_ACC_DIST+ KEYCHANGE_ACC_LEFTDIST+ KEYCHANGE_ACC_RIGHTDIST; @@ -1645,8 +1748,8 @@ void ScoreCanvas::calc_pos_add_list()  	for (iKeyEvent it=keymap.begin(); it!=keymap.end(); it++)  	{  		tonart_t new_key=it->second.key; -		list<int> aufloes_list=calc_accidentials(curr_key, USED_CLEF, new_key); -		list<int> new_acc_list=calc_accidentials(new_key, USED_CLEF); +		list<int> aufloes_list=calc_accidentials(curr_key, VIOLIN, new_key); //clef argument is unneccessary +		list<int> new_acc_list=calc_accidentials(new_key, VIOLIN);           //in this case  		int n_acc_drawn=aufloes_list.size() + new_acc_list.size();  		pos_add_list[it->second.tick]+=n_acc_drawn*KEYCHANGE_ACC_DIST+ KEYCHANGE_ACC_LEFTDIST+ KEYCHANGE_ACC_RIGHTDIST; @@ -1654,7 +1757,7 @@ void ScoreCanvas::calc_pos_add_list()  	}  } -void ScoreCanvas::draw_items(QPainter& p, int y, ScoreItemList& itemlist, int x1, int x2) +void ScoreCanvas::draw_items(QPainter& p, int y, staff_t& staff, int x1, int x2)  {  	int from_tick, to_tick;  	ScoreItemList::iterator from_it, to_it; @@ -1662,36 +1765,36 @@ void ScoreCanvas::draw_items(QPainter& p, int y, ScoreItemList& itemlist, int x1  	//drawing too much isn't bad. drawing too few is.  	from_tick=x_to_tick(x1); -	from_it=itemlist.lower_bound(from_tick); +	from_it=staff.itemlist.lower_bound(from_tick);  	//from_it now contains the first time which is fully drawn  	//however, the previous beat could still be relevant, when it's  	//partly drawn. so we decrement from_it -	if (from_it!=itemlist.begin()) from_it--; +	if (from_it!=staff.itemlist.begin()) from_it--;  	//decrement until we're at a time with a bar  	//otherwise, drawing accidentials will be broken -	while (from_it!=itemlist.begin() && from_it->second.find(FloItem(FloItem::BAR))==from_it->second.end()) +	while (from_it!=staff.itemlist.begin() && from_it->second.find(FloItem(FloItem::BAR))==from_it->second.end())  		from_it--;  	to_tick=x_to_tick(x2); -	to_it=itemlist.upper_bound(to_tick); +	to_it=staff.itemlist.upper_bound(to_tick);  	//to_it now contains the first time which is not drawn at all any more  	//however, a tie from 1:04 to 2:01 is stored in 2:01, not in 1:04,  	//so for drawing ties, we need to increment to_it, so that the  	//"first time not drawn at all any more" is the last which gets  	//actually drawn. -	if (to_it!=itemlist.end()) to_it++; //do one tick more than neccessary. this will draw ties +	if (to_it!=staff.itemlist.end()) to_it++; //do one tick more than neccessary. this will draw ties -	draw_items(p,y, from_it, to_it);	 +	draw_items(p,y, staff, from_it, to_it);	  } -void ScoreCanvas::draw_items(QPainter& p, int y, ScoreItemList& itemlist) +void ScoreCanvas::draw_items(QPainter& p, int y, staff_t& staff)  { -	draw_items(p,y, itemlist,x_pos,x_pos+width()-x_left); +	draw_items(p,y, staff,x_pos,x_pos+width()-x_left);  } -void ScoreCanvas::draw_items(QPainter& p, int y_offset, ScoreItemList::iterator from_it, ScoreItemList::iterator to_it) +void ScoreCanvas::draw_items(QPainter& p, int y_offset, staff_t& staff, ScoreItemList::iterator from_it, ScoreItemList::iterator to_it)  {  	// init accidentials properly  	vorzeichen_t curr_accidential[7]; @@ -1699,7 +1802,7 @@ void ScoreCanvas::draw_items(QPainter& p, int y_offset, ScoreItemList::iterator  	tonart_t curr_key;  	curr_key=key_at_tick(from_it->first); -	list<int> new_acc_list=calc_accidentials(curr_key, USED_CLEF); +	list<int> new_acc_list=calc_accidentials(curr_key, staff.clef);  	vorzeichen_t new_accidential = is_sharp_key(curr_key) ? SHARP : B;  	for (int i=0;i<7;i++) @@ -1889,8 +1992,8 @@ void ScoreCanvas::draw_items(QPainter& p, int y_offset, ScoreItemList::iterator  				tonart_t new_key=it->tonart;  				cout << "\tKEY CHANGE: from "<<curr_key<<" to "<<new_key<<endl; -				list<int> aufloes_list=calc_accidentials(curr_key, USED_CLEF, new_key); -				list<int> new_acc_list=calc_accidentials(new_key, USED_CLEF); +				list<int> aufloes_list=calc_accidentials(curr_key, staff.clef, new_key); +				list<int> new_acc_list=calc_accidentials(new_key, staff.clef);  				// vorzeichen aus curr_key auflösen  				draw_accidentials(p, it->x + KEYCHANGE_ACC_LEFTDIST - x_pos+x_left, y_offset, aufloes_list, pix_noacc[BLACK_PIXMAP]); @@ -1983,7 +2086,7 @@ bool ScoreCanvas::need_redraw_for_hilighting(ScoreItemList::iterator from_it, Sc  	return false;  } -int ScoreCanvas::clef_height(clef_t clef) +int clef_height(clef_t clef)  {  	switch (clef) //CLEF_MARKER  	{ @@ -2003,14 +2106,14 @@ int ScoreCanvas::clef_height(clef_t clef)  #define CLEF_LEFTMARGIN 5  #define CLEF_RIGHTMARGIN 5 -void ScoreCanvas::draw_preamble(QPainter& p, int y_offset) +void ScoreCanvas::draw_preamble(QPainter& p, int y_offset, clef_t clef)  {  	int x_left_old=x_left;  	int tick=x_to_tick(x_pos);  	// draw clef -------------------------------------------------------- -	QPixmap* pix_clef= (USED_CLEF==BASS) ? pix_clef_bass : pix_clef_violin; -	int y_coord=2*YLEN  -  ( clef_height(USED_CLEF) -2)*YLEN/2; +	QPixmap* pix_clef= (clef==BASS) ? pix_clef_bass : pix_clef_violin; +	int y_coord=2*YLEN  -  ( clef_height(clef) -2)*YLEN/2;  	draw_pixmap(p,CLEF_LEFTMARGIN + pix_clef->width()/2,y_offset + y_coord,*pix_clef); @@ -2020,7 +2123,7 @@ void ScoreCanvas::draw_preamble(QPainter& p, int y_offset)  	// draw accidentials ------------------------------------------------  	tonart_t key=key_at_tick(tick);  	QPixmap* pix_acc=is_sharp_key(key) ? &pix_sharp[BLACK_PIXMAP] : &pix_b[BLACK_PIXMAP]; -	list<int> acclist=calc_accidentials(key,USED_CLEF); +	list<int> acclist=calc_accidentials(key,clef);  	draw_accidentials(p,x_left, y_offset, acclist ,*pix_acc); @@ -2056,7 +2159,7 @@ void ScoreCanvas::draw_timesig(QPainter& p, int x, int y_offset, int num, int de  	draw_number(p, x+denom_indent, y_offset +DIGIT_YDIST, denom);  } -int ScoreCanvas::calc_timesig_width(int num, int denom) +int calc_timesig_width(int num, int denom)  {  	int num_width=calc_number_width(num);  	int denom_width=calc_number_width(denom); @@ -2064,7 +2167,7 @@ int ScoreCanvas::calc_timesig_width(int num, int denom)  	return width+TIMESIG_LEFTMARGIN+TIMESIG_RIGHTMARGIN;  } -int ScoreCanvas::calc_number_width(int n) +int calc_number_width(int n)  {  	string str=IntToStr(n);  	return (str.length()*DIGIT_WIDTH); @@ -2094,15 +2197,15 @@ void ScoreCanvas::draw(QPainter& p, const QRect&)  	for (list<staff_t>::iterator it=staffs.begin(); it!=staffs.end(); it++)  	{  		draw_note_lines(p,it->y_draw); -		draw_preamble(p,it->y_draw); +		draw_preamble(p,it->y_draw, it->clef);  		p.setClipRect(x_left+1,0,p.device()->width(),p.device()->height()); -		draw_items(p,it->y_draw, it->itemlist); +		draw_items(p,it->y_draw, *it);  		p.setClipping(false);  	}  } -list<int> ScoreCanvas::calc_accidentials(tonart_t key, clef_t clef, tonart_t next_key) +list<int> calc_accidentials(tonart_t key, clef_t clef, tonart_t next_key)  {  	list<int> result; @@ -2213,7 +2316,7 @@ int ScoreCanvas::height_to_pitch(int h, clef_t clef, tonart_t key)  {  	int add=0; -	list<int> accs=calc_accidentials(key,USED_CLEF); +	list<int> accs=calc_accidentials(key,clef);  	for (list<int>::iterator it=accs.begin(); it!=accs.end(); it++)  	{ @@ -2255,85 +2358,95 @@ void ScoreCanvas::mousePressEvent (QMouseEvent* event)  	if (it!=staffs.end())  	{ -		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; -		 -		if (it!=itemlist[tick].end()) //we found something? +		if (event->x() <= x_left) //clicked in the preamble?  		{ -			mouse_down_pos=event->pos(); -			mouse_operation=NO_OP; -			 -			int t=tick; -			set<FloItem, floComp>::iterator found; +			if (event->button() == Qt::RightButton) //right-click? +			{ +				staff_menu_staff=it; +				staff_menu->popup(event->globalPos()); +			} +		} +		else +		{ +			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 +				{ +					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)  				{ -					cout << "FATAL: THIS SHOULD NEVER HAPPEN: could not find the note's tie-destination" << endl; -					break; +					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(); @@ -2369,6 +2482,7 @@ void ScoreCanvas::mousePressEvent (QMouseEvent* event)  			}  		}  	} +		}  	}  } @@ -2669,8 +2783,7 @@ list<staff_t>::iterator ScoreCanvas::staff_at_y(int y)   * CURRENT TODO   *   o menu entries etc for creating new staves etc.   *   o drag-and-dropping staves to merge them - *   o right-click-menu for staves to select clef(s), remove it etc - *   o consider both small staves from a grand stave as ONE staff + *   o right-click-menu or middle-click for removing staves etc   *    * IMPORTANT TODO   *   o support adding staves to existing score window diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h index 189e9e0b..0a22def9 100644 --- a/muse2/muse/midiedit/scoreedit.h +++ b/muse2/muse/midiedit/scoreedit.h @@ -83,6 +83,7 @@ class ScoreEdit : public MidiEditor  		QScrollBar* hscroll; +				  	private slots: @@ -458,6 +459,13 @@ enum staff_type_t  	GRAND_BOTTOM  }; +enum staff_mode_t +{ +	MODE_TREBLE, +	MODE_BASS, +	MODE_BOTH +}; +  struct staff_t  {  	set<Part*> parts; @@ -469,8 +477,43 @@ struct staff_t  	int y_bottom;  	staff_type_t type; +	clef_t clef; +	unsigned split_note; +	 +	void create_appropriate_eventlist(const set<Part*>& parts); +	void create_itemlist(); +	void process_itemlist(); +	void calc_item_pos(); +	 +	staff_t() +	{ +		type=NORMAL; +		clef=VIOLIN; +	} +	 +	staff_t (staff_type_t type_, clef_t clef_, set<Part*> parts_, unsigned split_note_=0) +	{ +		type=type_; +		clef=clef_; +		split_note=split_note_; +		parts=parts_; +	}  }; +list<int> calc_accidentials(tonart_t key, clef_t clef, tonart_t next_key=C); +note_pos_t note_pos_(int note, tonart_t key); +note_pos_t note_pos (unsigned note, tonart_t key, clef_t clef); + +int calc_len(int l, int d); +list<note_len_t> parse_note_len(int len_ticks, int begin_tick, vector<int>& foo, bool allow_dots=true, bool allow_normal=true); + +int clef_height(clef_t clef); + + +int calc_timesig_width(int num, int denom); +int calc_number_width(int n); + +  class ScoreCanvas : public View  {  	Q_OBJECT @@ -480,26 +523,14 @@ class ScoreCanvas : public View  		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, 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 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); -		static int calc_number_width(int n); - - -		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); -		static note_pos_t note_pos (unsigned note, tonart_t key, clef_t clef); -		static int calc_len(int l, int d); -		static list<note_len_t> parse_note_len(int len_ticks, int begin_tick, vector<int>& foo, bool allow_dots=true, bool allow_normal=true); -		static int clef_height(clef_t clef);  		static int height_to_pitch(int h, clef_t clef, tonart_t key);  		static int height_to_pitch(int h, clef_t clef); @@ -509,13 +540,11 @@ class ScoreCanvas : public View -		void process_itemlist(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); +		void draw_preamble(QPainter& p, int y, clef_t clef); +		void draw_items(QPainter& p, int y, staff_t& staff, ScoreItemList::iterator from_it, ScoreItemList::iterator to_it); +		void draw_items(QPainter& p, int y, staff_t& staff, int x1, int x2); +		void draw_items(QPainter& p, int y, staff_t& staff);  		void calc_pos_add_list(); @@ -540,15 +569,10 @@ class ScoreCanvas : public View  		int viewport_width(); -// member variables --------------------------------------------------- +		void set_staffmode(list<staff_t>::iterator it, staff_mode_t mode); +		 -		static QPixmap *pix_whole, *pix_half, *pix_quarter; // arrays [NUM_PARTCOLORS+2] -		static QPixmap *pix_dot, *pix_b, *pix_sharp, *pix_noacc; // arrays [NUM_PARTCOLORS+2] -		static QPixmap *pix_r1, *pix_r2, *pix_r4, *pix_r8, *pix_r16; // pointers -		static QPixmap *pix_flag_up, *pix_flag_down; // arrays [4] -		static QPixmap *pix_num; // array [10] -		static QPixmap *pix_clef_violin, *pix_clef_bass; //pointers -		static bool pixmaps_loaded; +// member variables ---------------------------------------------------  		std::map<int,int> pos_add_list; @@ -594,6 +618,23 @@ class ScoreCanvas : public View  		int dragged_event_original_pitch; + + + +		//menu stuff +		QAction* staffmode_treble_action; +		QAction* staffmode_bass_action; +		QAction* staffmode_both_action; +		 +		QMenu* staff_menu; +		list<staff_t>::iterator staff_menu_staff; + + +	private slots: +		void staffmode_treble_slot(); +		void staffmode_bass_slot(); +		void staffmode_both_slot(); +     public slots:        void scroll_event(int);        void song_changed(int); | 
