1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  scoreedit.h
5 //  (C) Copyright 2011 Florian Jung (flo93@users.sourceforge.net)
6 //
7 //  This program is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU General Public License
9 //  as published by the Free Software Foundation; version 2 of
10 //  the License, or (at your option) any later version.
11 //
12 //  This program is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 //  GNU General Public License for more details.
16 //
17 //  You should have received a copy of the GNU General Public License
18 //  along with this program; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 //=========================================================
22 
23 #ifndef __SCOREEDIT_H__
24 #define __SCOREEDIT_H__
25 
26 #include <limits.h>
27 #include "type_defs.h"
28 #include "cobject.h"
29 #include "event.h"
30 #include "view.h"
31 #include "gconfig.h"
32 #include "keyevent.h"
33 #include "cleftypes.h"
34 #include "helper.h"
35 #include "event_tag_list.h"
36 
37 #include <set>
38 #include <map>
39 #include <list>
40 #include <vector>
41 #include <string>
42 
43 using std::set;
44 using std::pair;
45 using std::map;
46 using std::list;
47 using std::vector;
48 using std::string;
49 
50 
51 
52 #define TICKS_PER_WHOLE (MusEGlobal::config.division*4)
53 #define SONG_LENGTH (MusEGlobal::song->len())
54 
55 
56 
57 enum {CMD_COLOR_BLACK, CMD_COLOR_VELO, CMD_COLOR_PART,
58       CMD_SET_NAME,
59       CMD_NOTELEN_1, CMD_NOTELEN_2, CMD_NOTELEN_4, CMD_NOTELEN_8,
60       CMD_NOTELEN_16, CMD_NOTELEN_32, CMD_NOTELEN_LAST,
61 
62       CMD_QUANTIZE, CMD_VELOCITY, CMD_CRESCENDO, CMD_NOTELEN, CMD_TRANSPOSE,
63       CMD_ERASE, CMD_MOVE, CMD_FIXED_LEN, CMD_DELETE_OVERLAPS, CMD_LEGATO,
64       CMD_CUT, CMD_COPY, CMD_COPY_RANGE, CMD_PASTE, CMD_PASTE_DIALOG, CMD_DEL,
65       CMD_SELECT_ALL, CMD_SELECT_NONE, CMD_SELECT_INVERT,
66       CMD_SELECT_ILOOP, CMD_SELECT_OLOOP};
67 
68 
69 
70 
71 // Forward declarations:
72 class QCloseEvent;
73 class QResizeEvent;
74 class QKeyEvent;
75 class QPainter;
76 class QPixmap;
77 class QScrollBar;
78 class QComboBox;
79 class QAction;
80 class QActionGroup;
81 class QGridLayout;
82 class QToolButton;
83 
84 namespace MusECore {
85 class Part;
86 class StepRec;
87 }
88 
89 namespace MusEGui {
90 class EditToolBar;
91 class ScoreCanvas;
92 class MTScaleFlo;
93 class SpinBox;
94 
95 //---------------------------------------------------------
96 //   ScoreEdit
97 //---------------------------------------------------------
98 
99 class ScoreEdit : public TopWin
100 {
101 	Q_OBJECT
102 	private:
103         void closeEvent(QCloseEvent*) override;
104 
105 		void init_name();
106 
107 		QGridLayout* mainGrid;
108 		QWidget* mainw;
109 
110 		MusEGui::EditToolBar* edit_tools;
111 		SpinBox* velo_spinbox;
112 		SpinBox* velo_off_spinbox;
113 
114 		QComboBox* quant_combobox;
115 		SpinBox* px_per_whole_spinbox;
116 
117 		QAction* preamble_keysig_action;
118 		QAction* preamble_timesig_action;
119 
120 		QActionGroup* len_actions;
121 		QAction* n1_action;
122 		QAction* n2_action;
123 		QAction* n4_action;
124 		QAction* n8_action;
125 		QAction* n16_action;
126 		QAction* n32_action;
127 		QAction* nlast_action;
128 
129 		QActionGroup* color_actions;
130 		QAction* color_black_action;
131 		QAction* color_velo_action;
132 		QAction* color_part_action;
133 
134 		QMenu* color_menu;
135 
136 		QAction* cut_action;
137 		QAction* copy_action;
138 		QAction* copy_range_action;
139 		QAction* paste_action;
140 		QAction* paste_dialog_action;
141 		QAction* del_action;
142 
143 		QAction* select_all_action;
144 		QAction* select_none_action;
145 		QAction* select_invert_action;
146 		QAction* select_iloop_action;
147 		QAction* select_oloop_action;
148 
149 		QAction* func_quantize_action;
150 		QAction* func_notelen_action;
151 		QAction* func_velocity_action;
152 		QAction* func_cresc_action;
153 		QAction* func_transpose_action;
154 		QAction* func_erase_action;
155 		QAction* func_move_action;
156 		QAction* func_fixed_len_action;
157 		QAction* func_del_overlaps_action;
158 		QAction* func_legato_action;
159 
160 		QToolButton* srec;
161 
162 		QScrollBar* xscroll;
163 		QScrollBar* yscroll;
164 		ScoreCanvas* score_canvas;
165 		MusEGui::MTScaleFlo* time_bar;
166 
167 		bool apply_velo;
168 
169 		static set<QString> names;
170 
171 		QString name;
172 
173 		bool set_name(QString newname, bool emit_signal=true, bool emergency_name=false);
174 
175         void keyPressEvent(QKeyEvent*) override;
176 
177 	private slots:
178 		void menu_command(int);
179 		void velo_box_changed();
180 		void velo_off_box_changed();
181 		void quant_combobox_changed(int);
182 		void init_shortcuts();
183 		void selection_changed();
184 		void clipboard_changed();
185     void config_changed();
186 
187 	signals:
188 		void isDeleting(MusEGui::TopWin*);
189 		void name_changed();
190 		void velo_changed(int);
191 		void velo_off_changed(int);
192 
193 	public slots:
194 		void canvas_width_changed(int);
195 		void viewport_width_changed(int);
196 		void canvas_height_changed(int);
197 		void viewport_height_changed(int);
198 		void song_changed(MusECore::SongChangedStruct_t);
199         void focusCanvas() override;
200 
201 	public:
202         ScoreEdit(QWidget* parent = nullptr, const char* name = nullptr, unsigned initPos = INT_MAX);
203         ~ScoreEdit() override;
204 
205         void writeStatus(int level, MusECore::Xml& xml) const override;
206         void readStatus(MusECore::Xml& xml) override;
207 		static void read_configuration(MusECore::Xml&);
208 		static void write_configuration(int, MusECore::Xml&);
209         void storeSettings() override;
210 
211 		void add_parts(MusECore::PartList* pl, bool all_in_one=false);
get_name()212 		QString get_name() { return name; }
get_apply_velo()213 		bool get_apply_velo() { return apply_velo; }
214 
215 		bool itemsAreSelected() const;
216 		// Appends given tag list with item objects according to options. Avoids duplicate events or clone events.
217 		// Special: We 'abuse' a controller event's length, normally 0, to indicate visual item length.
218 		void tagItems(MusECore::TagEventList* tag_list, const MusECore::EventTagOptionsStruct& options) const;
219         void setEditTool(int tool);
220 };
221 
222 
223 
224 
225 
226 
227 enum stem_t
228 {
229 	UPWARDS,
230 	DOWNWARDS
231 };
232 
233 enum vorzeichen_t
234 {
235 	B=-1,
236 	NONE=0,
237 	SHARP=1
238 };
239 
240 struct note_pos_t
241 {
242 	int height; // 0 means "C-line", 1 "D-line" and so on
243 	vorzeichen_t vorzeichen;
244 
245 	bool operator== (const note_pos_t& that) const
246 	{
247 		return (this->height==that.height) && (this->vorzeichen == that.vorzeichen);
248 	}
249 };
250 
251 bool operator< (const note_pos_t& a, const note_pos_t& b);
252 
253 
254 
255 
256 
257 
258 
259 class FloEvent
260 {
261 	public:
262 		enum typeEnum { NOTE_ON = 30, NOTE_OFF = 10, BAR = 20, KEY_CHANGE=23, TIME_SIG=26 }; //the order matters!
263 		typeEnum type;
264 		unsigned tick;
265 		const MusECore::Part* source_part;
266 		const MusECore::Event* source_event;
267 
268 		int pitch;
269 		mutable int vel;
270 		mutable int len;
271 
272 		int num;
273 		int denom;
274 
275 		MusECore::key_enum key;
276 		bool minor;
277 
278         FloEvent(unsigned ti, int p,int v,int l,typeEnum t, const MusECore::Part* part=nullptr, const MusECore::Event* event=nullptr)
279 		{
280 			pitch=p;
281 			vel=v;
282 			len=l;
283 			type= t;
284 			tick=ti;
285 			source_event=event;
286 			source_part=part;
287 
288 			num=denom=0xdeadbeef; //unused, but valgrind complains if uninited
289 			key=MusECore::KEY_C;
290 			minor = false;
291 		}
FloEvent(unsigned ti,typeEnum t,int num_,int denom_)292 		FloEvent(unsigned ti, typeEnum t, int num_, int denom_)
293 		{
294 			type=t;
295 			num=num_;
296 			denom=denom_;
297 			tick=ti;
298 			source_event=NULL;
299 			source_part=NULL;
300 
301 			len=vel=pitch=0xdeadbeef; //unused, but valgrind complains if uninited
302 			key=MusECore::KEY_C;
303 			minor = false;
304 		}
FloEvent(unsigned ti,typeEnum t,MusECore::key_enum k,bool isMinor)305 		FloEvent(unsigned ti, typeEnum t, MusECore::key_enum k, bool isMinor)
306 		{
307 			type=t;
308 			key=k;
309 			minor = isMinor;
310 			tick=ti;
311 			source_event=NULL;
312 			source_part=NULL;
313 
314 			pitch=vel=len=num=denom=0xdeadbeef; //unused, but valgrind complains if uninited
315 		}
316 };
317 class FloItem
318 {
319 	public:
320 		enum typeEnum { NOTE=21, REST=22, NOTE_END=01, REST_END=02, BAR =10, KEY_CHANGE=13, TIME_SIG=16}; //the order matters!
321 		typeEnum type;
322 		unsigned begin_tick;
323 		const MusECore::Event* source_event;
324 		const MusECore::Part* source_part;
325 
326 		note_pos_t pos;
327 		int len;
328 		int dots;
329 		bool tied;
330 		bool already_grouped;
331 
332 		int num;
333 		int denom;
334 
335 		MusECore::key_enum key;
336 		bool minor;
337 
338 		mutable stem_t stem;
339 		mutable int shift;
340 		mutable bool ausweich;
341 		mutable bool is_tie_dest;
342 		mutable int tie_from_x;
343 
344 		mutable int x;
345 		mutable int y;
346 		mutable int stem_x;
347 		mutable QPixmap* pix;
348 
349 		mutable bool is_active;
350 
351 		QRect bbox() const;
352 
353 
354 
355 		FloItem(typeEnum t, note_pos_t p, int l=0,int d=0, bool ti=false, unsigned beg=0, const MusECore::Part* part=NULL, const MusECore::Event* event=NULL)
356 		{
357 			pos=p;
358 			dots=d;
359 			len=l;
360 			type=t;
361 			already_grouped=false;
362 			tied=ti;
363 			shift=0;
364 			ausweich=false;
365 			is_tie_dest=false;
366 			begin_tick=beg;
367 			source_event=event;
368 			source_part=part;
369 			is_active=false;
370 		}
371 
FloItem(typeEnum t,int num_,int denom_)372 		FloItem(typeEnum t, int num_, int denom_)
373 		{
374 			type=t;
375 			num=num_;
376 			denom=denom_;
377 			begin_tick=-1;
378 			source_event=NULL;
379 			source_part=NULL;
380 		}
381 
FloItem(typeEnum t,MusECore::key_enum k,bool isMinor)382 		FloItem(typeEnum t, MusECore::key_enum k, bool isMinor)
383 		{
384 			type=t;
385 			key=k;
386 			minor = isMinor;
387 			begin_tick=-1;
388 			source_event=NULL;
389 			source_part=NULL;
390 		}
391 
FloItem(typeEnum t)392 		FloItem(typeEnum t)
393 		{
394 			type=t;
395 
396 			already_grouped=false;
397 			tied=false;
398 			shift=0;
399 			ausweich=false;
400 			is_tie_dest=false;
401 			begin_tick=-1;
402 			source_event=NULL;
403 			source_part=NULL;
404 		}
405 
FloItem()406 		FloItem()
407 		{
408 			already_grouped=false;
409 			tied=false;
410 			shift=0;
411 			ausweich=false;
412 			is_tie_dest=false;
413 			begin_tick=-1;
414 			source_event=NULL;
415 			source_part=NULL;
416 		}
417 
418 		bool operator==(const FloItem& that)
419 		{
420 			if (this->type != that.type) return false;
421 
422 			switch(type)
423 			{
424 				case NOTE:
425 				case REST:
426 				case NOTE_END:
427 				case REST_END:
428 					return (this->pos == that.pos);
429 
430 				//the following may only occur once in a set
431 				//so we don't search for "the time signature with 4/4
432 				//at t=0", but only for "some time signature at t=0"
433 				//that's why true is returned, and not some conditional
434 				//expression
435 				case BAR:
436 				case KEY_CHANGE:
437 				case TIME_SIG:
438 					return true;
439 			}
440 		}
441 };
442 struct floComp
443 {
operatorfloComp444 	bool operator() (const pair<unsigned, FloEvent>& a, const pair<unsigned, FloEvent>& b )
445 	{
446 		if (a.first < b.first) return true;
447 		if (a.first > b.first) return false;
448 
449 		if (a.second.type<b.second.type) return true;
450 		if (a.second.type>b.second.type) return false;
451 
452 		return (a.second.pitch<b.second.pitch);
453 	}
operatorfloComp454 	bool operator() (const FloItem& a, const FloItem& b )
455 	{
456 		if (a.type < b.type) return true;
457 		if (a.type > b.type) return false;
458 
459 		switch(a.type)
460 		{
461 			case FloItem::NOTE:
462 			case FloItem::REST:
463 			case FloItem::NOTE_END:
464 			case FloItem::REST_END:
465 				return (a.pos < b.pos);
466 
467 			//the following may only occur once in a set
468 			//so we don't search for "the time signature with 4/4
469 			//at t=0", but only for "some time signature at t=0"
470 			//that's why true is returned, and not some conditional
471 			//expression
472 			case FloItem::BAR:
473 			case FloItem::KEY_CHANGE:
474 			case FloItem::TIME_SIG:
475 				return false;
476 		}
477 		return (a.pos < b.pos);
478 	}
479 };
480 
481 typedef set< pair<unsigned, FloEvent>, floComp > ScoreEventList;
482 typedef map< unsigned, set<FloItem, floComp> > ScoreItemList;
483 
484 enum clef_t
485 {
486 	VIOLIN,
487 	BASS
488 };
489 
490 
491 struct note_len_t
492 {
493 	int len;
494 	int dots;
495 
note_len_tnote_len_t496 	note_len_t(int l, int d)
497 	{
498 		len=l; dots=d;
499 	}
500 
note_len_tnote_len_t501 	note_len_t(int l)
502 	{
503 		len=l; dots=0;
504 	}
505 };
506 
507 
508 struct cumulative_t
509 {
510 	int count;
511 	int cumul;
512 
cumulative_tcumulative_t513 	cumulative_t()
514 	{
515 		count=0;
516 		cumul=0;
517 	}
518 
addcumulative_t519 	void add(int v)
520 	{
521 		count++;
522 		cumul+=v;
523 	}
524 
meancumulative_t525 	float mean()
526 	{
527 		return (float)cumul/count;
528 	}
529 };
530 
531 #define DEFAULT (NUM_PARTCOLORS)
532 #define HIGHLIGHTED_PIXMAP (NUM_PARTCOLORS + 1)
533 #define SELECTED_PIXMAP (NUM_PARTCOLORS + 2)
534 #define NUM_MYCOLORS (NUM_PARTCOLORS + 3 + 128)
535 #define VELO_PIXMAP_BEGIN (NUM_PARTCOLORS + 3)
536 
537 struct timesig_t
538 {
539 	int num;
540 	int denom;
541 };
542 
543 enum staff_type_t
544 {
545 	NORMAL,
546 	GRAND_TOP,
547 	GRAND_BOTTOM
548 };
549 
550 enum staff_mode_t
551 {
552 	MODE_TREBLE,
553 	MODE_BASS,
554 	MODE_BOTH
555 };
556 
557 struct staff_t
558 {
559 	set<const MusECore::Part*> parts;
560 	set<int> part_indices;
561 	ScoreEventList eventlist;
562 	ScoreItemList itemlist;
563 
564 	int y_top;
565 	int y_draw;
566 	int y_bottom;
567 
568 	int min_y_coord;
569 	int max_y_coord;
570 
571 	staff_type_t type;
572 	clef_t clef;
573 
574 	ScoreCanvas* parent;
575 
576 	void create_appropriate_eventlist();
577 	void create_itemlist();
578 	void process_itemlist();
579 	void calc_item_pos();
580 
581 	void apply_lasso(QRect rect, set<const MusECore::Event*>& already_processed);
582 
recalculatestaff_t583 	void recalculate()
584 	{
585 		create_appropriate_eventlist();
586 		create_itemlist();
587 		process_itemlist();
588 		calc_item_pos();
589 	}
590 
staff_tstaff_t591 	staff_t(ScoreCanvas* parent_)
592 	{
593 		type=NORMAL;
594 		clef=VIOLIN;
595 		parent=parent_;
596 	}
597 
staff_tstaff_t598 	staff_t (ScoreCanvas* parent_, staff_type_t type_, clef_t clef_, set<const MusECore::Part*> parts_)
599 	{
600 		type=type_;
601 		clef=clef_;
602 		parts=parts_;
603 		parent=parent_;
604 		update_part_indices();
605 	}
606 
607 	bool cleanup_parts();
608 
609 	set<const MusECore::Part*> parts_at_tick(unsigned tick);
610 
611 	void read_status(MusECore::Xml& xml);
612 	void write_status(int level, MusECore::Xml& xml) const;
613 
614 	void update_parts(); //re-populates the set<MusECore::Part*> from the set<int>
615 	void update_part_indices(); //re-populates the set<int> from the set<MusECore::Part*>
616 };
617 
618 list<int> calc_accidentials(MusECore::key_enum key, clef_t clef, MusECore::key_enum next_key=MusECore::KEY_C);
619 note_pos_t note_pos_(int note, MusECore::key_enum key);
620 note_pos_t note_pos (unsigned note, MusECore::key_enum key, clef_t clef);
621 
622 int calc_len(int l, int d);
623 list<note_len_t> parse_note_len(int len_ticks, int begin_tick, vector<int>& foo, bool allow_dots=true, bool allow_normal=true);
624 
625 int clef_height(clef_t clef);
626 
627 
628 int calc_timesig_width(int num, int denom);
629 int calc_number_width(int n);
630 
631 
632 class ScoreCanvas : public MusEGui::View
633 {
634 	Q_OBJECT
635 	private:
636         void init_pixmaps();
637 		static void draw_pixmap(QPainter& p, int x, int y, const QPixmap& pm);
638 		static void draw_tie (QPainter& p, int x1, int x4, int yo, bool up=true, QColor color=Qt::black);
639 		static void draw_akkolade (QPainter& p, int x, int y);
640 
641 		static void draw_accidentials(QPainter& p, int x, int y_offset, const list<int>& acc_list, const QPixmap& pix);
642 
643 		static void draw_timesig(QPainter& p, int x, int y_offset, int num, int denom);
644 
645 		static void draw_number(QPainter& p, int x, int y, int n);
646 
647 
648 
649 
650 
651 		static int height_to_pitch(int h, clef_t clef, MusECore::key_enum key);
652 		static int height_to_pitch(int h, clef_t clef);
653 		static int y_to_height(int y);
654 		int y_to_pitch(int y, int t, clef_t clef);
655 
656 
657 
658 
659 		void draw_note_lines(QPainter& p, int y, bool reserve_akkolade_space=false);
660 		void draw_preamble(QPainter& p, int y, clef_t clef, bool reserve_akkolade_space=false, bool with_akkolade=false);
661 		void draw_items(QPainter& p, int y, staff_t& staff, ScoreItemList::iterator from_it, ScoreItemList::iterator to_it);
662 		void draw_items(QPainter& p, int y, staff_t& staff, int x1, int x2);
663 		void draw_items(QPainter& p, int y, staff_t& staff);
664 		void calc_pos_add_list();
665 
666 
667 		void recalc_staff_pos();
668 		list<staff_t>::iterator staff_at_y(int y);
669 
670 
671 
672 		bool need_redraw_for_hilighting(ScoreItemList::iterator from_it, ScoreItemList::iterator to_it);
673 		bool need_redraw_for_hilighting(ScoreItemList& itemlist, int x1, int x2);
674 		bool need_redraw_for_hilighting(ScoreItemList& itemlist);
675 		bool need_redraw_for_hilighting();
676 
677 
678 		void set_staffmode(list<staff_t>::iterator it, staff_mode_t mode);
679 		void remove_staff(list<staff_t>::iterator it);
680 		void merge_staves(list<staff_t>::iterator dest, list<staff_t>::iterator src);
681 		void move_staff_above(list<staff_t>::iterator dest, list<staff_t>::iterator src);
682 		void move_staff_below(list<staff_t>::iterator dest, list<staff_t>::iterator src);
683 		void cleanup_staves();
684 		void maybe_close_if_empty();
685 
686         QMenu* toolContextMenu();
687         void callContextMenu();
688 
689 // defaults  ----------------------------------------------------------
690 	public:
691 		enum coloring_mode_t {COLOR_MODE_BLACK, COLOR_MODE_PART, COLOR_MODE_VELO};
692 		static int _quant_power2_init;
693 		static int _pixels_per_whole_init;
694 		static int note_velo_init, note_velo_off_init;
695 		static int new_len_init;
696 		static coloring_mode_t coloring_mode_init;
697 		static bool preamble_contains_timesig_init;
698 		static bool preamble_contains_keysig_init;
699 
700 // member variables ---------------------------------------------------
701 	private:
702 		int _quant_power2;
703 		int _pixels_per_whole;
704 
705 		int note_velo;
706 		int note_velo_off;
707 
708 		std::map<int,int> pos_add_list;
709 
710 		list<staff_t> staves;
711 
712 		MusECore::StepRec* steprec;
713 
714 		// the drawing area is split into a "preamble" containing clef,
715 		// key and time signature, and the "item's area" containing the
716 		// actual items (notes, bars, rests, etc.)
717 		// x_pos is responsible for scrolling. an item with item->x==x_pos
718 		// will be drawn exactly at the left beginning of the item's area
719 		// x_left could also be called "preamble's width". it defines
720 		// where the item's area begins
721 		// when multiple note systems are drawn into one window, the
722 		// preamble's length is the same for each system
723 		int x_pos;
724 		int x_left;
725 
726 		int y_pos;
727 
728 		//for mouse-scrolling
729 		float x_scroll_speed;
730 		float x_scroll_pos;
731 		float y_scroll_speed;
732 		float y_scroll_pos;
733 
734 		const MusECore::Part* selected_part;
735 		int selected_part_index;
736 
737 		int last_len;
738 		int new_len; //when zero or negative, last_len is used
739 
740 		Qt::KeyboardModifiers keystate;
741 		QPoint mouse_down_pos;
742 		bool mouse_down;
743 		enum operation_t
744 		{
745 			NO_OP=0,
746 			BEGIN=1,
747 			LENGTH=2,
748 			PITCH=3
749 		};
750 		operation_t mouse_operation;
751 		operation_t mouse_x_drag_operation;
752 		bool mouse_erases_notes;
753 		bool mouse_inserts_notes;
754 
755 		bool inserting;
756 		bool dragging;
757 		bool drag_cursor_changed;
758   const MusECore::Part* dragged_event_part;
759 		int dragged_event_part_index;
760 		MusECore::Event dragged_event;
761 		MusECore::Event original_dragged_event;
762 		const MusECore::Event* clicked_event_ptr;
763 
764 		int old_pitch;
765 		unsigned old_dest_tick;
766 		int old_len;
767 
768 		bool have_lasso;
769 		QPoint lasso_start;
770 		QRect lasso;
771 
772 		bool undo_started;
773 		bool temp_undo;
774 
775 		bool srec;
776 		bool held_notes[128];
777 
778 		coloring_mode_t coloring_mode;
779 		bool preamble_contains_keysig;
780 		bool preamble_contains_timesig;
781 
782 
783 		//menu stuff
784 		QAction* staffmode_treble_action;
785 		QAction* staffmode_bass_action;
786 		QAction* staffmode_both_action;
787 		QAction* remove_staff_action;
788 
789 		QMenu* staff_menu;
790 		list<staff_t>::iterator current_staff;
791 		bool dragging_staff;
792 
793         QCursor active_tool_cursor;
794         int active_tool;
795 
796 	private slots:
797 		void staffmode_treble_slot();
798 		void staffmode_bass_slot();
799 		void staffmode_both_slot();
800 		void remove_staff_slot();
801 
802 		void play_changed(bool);
803 
804 		void deselect_all();
805 		void midi_note(int pitch, int velo);
806 
807 		void add_new_parts(const std::map< const MusECore::Part*, std::set<const MusECore::Part*> >&);
808 
809 	public slots:
810 		void x_scroll_event(int);
811 		void y_scroll_event(int);
812 		void song_changed(MusECore::SongChangedStruct_t);
813 		void fully_recalculate();
814 		void goto_tick(int,bool);
815 		void pos_changed(int i, unsigned u, bool b);
816 		void heartbeat_timer_event();
817 		void config_changed();
818 
819 		void set_tool(int);
820 		void set_quant(int);
821 		void menu_command(int);
822 		void preamble_keysig_slot(bool);
823 		void preamble_timesig_slot(bool);
824 		void set_pixels_per_whole(int);
825 
826 		void set_velo(int);
827 		void set_velo_off(int);
828 
829 		void set_steprec(bool);
830 
831 		void update_parts(); //re-populates the set<MusECore::Part*>s from the set<int>s
832 	signals:
833 		void xscroll_changed(int);
834 		void yscroll_changed(int);
835 		void viewport_width_changed(int);
836 		void canvas_width_changed(int);
837 		void preamble_width_changed(int);
838 		void viewport_height_changed(int);
839 		void canvas_height_changed(int);
840 		void pixels_per_whole_changed(int);
841 		void pos_add_changed();
842 
843 	protected:
844 		virtual void draw(QPainter& p, const QRect& rect, const QRegion& = QRegion());
845 		ScoreEdit* parent;
846 
847 		virtual void mousePressEvent (QMouseEvent* event);
848 		virtual void mouseMoveEvent (QMouseEvent* event);
849 		virtual void mouseReleaseEvent (QMouseEvent* event);
850 		virtual void resizeEvent(QResizeEvent*);
851 
852 	public:
853 		ScoreCanvas(ScoreEdit*, QWidget*);
854 		~ScoreCanvas();
855 
856 		void add_staves(MusECore::PartList* pl, bool all_in_one);
push_back_staff(staff_t & staff)857 		void push_back_staff(staff_t& staff) { staves.push_back(staff); } //FINDMICH dirty. very dirty.
858 
859 		int canvas_width();
860 		int canvas_height();
861 		int viewport_width();
862 		int viewport_height();
863 
quant_power2()864 		int quant_power2() { return _quant_power2; }
quant_len()865 		int quant_len() { return (1<<_quant_power2); }
quant_ticks()866 		int quant_ticks() { return TICKS_PER_WHOLE / (1<<_quant_power2); }
pixels_per_whole()867 		int pixels_per_whole() { return _pixels_per_whole; }
note_x_indent()868 		int note_x_indent() { return pixels_per_whole()/quant_len()/2; }
869 
get_last_len()870 		int get_last_len() {return last_len;}
set_last_len(int l)871 		void set_last_len(int l) {last_len=l;}
872 
get_selected_part()873 		const MusECore::Part* get_selected_part() const {return selected_part;}
set_selected_part(const MusECore::Part * p)874 		void set_selected_part(const MusECore::Part* p) {selected_part=p; if (selected_part) selected_part_index=selected_part->sn();}
get_dragged_event_part()875 		const MusECore::Part* get_dragged_event_part() const {return dragged_event_part;}
set_dragged_event_part(const MusECore::Part * p)876   void set_dragged_event_part(const MusECore::Part* p) {dragged_event_part=p; if (dragged_event_part) dragged_event_part_index=dragged_event_part->sn();}
877 
878 		set<const MusECore::Part*> get_all_parts();
879 
880 		void write_staves(int level, MusECore::Xml& xml) const;
881 
882 		timesig_t timesig_at_tick(int t);
883 		MusECore::KeyEvent key_at_tick(int t);
884 		int tick_to_x(int t);
885 		int delta_tick_to_delta_x(int t);
886 		int x_to_tick(int x);
887 		int calc_posadd(int t);
888 
889 
890 		bool itemsAreSelected() const;
891 		// Appends given tag list with item objects according to options. Avoids duplicate events or clone events.
892 		// Special: We 'abuse' a controller event's length, normally 0, to indicate visual item length.
893 		void tagItems(MusECore::TagEventList* tag_list, const MusECore::EventTagOptionsStruct& options) const;
894 };
895 
896 int calc_measure_len(const list<int>& nums, int denom);
897 vector<int> create_emphasize_list(const list<int>& nums, int denom);
898 vector<int> create_emphasize_list(int num, int denom);
899 
900 } // namespace MusEGui
901 
902 #endif
903 
904