From 6ddc310885d4dc3dfd2bdea44c2f6f1568fbd6bb Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Thu, 19 May 2011 16:02:25 +0000 Subject: added a modified MTScale to the score editor --- muse2/muse/midiedit/prcanvas.h | 2 +- muse2/muse/midiedit/scoreedit.cpp | 38 +++-- muse2/muse/midiedit/scoreedit.h | 20 ++- muse2/muse/widgets/CMakeLists.txt | 2 + muse2/muse/widgets/mtscale_flo.cpp | 325 +++++++++++++++++++++++++++++++++++++ muse2/muse/widgets/mtscale_flo.h | 51 ++++++ 6 files changed, 414 insertions(+), 24 deletions(-) create mode 100644 muse2/muse/widgets/mtscale_flo.cpp create mode 100644 muse2/muse/widgets/mtscale_flo.h diff --git a/muse2/muse/midiedit/prcanvas.h b/muse2/muse/midiedit/prcanvas.h index 6995bdbe..a04ca514 100644 --- a/muse2/muse/midiedit/prcanvas.h +++ b/muse2/muse/midiedit/prcanvas.h @@ -42,7 +42,7 @@ class PianoCanvas : public EventCanvas { int playedPitch; QTimer* chordTimer; - int chordTimer_setToTick; + unsigned chordTimer_setToTick; Q_OBJECT virtual void viewMouseDoubleClickEvent(QMouseEvent*); diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index 46fa1914..dccac615 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -170,9 +170,10 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos) apply_velo=false; - score_canvas=new ScoreCanvas(this, mainw, 1, 1); + score_canvas=new ScoreCanvas(this, mainw); xscroll = new QScrollBar(Qt::Horizontal, mainw); yscroll = new QScrollBar(Qt::Vertical, mainw); + time_bar = new MTScaleFlo(score_canvas, mainw); connect(xscroll, SIGNAL(valueChanged(int)), score_canvas, SLOT(x_scroll_event(int))); connect(score_canvas, SIGNAL(xscroll_changed(int)), xscroll, SLOT(setValue(int))); @@ -187,9 +188,14 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos) connect(song, SIGNAL(songChanged(int)), score_canvas, SLOT(song_changed(int))); - mainGrid->addWidget(score_canvas, 0, 0); - mainGrid->addWidget(xscroll,1,0); - mainGrid->addWidget(yscroll,0,1); + connect(xscroll, SIGNAL(valueChanged(int)), time_bar, SLOT(set_xpos(int))); + connect(score_canvas, SIGNAL(pos_add_changed()), time_bar, SLOT(pos_add_changed())); + connect(score_canvas, SIGNAL(preamble_width_changed(int)), time_bar, SLOT(set_xoffset(int))); + + mainGrid->addWidget(time_bar, 0,0); + mainGrid->addWidget(score_canvas, 1,0); + mainGrid->addWidget(xscroll,2,0); + mainGrid->addWidget(yscroll,1,1); xscroll->setMinimum(0); yscroll->setMinimum(0); @@ -957,8 +963,7 @@ void ScoreCanvas::add_staves(PartList* pl, bool all_in_one) } -ScoreCanvas::ScoreCanvas(ScoreEdit* pr, QWidget* parent_widget, - int sx, int sy) : View(parent_widget, sx, sy) +ScoreCanvas::ScoreCanvas(ScoreEdit* pr, QWidget* parent_widget) : View(parent_widget, 1, 1) { parent = pr; setFocusPolicy(Qt::StrongFocus); @@ -2667,6 +2672,8 @@ void ScoreCanvas::calc_pos_add_list() curr_key=new_key; } + + emit pos_add_changed(); } void ScoreCanvas::draw_items(QPainter& p, int y, staff_t& staff, int x1, int x2) @@ -3088,7 +3095,10 @@ void ScoreCanvas::draw_preamble(QPainter& p, int y_offset, clef_t clef) if (x_left_old!=x_left) + { emit viewport_width_changed(viewport_width()); + emit preamble_width_changed(x_left); + } } @@ -3206,6 +3216,11 @@ int ScoreCanvas::tick_to_x(int t) return x; } +int ScoreCanvas::delta_tick_to_delta_x(int t) +{ + return t*pixels_per_whole()/TICKS_PER_WHOLE; +} + int ScoreCanvas::calc_posadd(int t) { int result=0; @@ -4205,17 +4220,15 @@ void staff_t::apply_lasso(QRect rect, set& already_processed) * x nothing atm * * IMPORTANT TODO - * o display blue loop markers in score editor - * o transpose: support in-key-transpose - * o drum-loop-editor (like in sq korg ds xD) - * * o add a select-clef-toolbox for tracks * o respect the track's clef (has to be implemented first in muse) * o do partial recalculating; recalculating can take pretty long * (0,5 sec) when displaying a whole song in scores * o transpose etc. must also transpose key-pressure events + * o transpose: support in-key-transpose * * less important stuff + * o controller view in score editor * o quantize-templates (everything is forced into a specified * rhythm) * o part-templates (you specify some notes and a control-chord; @@ -4251,11 +4264,6 @@ void staff_t::apply_lasso(QRect rect, set& already_processed) * msgNewEvent functions (see my e-mail) * * o make quantize and other stuff faster (by assymetric communication) - * - * GUI stuff - * o velocity/release-velo for already existing notes - * - do this by right-click -> some dialog shows up? - * - or by controller graphs, as used by the piano roll */ diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h index c26bdd84..4004452f 100644 --- a/muse2/muse/midiedit/scoreedit.h +++ b/muse2/muse/midiedit/scoreedit.h @@ -31,6 +31,7 @@ #include "gconfig.h" #include "part.h" #include "keyevent.h" +#include "mtscale_flo.h" #include #include @@ -109,6 +110,7 @@ class ScoreEdit : public TopWin QScrollBar* xscroll; QScrollBar* yscroll; ScoreCanvas* score_canvas; + MTScaleFlo* time_bar; QLabel* apply_velo_to_label; bool apply_velo; @@ -583,13 +585,6 @@ class ScoreCanvas : public View void recalc_staff_pos(); list::iterator staff_at_y(int y); - - timesig_t timesig_at_tick(int t); - key_enum key_at_tick(int t); - int tick_to_x(int t); - int x_to_tick(int x); - int calc_posadd(int t); - bool need_redraw_for_hilighting(ScoreItemList::iterator from_it, ScoreItemList::iterator to_it); @@ -722,9 +717,11 @@ class ScoreCanvas : public View void yscroll_changed(int); void viewport_width_changed(int); void canvas_width_changed(int); + void preamble_width_changed(int); void viewport_height_changed(int); void canvas_height_changed(int); void pixels_per_whole_changed(int); + void pos_add_changed(); protected: virtual void draw(QPainter& p, const QRect& rect); @@ -737,7 +734,7 @@ class ScoreCanvas : public View virtual void keyPressEvent(QKeyEvent* event); public: - ScoreCanvas(ScoreEdit*, QWidget*, int, int); + ScoreCanvas(ScoreEdit*, QWidget*); ~ScoreCanvas(){}; void add_staves(PartList* pl, bool all_in_one); @@ -763,6 +760,13 @@ class ScoreCanvas : public View set get_all_parts(); void write_staves(int level, Xml& xml) const; + + timesig_t timesig_at_tick(int t); + key_enum key_at_tick(int t); + int tick_to_x(int t); + int delta_tick_to_delta_x(int t); + int x_to_tick(int x); + int calc_posadd(int t); }; int calc_measure_len(const list& nums, int denom); diff --git a/muse2/muse/widgets/CMakeLists.txt b/muse2/muse/widgets/CMakeLists.txt index 5989df11..7589ddf0 100644 --- a/muse2/muse/widgets/CMakeLists.txt +++ b/muse2/muse/widgets/CMakeLists.txt @@ -53,6 +53,7 @@ QT4_WRAP_CPP (widget_mocs mixdowndialog.h mlabel.h mtscale.h + mtscale_flo.h mtrackinfo.h nentry.h noteinfo.h @@ -149,6 +150,7 @@ file (GLOB widgets_source_files mmath.cpp mtrackinfo.cpp mtscale.cpp + mtscale_flo.cpp nentry.cpp noteinfo.cpp pitchedit.cpp diff --git a/muse2/muse/widgets/mtscale_flo.cpp b/muse2/muse/widgets/mtscale_flo.cpp new file mode 100644 index 00000000..e18a7d11 --- /dev/null +++ b/muse2/muse/widgets/mtscale_flo.cpp @@ -0,0 +1,325 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: mtscale_flo.cpp,v 1.8.2.7 2011/05/19 04:14:01 flo Exp $ +// (C) Copyright 1999 Werner Schweer (ws@seh.de) +//========================================================= + +#include + +#include +#include + +#include "mtscale_flo.h" +#include "song.h" +#include "icons.h" +#include "gconfig.h" +#include "scoreedit.h" + +//--------------------------------------------------------- +// MTScale +// Midi Time Scale +//--------------------------------------------------------- + +MTScaleFlo::MTScaleFlo(ScoreCanvas* parent_editor, QWidget* parent_widget) + : View(parent_widget, 1, 1) + { + setToolTip(tr("bar scale")); + pos[0] = song->cpos(); + pos[1] = song->lpos(); + pos[2] = song->rpos(); + button = Qt::NoButton; + setMouseTracking(true); + connect(song, SIGNAL(posChanged(int, unsigned, bool)), SLOT(setPos(int, unsigned, bool))); + connect(song, SIGNAL(songChanged(int)), SLOT(songChanged(int))); + connect(song, SIGNAL(markerChanged(int)), SLOT(redraw())); + + parent=parent_editor; + + setFixedHeight(28); + setBg(QColor(0xe0, 0xe0, 0xe0)); + } + +//--------------------------------------------------------- +// songChanged +//--------------------------------------------------------- + +void MTScaleFlo::songChanged(int type) + { + if (type & (SC_SIG|SC_TEMPO)) + redraw(); + } + +//--------------------------------------------------------- +// setPos +//--------------------------------------------------------- + +void MTScaleFlo::setPos(int idx, unsigned val, bool) + { + if ((val == MAXINT) || (val == pos[idx])) + return; + + int opos = parent->tick_to_x(pos[idx] == MAXINT ? val : pos[idx]) + xoffset - xpos; + + pos[idx] = val; + +// if (isVisible()) +// redraw(); + if (isVisible()) { + + int tval = parent->tick_to_x(val) + xoffset - xpos; + int x = -9; + int w = 18; + + if (tval < 0) { // tval<0 occurs whenever the window is scrolled left, so I switched to signed int (ml) + redraw(); + } + else if (opos > tval) { + w += opos - tval; + x += tval; + } + else { + w += tval - opos; + x += opos; + } + redraw(QRect(x, 0, w, height())); + } + } + +//--------------------------------------------------------- +// mousePressEvent +//--------------------------------------------------------- + +void MTScaleFlo::mousePressEvent(QMouseEvent* event) + { + button = event->button(); + mouseMoveEvent(event); + } + +//--------------------------------------------------------- +// mouseReleaseEvent +//--------------------------------------------------------- + +void MTScaleFlo::mouseReleaseEvent(QMouseEvent*) + { + button = Qt::NoButton; + } + +//--------------------------------------------------------- +// mouseMoveEvent +//--------------------------------------------------------- + +void MTScaleFlo::mouseMoveEvent(QMouseEvent* event) + { + if (event->modifiers() & Qt::ShiftModifier ) + setCursor(QCursor(Qt::PointingHandCursor)); + else + setCursor(QCursor(Qt::ArrowCursor)); + + int tick = AL::sigmap.raster(parent->x_to_tick(event->x()-xoffset+xpos), parent->quant_ticks()); + if (tick<0) tick=0; + + int i; + switch (button) { + case Qt::LeftButton: + i = 0; + break; + case Qt::MidButton: + i = 1; + break; + case Qt::RightButton: + i = 2; + break; + default: + return; // if no button is pressed the function returns here + } + Pos p(tick, true); + + if(i== 0 && (event->modifiers() & Qt::ShiftModifier )) { // If shift +LMB we add a marker + Marker *alreadyExists = song->getMarkerAt(tick); + if (!alreadyExists) + song->addMarker(QString(""), tick, false); + } + else if (i== 2 && (event->modifiers() & Qt::ShiftModifier )) { // If shift +RMB we remove a marker + Marker *toRemove = song->getMarkerAt(tick); + if (toRemove) + song->removeMarker(toRemove); + else + printf("No marker to remove\n"); + } + else + song->setPos(i, p); // all other cases: relocating one of the locators + } + + + +//--------------------------------------------------------- +// draw +//--------------------------------------------------------- + +void MTScaleFlo::draw(QPainter& p, const QRect& r) + { + int x = r.x(); + int w = r.width(); + + x -= 20; + w += 40; // wg. Text + + //--------------------------------------------------- + // draw Marker + //--------------------------------------------------- + + int y = 12; + p.setPen(Qt::black); + p.setFont(config.fonts[4]); + p.drawLine(r.x(), y+1, r.x() + r.width(), y+1); + QRect tr(r); + tr.setHeight(12); + MarkerList* marker = song->marker(); + for (iMarker m = marker->begin(); m != marker->end(); ++m) { + + int xp = parent->tick_to_x(m->second.tick()) + xoffset - xpos; + if (xp > x+w) + break; + int xe = r.x() + r.width(); + iMarker mm = m; + ++mm; + if (mm != marker->end()) + xe = parent->tick_to_x(mm->first) + xoffset - xpos; + + QRect tr(xp, 0, xe-xp, 13); + + QRect wr = r.intersect(tr); + if(!wr.isEmpty()) + { + if (m->second.current()) + p.fillRect(wr, Qt::white); + + int x2; + if (mm != marker->end()) + x2 = parent->tick_to_x(mm->first) + xoffset - xpos; + else + x2 = xp+200; + + if(xp >= -32) + p.drawPixmap(xp, 0, *flagIconS); + + if(xp >= -1023) + { + QRect r = QRect(xp+10, 0, x2-xp, 12); + p.setPen(Qt::black); + p.drawText(r, Qt::AlignLeft|Qt::AlignVCenter, m->second.name()); + } + + if(xp >= 0) + { + p.setPen(Qt::green); + p.drawLine(xp, y, xp, height()); + } + } + } + + //--------------------------------------------------- + // draw location marker + //--------------------------------------------------- + + int h = height()-12; + + for (int i = 0; i < 3; ++i) { + int xp = parent->tick_to_x(pos[i]) + xoffset - xpos; + if (xp >= x && xp < x+w) { + QPixmap* pm = markIcon[i]; + p.drawPixmap(xp - pm->width()/2, y-1, *pm); + } + } + + + //--------------------------------------------------- + // draw beats + //--------------------------------------------------- + + + p.setPen(Qt::black); + + unsigned ctick; + int bar1, bar2, beat; + unsigned tick; + + ctick = parent->x_to_tick(x - xoffset + xpos); + AL::sigmap.tickValues(ctick, &bar1, &beat, &tick); + AL::sigmap.tickValues(parent->x_to_tick(x+w - xoffset + xpos), &bar2, &beat, &tick); + + + int stick = AL::sigmap.bar2tick(bar1, 0, 0); + int ntick; + for (int bar = bar1; bar <= bar2; bar++, stick = ntick) { + ntick = AL::sigmap.bar2tick(bar+1, 0, 0); + int tpix = parent->delta_tick_to_delta_x(ntick - stick); + if (tpix < 64) { + // don�t show beats if measure is this small + int n = 1; + if (tpix < 32) + n = 2; + if (tpix <= 16) + n = 4; + if (tpix < 8) + n = 8; + if (tpix <= 4) + n = 16; + if (tpix <= 2) + n = 32; + if (bar % n) + continue; + p.setFont(config.fonts[3]); + int x = parent->tick_to_x(stick) + xoffset - xpos; + QString s; + s.setNum(bar + 1); + p.drawLine(x, y+1, x, y+1+h); +// QRect r = QRect(x+2, y, 0, h); + QRect r = QRect(x+2, y, 1000, h); + p.drawText(r, Qt::AlignLeft|Qt::AlignVCenter|Qt::TextDontClip, s); + } + else { + int z, n; + AL::sigmap.timesig(stick, z, n); + for (int beat = 0; beat < z; beat++) { + int xp = parent->tick_to_x(AL::sigmap.bar2tick(bar, beat, 0)) + xoffset - xpos; + QString s; + QRect r(xp+2, y, 1000, h); + int y1; + int num; + if (beat == 0) { + num = bar + 1; + y1 = y + 1; + p.setFont(config.fonts[3]); + } + else { + num = beat + 1; + y1 = y + 7; + p.setFont(config.fonts[1]); + r.setY(y+3); + } + s.setNum(num); + p.drawLine(xp, y1, xp, y+1+h); + p.drawText(r, Qt::AlignLeft|Qt::AlignVCenter|Qt::TextDontClip, s); + } + } + } + } + +void MTScaleFlo::set_xpos(int pos) +{ + xpos=pos; + redraw(); +} + +void MTScaleFlo::set_xoffset(int o) +{ + xoffset=o; + redraw(); +} + +void MTScaleFlo::pos_add_changed() +{ + redraw(); +} diff --git a/muse2/muse/widgets/mtscale_flo.h b/muse2/muse/widgets/mtscale_flo.h new file mode 100644 index 00000000..b7856207 --- /dev/null +++ b/muse2/muse/widgets/mtscale_flo.h @@ -0,0 +1,51 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: mtscale_flo.h,v 1.3 2011/05/19 22:27:06 flo Exp $ +// (C) Copyright 1999 Werner Schweer (ws@seh.de) +//========================================================= + +#ifndef __MTSCALE_FLO_H__ +#define __MTSCALE_FLO_H__ + +#include "view.h" + + +class ScoreCanvas; + +//--------------------------------------------------------- +// MTScaleFlo +// scale for midi track +//--------------------------------------------------------- + +class MTScaleFlo : public View { + Q_OBJECT + unsigned pos[3]; + int button; + ScoreCanvas* parent; + int xpos; + int xoffset; + + private slots: + void songChanged(int); + + protected: + virtual void draw(QPainter&, const QRect&); + virtual void mousePressEvent(QMouseEvent* event); + virtual void mouseMoveEvent(QMouseEvent* event); + virtual void mouseReleaseEvent(QMouseEvent* event); + + signals: + void timeChanged(unsigned); + + public slots: + void setPos(int, unsigned, bool); + void set_xpos(int); + void pos_add_changed(); + void set_xoffset(int); + + public: + MTScaleFlo(ScoreCanvas* parent_editor, QWidget* parent_widget); + }; +#endif + -- cgit v1.2.3