diff options
author | Robert Jonsson <spamatica@gmail.com> | 2009-12-27 11:30:35 +0000 |
---|---|---|
committer | Robert Jonsson <spamatica@gmail.com> | 2009-12-27 11:30:35 +0000 |
commit | b703eab295330e6f81564fbb39a10a1a2fdd2f54 (patch) | |
tree | e46b5c9a6bc22fd661c15d1d2123f5bf631cef80 /muse_qt4_evolution/muse/ctrl/ctrleditor.cpp | |
parent | 5d5fa0fdf913907edbc3d2d29a7548f0cb658c94 (diff) |
moved old qt4 branch
Diffstat (limited to 'muse_qt4_evolution/muse/ctrl/ctrleditor.cpp')
-rw-r--r-- | muse_qt4_evolution/muse/ctrl/ctrleditor.cpp | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/muse_qt4_evolution/muse/ctrl/ctrleditor.cpp b/muse_qt4_evolution/muse/ctrl/ctrleditor.cpp new file mode 100644 index 00000000..cc89c4c6 --- /dev/null +++ b/muse_qt4_evolution/muse/ctrl/ctrleditor.cpp @@ -0,0 +1,492 @@ +//============================================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// Copyright (C) 2002-2006 by Werner Schweer and others +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#include "ctrleditor.h" +#include "track.h" +#include "awl/tcanvas.h" +#include "ctrl.h" +#include "midictrl.h" +#include "gconfig.h" +#include "song.h" +#include "part.h" +#include "tools.h" +#include "muse.h" +#include "gui.h" + +static const int HANDLE1 = 6; +static const int HANDLE2 = 3; +static const int veloWidth = 3; + +Ctrl veloList(CTRL_VELOCITY, "velocity", Ctrl::DISCRETE |Ctrl::INT, 0.0, 127.0); // dummy +Ctrl sveloList(CTRL_SVELOCITY, "single velocity", Ctrl::DISCRETE |Ctrl::INT, 0.0, 127.0); // dummy + +//--------------------------------------------------------- +// CtrlEditor +//--------------------------------------------------------- + +CtrlEditor::CtrlEditor() + { + _drawCtrlName = false; + dragy = -1; + lselected = 0; + singlePitch = -1; + drawRuler = false; + } + +//--------------------------------------------------------- +// drawHandle +//--------------------------------------------------------- + +inline static void drawHandle(QPainter& p, int x, int y, int lselected) + { + p.fillRect(x-HANDLE2, y-HANDLE2, HANDLE1, HANDLE1, + x == lselected ? Qt::red : Qt::yellow); + } + +//--------------------------------------------------------- +// ctrlY +//--------------------------------------------------------- + +int CtrlEditor::ctrlY(int x, const CVal& val) const + { + if (dragy != -1 && lselected == x) + return dragy; + return ctrl()->val2pixelR(val, th) + HANDLE2; + } + +//--------------------------------------------------------- +// paint +//--------------------------------------------------------- + +void CtrlEditor::paint(QPainter& p, const QRect& r) + { + if (!ctrl()) + return; + int from = r.x() - HANDLE1; + if (from < 0) + from = 0; + int to = r.x() + r.width() + HANDLE1; + th = cheight() - HANDLE1 + splitWidth; + + p.save(); + bool aR = track()->autoRead(); + p.setPen(QPen(aR ? Qt::white : Qt::gray, 2)); + + TType tt = track()->timeType(); + + if (ctrl()->id() == CTRL_VELOCITY) { + p.setRenderHint(QPainter::Antialiasing, false); + p.setPen(QPen(Qt::blue, veloWidth)); + PartList* pl = track()->parts(); + for (iPart ip = pl->begin(); ip != pl->end(); ++ip) { + Part* part = ip->second; + int pos1 = tc()->pos2pix(*part); + int pos2 = tc()->pos2pix(part->end()); + + if (pos2 <= from) + continue; + if (pos1 > to) + break; + + EventList* events = part->events(); + for (iEvent e = events->begin(); e != events->end(); ++e) { + const Event& ev = e->second; + if (ev.type() != Note) + continue; + int pos = tc()->pos2pix(ev.pos() + *part); + if (pos <= from) + continue; + if (pos > to) + break; + int id = ctrl()->id(); + if (id == CTRL_VELOCITY || + (id == CTRL_SVELOCITY && ev.pitch() == singlePitch)) { + int y1 = ctrl()->val2pixelR(ev.velo(), th+3) + 1; + p.drawLine(pos, th+3, pos, y1); + } + } + } + } + else { + p.setRenderHint(QPainter::Antialiasing, true); + if (ctrl()->empty()) { + if (aR) { + int y = ctrl()->cur2pixel(th) + HANDLE2; + p.drawLine(r.x(), y, r.x() + r.width(), y); + } + } + else { + int x1, y1, x2, y2; + int hx = -1; + int hy = 0; + + Pos pos1 = tc()->pix2pos(from); + ciCtrlVal i = ctrl()->lowerBound(pos1.time(tt)); + + if (i == ctrl()->end()) { + --i; + int x = tc()->pos2pix(Pos(i.key(), tt)); + int y = ctrlY(x, i.value()); + p.drawLine(r.x(), y, r.x() + r.width(), y); + } + else { + if (i == ctrl()->begin()) { + x1 = tc()->pos2pix(Pos(i.key(), tt)); + y1 = ctrlY(x1, i.value()); + x1 = r.x(); + } + else { + --i; + x1 = tc()->pos2pix(Pos(i.key(), tt)); + y1 = ctrlY(x1, i.value()); + hx = x1; + hy = y1; + ++i; + } + do { + x2 = tc()->pos2pix(Pos(i.key(), tt)); + y2 = ctrlY(x2, i.value()); + if (ctrl()->type() & Ctrl::DISCRETE) { + p.drawLine(x1, y1, x2, y1); + p.drawLine(x2, y1, x2, y2); + } + else + p.drawLine(x1, y1, x2, y2); + if (x2 >= to) + break; + if (hx != -1) + drawHandle(p, hx, hy, lselected); + hx = x2; + hy = y2; + x1 = x2; + y1 = y2; + ++i; + } while (i != ctrl()->end()); + if (x2 < to) + p.drawLine(x2, y1, to, y1); + if (hx != -1) + drawHandle(p, hx, hy, lselected); + } + } + if (!aR) { + int y = ctrl()->cur2pixel(th) + HANDLE2; + p.drawLine(r.x(), y, r.x() + r.width(), y); + } + } + + if (drawRuler) { + p.setPen(QPen(Qt::white, 2)); + p.setRenderHint(QPainter::Antialiasing, true); + p.drawLine(ruler1, ruler2); + } + // + // this does not work well a.t.m: + // + if (_drawCtrlName) { + QString s(ctrl()->name()); + QFont f(tc()->font()); +// p.setFont(config.fonts[3]); + p.setPen(Qt::black); + QFontMetrics fm(f); + int ly = fm.lineSpacing() + 2; + p.drawText(2, ly, s); + } + p.restore(); + } + +//--------------------------------------------------------- +// mousePress +//--------------------------------------------------------- + +void CtrlEditor::mousePress(const QPoint& pos, QMouseEvent* me) + { + int button = me->button(); + Qt::KeyboardModifiers modifiers = me->modifiers(); + Tool tool = tc()->tool(); + if (button & Qt::RightButton) { + QMenu pop(tc()); + QAction* a; + for (int i = 0; i < TOOLS; ++i) { + int id = 1 << i; + if ((arrangerTools & id) == 0) + continue; + a = getAction(toolList[i], &pop); + pop.addAction(a); + a->setCheckable(true); + if (id == (int)tool) + a->setChecked(true); + } + a = pop.addSeparator(); + a = pop.addAction("List Editor"); + a->setData(1 << (TOOLS+1)); + + a = pop.exec(me->globalPos()); + if (a) { + int n = a->data().toInt(); + if (n == (1 << (TOOLS+1))) { + Pos t(tc()->pix2pos(pos.x())); + muse->showListEditor(t, track(), 0, ctrl()); + } + else + muse->setTool(n); + } + return; + } + + int wh = cheight(); + int y = pos.y(); + int x = pos.x(); + + int cid = ctrl()->id(); + + if (tool == PencilTool || (modifiers & Qt::ShiftModifier)) { + selected = tc()->pix2pos(x); + lselected = x; + dragy = y; + dragx = x; + dragYoffset = 0; + if (cid == CTRL_VELOCITY || cid == CTRL_SVELOCITY) + song->startUndo(); + else { + // add controller: + CVal val = ctrl()->pixel2val(dragy-HANDLE2, wh - HANDLE1 + splitWidth); + song->cmdAddControllerVal(track(), ctrl(), selected, val); + tc()->widget()->update(); + } + } + else if (tool == PointerTool || tool == RubberTool) { + if (cid == CTRL_VELOCITY || cid == CTRL_SVELOCITY) { + dragx = x; + song->startUndo(); + return; + } + + Pos pos1(tc()->pix2pos(x - HANDLE2)); + Pos pos2(tc()->pix2pos(x + HANDLE2)); + + TType tt = track()->timeType(); + ciCtrlVal s = ctrl()->upperBound(pos1.time(tt)); + ciCtrlVal e = ctrl()->upperBound(pos2.time(tt)); + for (ciCtrlVal i = s; i != e; ++i) { + int yy = ctrl()->val2pixelR(i.value(), wh - HANDLE1 + splitWidth) + HANDLE2; + startY = yy; + if ((yy >= (y-HANDLE2)) && (yy < (y + HANDLE2))) { + if (tt == AL::TICKS) + selected.setTick(i.key()); + else + selected.setFrame(i.key()); + lselected = tc()->pos2pix(selected); + if (tool == RubberTool || button == Qt::RightButton + || modifiers & Qt::ControlModifier) { + song->cmdRemoveControllerVal(track(), ctrl()->id(), i.key()); + dragy = -1; + } + else { + dragy = yy; + dragYoffset = dragy - y; + } + tc()->widget()->update(); + break; + } + } + } + else if (tool == DrawTool) { + ruler1 = ruler2 = pos; + drawRuler = true; + } + } + +//--------------------------------------------------------- +// mouseRelease +//--------------------------------------------------------- + +void CtrlEditor::mouseRelease() + { + if (tc()->tool() == DrawTool) { + song->startUndo(); + drawRuler = false; + int from, to, y1, y2; + if (ruler1.x() > ruler2.x()) { + from = ruler2.x(); + to = ruler1.x(); + y1 = ruler2.y(); + y2 = ruler1.y(); + } + else { + from = ruler1.x(); + to = ruler2.x(); + y1 = ruler1.y(); + y2 = ruler2.y(); + } + MidiController::ControllerType type = midiControllerType(ctrl()->id()); + if (type == MidiController::Velo) { + PartList* pl = track()->parts(); + for (iPart ip = pl->begin(); ip != pl->end(); ++ip) { + Part* part = ip->second; + int pos1 = tc()->pos2pix(*part); + int pos2 = tc()->pos2pix(part->end()); + + if (pos2 <= from) + continue; + if (pos1 > to) + break; + + EventList* events = part->events(); + for (iEvent e = events->begin(); e != events->end(); ++e) { + if (e->second.type() != Note) + continue; + int pos = tc()->pos2pix(e->second.pos() + *part); + if (pos <= from) + continue; + if (pos > to) + break; + int id = ctrl()->id(); + if (id == CTRL_VELOCITY || + (CTRL_SVELOCITY && e->second.pitch() == singlePitch)) { + int y = y1 + (y2 - y1) * (pos - from) / (to - from); + int val = (ctrl()->pixel2val(y+HANDLE2, cheight()-HANDLE1+splitWidth)).i; + Event clone = e->second.clone(); + clone.setB(val); + song->changeEvent(e->second, clone, part); + song->undoOp(UndoOp::ModifyEvent, clone, e->second, part); + } + } + } + } + else { + printf("ctrleditor:: not implemented\n"); + } + song->endUndo(SC_EVENT_MODIFIED); + tc()->widget()->update(); + return; + } + if (ctrl()->id() == CTRL_VELOCITY || ctrl()->id() == CTRL_SVELOCITY) + song->endUndo(SC_EVENT_MODIFIED); + else { + if (dragy != -1 && dragy != startY) { + int wh = cheight() + splitWidth - HANDLE1; + CVal val = ctrl()->pixel2val(dragy - HANDLE2, wh); + // modify controller: + song->cmdAddControllerVal(track(), ctrl(), selected, val); + } + dragy = -1; + } + } + +//--------------------------------------------------------- +// mouseMove +// called only with mouse button pressed +//--------------------------------------------------------- + +void CtrlEditor::mouseMove(const QPoint& pos) + { + Tool tool = tc()->tool(); + int cid = ctrl()->id(); + + if (tool == DrawTool) { + ruler2 = pos; + tc()->widget()->update(); + return; + } + if (cid == CTRL_VELOCITY || cid == CTRL_SVELOCITY) { + AL::Pos p1(tc()->pix2pos(dragx)); + AL::Pos p2(tc()->pix2pos(pos.x())); + dragx = pos.x(); + + int wh = cheight() - HANDLE1 + splitWidth; + int val = (ctrl()->pixel2val(pos.y() - HANDLE2, wh)).i; + unsigned tick1 = p1.tick(); + Part* part = track()->parts()->findPart(tick1); + if (part == 0) + return; + unsigned tick2 = p2.tick(); + if (tick1 > tick2) { + int tmp = tick2; + tick2 = tick1; + tick1 = tmp; + } + if (part->tick() > tick1) + tick1 = 0; + else + tick1 -= part->tick(); // event time is relative to part + if (part->tick() > tick2) + tick2 = 0; + else + tick2 -= part->tick(); + + // + // change velocity for all notes at tick time + // + EventList* el = part->events(); + EventList tel; + for (iEvent ie = el->lower_bound(tick1); ie != el->lower_bound(tick2); ie++) { + Event e = ie->second; + if (!e.isNote() || e.dataB() == val) + continue; + tel.add(e); + } + for (iEvent ie = tel.begin(); ie != tel.end(); ++ie) { + Event e = ie->second; + Event clone = e.clone(); + clone.setB(val); + song->changeEvent(e, clone, part); + song->undoOp(UndoOp::ModifyEvent, clone, e, part); + } + } + else { + if (tool == RubberTool) { + int wh = cheight(); + int y = pos.y(); + int x = pos.x(); + + Pos pos1(tc()->pix2pos(x - HANDLE2)); + Pos pos2(tc()->pix2pos(x + HANDLE2)); + + TType tt = track()->timeType(); + ciCtrlVal s = ctrl()->upperBound(pos1.time(tt)); + ciCtrlVal e = ctrl()->upperBound(pos2.time(tt)); + for (ciCtrlVal i = s; i != e; ++i) { + int yy = ctrl()->val2pixelR(i.value(), wh); + startY = yy; + if ((yy >= (y-HANDLE2)) && (yy < (y + HANDLE2))) { + if (tt == AL::TICKS) + selected.setTick(i.key()); + else + selected.setFrame(i.key()); + lselected = tc()->pos2pix(selected); + song->cmdRemoveControllerVal(track(), ctrl()->id(), i.key()); + dragy = -1; + break; + } + } + } + if (dragy != -1) { + int th = cheight() + splitWidth - HANDLE2 - 1; + dragy = pos.y() + dragYoffset; + if (dragy < HANDLE2) + dragy = HANDLE2; + else if (dragy > th) { + dragy = th; + } + } + } + tc()->widget()->update(); + } + |