diff options
author | Florian Jung <flo@windfisch.org> | 2012-05-28 14:15:52 +0000 |
---|---|---|
committer | Florian Jung <flo@windfisch.org> | 2012-05-28 14:15:52 +0000 |
commit | d2a88cfaad5ac385fc3c6212c09ad7fbc38e9454 (patch) | |
tree | 387da0b38255003e1a971629ea0de32273ac3d3c /muse2/muse/arranger | |
parent | 716f5a5b56a3b7ff59004ef0a1af5f98cb2a691c (diff) |
merged with release_2_0
Diffstat (limited to 'muse2/muse/arranger')
-rw-r--r-- | muse2/muse/arranger/arranger.cpp | 151 | ||||
-rw-r--r-- | muse2/muse/arranger/arranger.h | 5 | ||||
-rw-r--r-- | muse2/muse/arranger/arrangerview.cpp | 2 | ||||
-rw-r--r-- | muse2/muse/arranger/arrangerview.h | 3 | ||||
-rw-r--r-- | muse2/muse/arranger/pcanvas.cpp | 262 | ||||
-rw-r--r-- | muse2/muse/arranger/pcanvas.h | 9 | ||||
-rw-r--r-- | muse2/muse/arranger/tlist.cpp | 33 | ||||
-rw-r--r-- | muse2/muse/arranger/tlist.h | 2 |
8 files changed, 248 insertions, 219 deletions
diff --git a/muse2/muse/arranger/arranger.cpp b/muse2/muse/arranger/arranger.cpp index 55275ddc..29e69582 100644 --- a/muse2/muse/arranger/arranger.cpp +++ b/muse2/muse/arranger/arranger.cpp @@ -23,7 +23,7 @@ #include "config.h" #include <stdio.h> -#include <values.h> +#include <limits.h> #include <QComboBox> #include <QGridLayout> @@ -73,7 +73,7 @@ namespace MusEGui { std::vector<Arranger::custom_col_t> Arranger::custom_columns; //FINDMICH TODO: eliminate all usage of new_custom_columns std::vector<Arranger::custom_col_t> Arranger::new_custom_columns; //and instead let the arranger update without restarting muse! -QString Arranger::header_state; +QByteArray Arranger::header_state; void Arranger::writeCustomColumns(int level, MusECore::Xml& xml) { @@ -211,7 +211,7 @@ Arranger::Arranger(ArrangerView* parent, const char* name) selected = 0; showTrackinfoFlag = true; - cursVal = MAXINT; + cursVal = INT_MAX; parentWin=parent; @@ -372,10 +372,44 @@ Arranger::Arranger(ArrangerView* parent, const char* name) ib->setFocusPolicy(Qt::NoFocus); connect(ib, SIGNAL(toggled(bool)), SLOT(showTrackInfo(bool))); - list=NULL; - header=NULL; - tgrid=NULL; - updateTListHeader(); + // set up the header + header = new Header(tracklist, "header"); + header->setFixedHeight(30); + + QFontMetrics fm1(header->font()); + int fw = 8; + + header->setColumnLabel(tr("R"), COL_RECORD, fm1.width('R')+fw); + header->setColumnLabel(tr("M"), COL_MUTE, fm1.width('M')+fw); + header->setColumnLabel(tr("S"), COL_SOLO, fm1.width('S')+fw); + header->setColumnLabel(tr("C"), COL_CLASS, fm1.width('C')+fw); + header->setColumnLabel(tr("Track"), COL_NAME, 100); + header->setColumnLabel(tr("Port"), COL_OPORT, 60); + header->setColumnLabel(tr("Ch"), COL_OCHANNEL, 30); + header->setColumnLabel(tr("T"), COL_TIMELOCK, fm1.width('T')+fw); + header->setColumnLabel(tr("Automation"), COL_AUTOMATION, 75); + header->setColumnLabel(tr("Clef"), COL_CLEF, 75); + for (unsigned i=0;i<custom_columns.size();i++) + header->setColumnLabel(custom_columns[i].name, COL_CUSTOM_MIDICTRL_OFFSET+i, MAX(fm1.width(custom_columns[i].name)+fw, 30)); + header->setResizeMode(COL_RECORD, QHeaderView::Fixed); + header->setResizeMode(COL_MUTE, QHeaderView::Fixed); + header->setResizeMode(COL_SOLO, QHeaderView::Fixed); + header->setResizeMode(COL_CLASS, QHeaderView::Fixed); + header->setResizeMode(COL_NAME, QHeaderView::Interactive); + header->setResizeMode(COL_OPORT, QHeaderView::Interactive); + header->setResizeMode(COL_OCHANNEL, QHeaderView::Fixed); + header->setResizeMode(COL_TIMELOCK, QHeaderView::Fixed); + header->setResizeMode(COL_AUTOMATION, QHeaderView::Interactive); + header->setResizeMode(COL_CLEF, QHeaderView::Interactive); + for (unsigned i=0;i<custom_columns.size();i++) + header->setResizeMode(COL_CUSTOM_MIDICTRL_OFFSET+i, QHeaderView::Interactive); + + setHeaderToolTips(); + setHeaderWhatsThis(); + header->setMovable (true); + header->restoreState(header_state); + + list = new TList(header, tracklist, "tracklist"); // Do this now that the list is available. @@ -454,17 +488,14 @@ Arranger::Arranger(ArrangerView* parent, const char* name) connect(canvas, SIGNAL(selectTrackBelow()), list, SLOT(selectTrackBelow())); connect(canvas, SIGNAL(horizontalZoomIn()), SLOT(horizontalZoomIn())); connect(canvas, SIGNAL(horizontalZoomOut()), SLOT(horizontalZoomOut())); - if(MusEGlobal::config.smartFocus) - { - connect(lenEntry, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(lenEntry, SIGNAL(escapePressed()), SLOT(focusCanvas())); - connect(globalPitchSpinBox, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(globalPitchSpinBox, SIGNAL(escapePressed()), SLOT(focusCanvas())); - connect(globalTempoSpinBox, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(globalTempoSpinBox, SIGNAL(escapePressed()), SLOT(focusCanvas())); - connect(midiTrackInfo, SIGNAL(returnPressed()), SLOT(focusCanvas())); - connect(midiTrackInfo, SIGNAL(escapePressed()), SLOT(focusCanvas())); - } + connect(lenEntry, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(lenEntry, SIGNAL(escapePressed()), SLOT(focusCanvas())); + connect(globalPitchSpinBox, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(globalPitchSpinBox, SIGNAL(escapePressed()), SLOT(focusCanvas())); + connect(globalTempoSpinBox, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(globalTempoSpinBox, SIGNAL(escapePressed()), SLOT(focusCanvas())); + connect(midiTrackInfo, SIGNAL(returnPressed()), SLOT(focusCanvas())); + connect(midiTrackInfo, SIGNAL(escapePressed()), SLOT(focusCanvas())); //connect(this, SIGNAL(redirectWheelEvent(QWheelEvent*)), canvas, SLOT(redirectedWheelEvent(QWheelEvent*))); connect(list, SIGNAL(redirectWheelEvent(QWheelEvent*)), canvas, SLOT(redirectedWheelEvent(QWheelEvent*))); @@ -517,65 +548,6 @@ Arranger::Arranger(ArrangerView* parent, const char* name) } -void Arranger::updateTListHeader() // TODO FIXME FINDMICHJETZT this doesn't work properly :/ -{ - if (header) - { - header_state=header->getStatus(); - delete header; - } - - header = new Header(tracklist, "header"); - - header->setFixedHeight(30); - - QFontMetrics fm1(header->font()); - int fw = 8; - - header->setColumnLabel(tr("R"), COL_RECORD, fm1.width('R')+fw); - header->setColumnLabel(tr("M"), COL_MUTE, fm1.width('M')+fw); - header->setColumnLabel(tr("S"), COL_SOLO, fm1.width('S')+fw); - header->setColumnLabel(tr("C"), COL_CLASS, fm1.width('C')+fw); - header->setColumnLabel(tr("Track"), COL_NAME, 100); - header->setColumnLabel(tr("Port"), COL_OPORT, 60); - header->setColumnLabel(tr("Ch"), COL_OCHANNEL, 30); - header->setColumnLabel(tr("T"), COL_TIMELOCK, fm1.width('T')+fw); - header->setColumnLabel(tr("Automation"), COL_AUTOMATION, 75); - header->setColumnLabel(tr("Clef"), COL_CLEF, 75); - for (unsigned i=0;i<custom_columns.size();i++) - header->setColumnLabel(custom_columns[i].name, COL_CUSTOM_MIDICTRL_OFFSET+i, MAX(fm1.width(custom_columns[i].name)+fw, 30)); - header->setResizeMode(COL_RECORD, QHeaderView::Fixed); - header->setResizeMode(COL_MUTE, QHeaderView::Fixed); - header->setResizeMode(COL_SOLO, QHeaderView::Fixed); - header->setResizeMode(COL_CLASS, QHeaderView::Fixed); - header->setResizeMode(COL_NAME, QHeaderView::Interactive); - header->setResizeMode(COL_OPORT, QHeaderView::Interactive); - header->setResizeMode(COL_OCHANNEL, QHeaderView::Fixed); - header->setResizeMode(COL_TIMELOCK, QHeaderView::Fixed); - header->setResizeMode(COL_AUTOMATION, QHeaderView::Interactive); - header->setResizeMode(COL_CLEF, QHeaderView::Interactive); - for (unsigned i=0;i<custom_columns.size();i++) - header->setResizeMode(COL_CUSTOM_MIDICTRL_OFFSET+i, QHeaderView::Interactive); - - setHeaderToolTips(); - setHeaderWhatsThis(); - header->setMovable (true); - header->setStatus(header_state); - - if (list) - { - list->setHeader(header); - connect(header, SIGNAL(sectionResized(int,int,int)), list, SLOT(redraw())); - connect(header, SIGNAL(sectionMoved(int,int,int)), list, SLOT(redraw())); - connect(header, SIGNAL(sectionMoved(int,int,int)), this, SLOT(headerMoved())); - } - - if (tgrid) - { - tgrid->wadd(2, header); - } -} - // DELETETHIS 20 //--------------------------------------------------------- // updateHScrollRange @@ -602,7 +574,7 @@ void Arranger::updateTListHeader() // TODO FIXME FINDMICHJETZT this doesn't work void Arranger::setTime(unsigned tick) { - if (tick == MAXINT) + if (tick == INT_MAX) cursorPos->setEnabled(false); else { cursVal = tick; @@ -651,8 +623,11 @@ void Arranger::configChanged() void Arranger::focusCanvas() { - canvas->setFocus(); - canvas->activateWindow(); + if(MusEGlobal::config.smartFocus) + { + canvas->setFocus(); + canvas->activateWindow(); + } } //--------------------------------------------------------- @@ -696,7 +671,7 @@ void Arranger::songChanged(int type) if(type & SC_SONG_TYPE) setMode(MusEGlobal::song->mtype()); - if(type & SC_SELECTION) // TEST p4.0.36 Try this alone, may need more. + if(type & (SC_SELECTION | SC_TRACK_INSERTED | SC_TRACK_REMOVED | SC_TRACK_MODIFIED)) trackSelectionChanged(); // Keep this light, partsChanged is a heavy move! TEST p4.0.36 Try these, may need more. @@ -771,8 +746,7 @@ void Arranger::modeChange(int mode) { MusEGlobal::song->setMType(MType(mode)); updateTrackInfo(-1); - if(MusEGlobal::config.smartFocus) - focusCanvas(); + focusCanvas(); } //--------------------------------------------------------- @@ -807,7 +781,7 @@ void Arranger::writeConfiguration(int level, MusECore::Xml& xml) { xml.tag(level++, "arranger"); writeCustomColumns(level, xml); - xml.strTag(level, "tlist_header", header->getStatus()); + xml.strTag(level, "tlist_header", header->saveState().toHex().constData()); xml.etag(level, "arranger"); } @@ -826,7 +800,7 @@ void Arranger::readConfiguration(MusECore::Xml& xml) return; case MusECore::Xml::TagStart: if (tag == "tlist_header") - header_state = xml.parse1(); + header_state = QByteArray::fromHex(xml.parse1().toAscii()); else if (tag == "custom_columns") readCustomColumns(xml); else @@ -894,8 +868,7 @@ void Arranger::_setRaster(int index) // Set the audio record part snapping. MusEGlobal::song->setArrangerRaster(_raster); canvas->redraw(); - if(MusEGlobal::config.smartFocus) - focusCanvas(); + focusCanvas(); } //--------------------------------------------------------- @@ -1199,8 +1172,8 @@ void Arranger::updateTrackInfo(int flags) } if (selected->isMidiTrack()) { switchInfo(1); - // If a new part was selected, and only if it's different. - if((flags & SC_SELECTION) && midiTrackInfo->track() != selected) + // If a different part was selected + if(midiTrackInfo->track() != selected) // Set a new track and do a complete update. midiTrackInfo->setTrack(selected); else diff --git a/muse2/muse/arranger/arranger.h b/muse2/muse/arranger/arranger.h index 8873e2af..e51ec068 100644 --- a/muse2/muse/arranger/arranger.h +++ b/muse2/muse/arranger/arranger.h @@ -112,7 +112,7 @@ class ScrollBar : public QScrollBar { class Arranger : public QWidget { Q_OBJECT - static QString header_state; + static QByteArray header_state; int _quant, _raster; PartCanvas* canvas; @@ -167,7 +167,6 @@ class Arranger : public QWidget { void verticalScrollSetYpos(unsigned); void horizontalZoomIn(); void horizontalZoomOut(); - void focusCanvas(); signals: void editPart(MusECore::Track*); @@ -188,7 +187,7 @@ class Arranger : public QWidget { void updateTrackInfo(int flags); void configChanged(); void controllerChanged(MusECore::Track *t); - void updateTListHeader(); + void focusCanvas(); public: enum { CMD_CUT_PART, CMD_COPY_PART, CMD_COPY_PART_IN_RANGE, CMD_PASTE_PART, CMD_PASTE_CLONE_PART, diff --git a/muse2/muse/arranger/arrangerview.cpp b/muse2/muse/arranger/arrangerview.cpp index da510c0e..57c12d15 100644 --- a/muse2/muse/arranger/arrangerview.cpp +++ b/muse2/muse/arranger/arrangerview.cpp @@ -352,7 +352,7 @@ ArrangerView::ArrangerView(QWidget* parent) connect(cb, SIGNAL(dataChanged()), SLOT(clipboardChanged())); connect(cb, SIGNAL(selectionChanged()), SLOT(clipboardChanged())); - MusEGlobal::muse->topwinMenuInited(this); + finalizeInit(); // work around for probable QT/WM interaction bug. // for certain window managers, e.g xfce, this window is diff --git a/muse2/muse/arranger/arrangerview.h b/muse2/muse/arranger/arrangerview.h index 98e7f01c..570dcd80 100644 --- a/muse2/muse/arranger/arrangerview.h +++ b/muse2/muse/arranger/arrangerview.h @@ -39,7 +39,7 @@ #include <QByteArray> #include <QToolButton> -#include <values.h> +#include <limits.h> #include "noteinfo.h" #include "cobject.h" #include "event.h" @@ -139,6 +139,7 @@ class ArrangerView : public TopWin void selectionChanged(); void updateShortcuts(); void updateVisibleTracksButtons(); + virtual void focusCanvas() { arranger->focusCanvas(); } public: ArrangerView(QWidget* parent = 0); diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index f3e71916..cc23b59b 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -25,7 +25,7 @@ #include <sys/stat.h> #include <sys/mman.h> #include <errno.h> -#include <values.h> +#include <limits.h> #include <uuid/uuid.h> #include <math.h> #include <map> @@ -80,6 +80,8 @@ NPart::NPart(MusECore::Part* e) : CItem(MusECore::Event(), e) leftBorderTouches = false; rightBorderTouches = false; + _serial=e->sn(); + int y = track()->y(); setPos(QPoint(e->tick(), y)); setBBox(QRect(e->tick(), y, e->lenTick(), track()->height())); @@ -155,7 +157,7 @@ int PartCanvas::pitch2y(int p) const void PartCanvas::leaveEvent(QEvent*) { - emit timeChanged(MAXINT); + emit timeChanged(INT_MAX); } //--------------------------------------------------------- @@ -215,7 +217,7 @@ void PartCanvas::viewMouseDoubleClickEvent(QMouseEvent* event) emit dclickPart(((NPart*)(curItem))->track()); } } - // + // double click creates new part between left and // right mark @@ -226,7 +228,7 @@ void PartCanvas::viewMouseDoubleClickEvent(QMouseEvent* event) int y = event->y(); for (it = tl->begin(); it != tl->end(); ++it) { int h = (*it)->height(); - if (y >= yy && y < (yy + h)) + if (y >= yy && y < (yy + h) && (*it)->isVisible()) break; yy += h; } @@ -395,7 +397,7 @@ bool PartCanvas::moveItem(MusECore::Undo& operations, CItem* item, const QPoint& // But just in case we ever have two different lists... dpart->events()->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it // so we must decrement it first :/ - spart->events()->incARef(1); // the later MusEGlobal::song->applyOperationGroup() will decrement it + spart->events()->incARef(1); // the later MusEGlobal::song->applyOperationGroup() will decrement it // so we must increment it first :/ dpart->setSelected(spart->selected()); // These will increment ref count if not a clone, and will chain clones... @@ -444,23 +446,24 @@ void PartCanvas::songIsClearing() void PartCanvas::partsChanged() { int sn = -1; - if (curItem) sn=curItem->part()->sn(); - curItem=NULL; + if (curItem) sn=static_cast<NPart*>(curItem)->serial(); + curItem=NULL; items.clearDelete(); for (MusECore::iTrack t = tracks->begin(); t != tracks->end(); ++t) { + if ((*t)->isVisible()) //ignore parts from hidden tracks + { MusECore::PartList* pl = (*t)->parts(); for (MusECore::iPart i = pl->begin(); i != pl->end(); ++i) { MusECore::Part* part = i->second; NPart* np = new NPart(part); items.add(np); - if (np->part()->sn() == sn) + if (np->serial() == sn) curItem=np; - if (i->second->selected()) { + if (i->second->selected()) selectItem(np, true); - } // Check for touching borders. p4.0.29 MusECore::Part* pp; @@ -476,10 +479,11 @@ void PartCanvas::partsChanged() if(pp->tick() == part->endTick()) np->rightBorderTouches = true; } - } } - redraw(); + } } + redraw(); +} //--------------------------------------------------------- // updateSelection @@ -868,10 +872,10 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt) // viewMousePressEvent //--------------------------------------------------------- -void PartCanvas::mousePress(QMouseEvent* event) +bool PartCanvas::mousePress(QMouseEvent* event) { if (event->modifiers() & Qt::ControlModifier) { - return; + return true; } QPoint pt = event->pos(); CItem* item = items.find(pt); @@ -900,10 +904,26 @@ void PartCanvas::mousePress(QMouseEvent* event) } } case AutomationTool: - if (automation.controllerState != doNothing) - automation.moveController=true; - break; + if (event->button() & Qt::RightButton) { + QMenu *automationMenu = new QMenu(this); + QAction* act; + act = automationMenu->addAction(tr("Remove selected")); + act = automationMenu->exec(event->globalPos()); + if (act && automation.currentTrack) { + foreach(int frame, automation.currentCtrlFrameList) + MusEGlobal::audio->msgEraseACEvent((MusECore::AudioTrack*)automation.currentTrack, + automation.currentCtrlList->id(), frame); + } + + } + else { + if (automation.controllerState != doNothing) + automation.moveController=true; + } + return false; + break; } + return true; } //--------------------------------------------------------- @@ -3317,11 +3337,9 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) //-------------------------------- MusECore::TrackList* tl = MusEGlobal::song->tracks(); - //int yy = 0; int yy = -rmapy(yorg) - ypos; int th; for (MusECore::iTrack it = tl->begin(); it != tl->end(); ++it) { - //if (yy > y + h) if (yy > my + mh) break; MusECore::Track* track = *it; @@ -3331,9 +3349,7 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) if (MusEGlobal::config.canvasShowGrid && (track->isMidiTrack() || track->type() == MusECore::Track::WAVE)) // Tim. { p.setPen(baseColor.dark(130)); - //p.drawLine(x, yy + th, x + w, yy + th); p.drawLine(mx, yy + th, mx + mw, yy + th); - //p.setPen(baseColor); } // The update rectangle (rect and mr etc) is clipped at x<0 and y<0 in View::pdraw(). @@ -3346,26 +3362,10 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) // does NOT depend on the update rectangle (except to check intersection). That's why this issue // does not show up there. Should probably try to make that routine more efficient, just like here. Tim. p4.0.30 QRect r(mx, yy, mw, th); - //if(r.intersects(mr)) DELETETHIS { if (!track->isMidiTrack() && (track->type() != MusECore::Track::WAVE)) { - //QRect r = rect & QRect(x, yy, w, track->height()); drawAudioTrack(p, mr, r, (MusECore::AudioTrack*)track); - //p.setPen(baseColor); - } - - // DELETETHIS 13 - // This was redundant drawing. Not required, done via drawTopItem in Canvas::draw - /* - //p.setWorldMatrixEnabled(true); - //if (!track->isMidiTrack()) { // draw automation - if (!track->isMidiTrack() && (track->type() != MusECore::Track::WAVE)) { - //QRect r = rect & QRect(x, yy, w, track->height()); - drawAutomation(p, r, (MusECore::AudioTrack*)track); - //p.setPen(baseColor); - } - //p.setWorldMatrixEnabled(false); - */ + } } yy += th; } @@ -3378,8 +3378,7 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) //--------------------------------------------------------- void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) { - //QRect mr = p.transform().mapRect(rect); // Gives inconsistent positions. Source shows wrong operation for our needs. - QRect mr = map(rect); // Use our own map instead. + QRect mr = map(rect); int mx = mr.x(); int my = mr.y(); @@ -3396,7 +3395,6 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) int yy = yoff; int th; for (MusECore::iTrack it = tl->begin(); it != tl->end(); ++it) { - //if (yy > y + h) DELETETHIS if (yy > my + mh) break; MusECore::Track* track = *it; @@ -3404,15 +3402,12 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) if (!th) continue; if (!track->isMidiTrack()) { // draw automation - //QRect r = rect & QRect(x, yy, w, track->height()); DELETETHIS QRect r(mx, yy, mw, th); if(r.intersects(mr)) { drawAutomation(p, r, (MusECore::AudioTrack*)track); - //p.setPen(baseColor); DELETETHIS } } - //yy += track->height(); DELETETHIS yy += th; } @@ -3631,13 +3626,25 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra //p.drawRect(mapx(MusEGlobal::tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5); //p.drawRect(mapx(MusEGlobal::tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-1)-prevVal*height-2, 3, 3); pen2.setColor((automation.currentCtrlValid && automation.currentCtrlList == cl && - automation.currentCtrlFrame == ic->second.frame) ? + automation.currentCtrlFrameList.contains(ic->second.frame)) ? Qt::white : cl->color()); p.setPen(pen2); p.drawRect(xpixel-2, ypixel-2, 5, 5); oldX = xpixel; oldY = ypixel; + if (automation.currentCtrlValid && automation.currentCtrlList == cl && + automation.currentCtrlFrameList.contains(ic->second.frame) && + automation.currentCtrlFrameList.size() == 1) { + double val = ic->second.val; + QRect textRect = rr; + textRect.setX(xpixel + 20); + textRect.setY(ypixel); + if (cl->valueType() == MusECore::VAL_LOG) { + val = MusECore::fast_log10(ic->second.val) * 20.0; + } + p.drawText(textRect, QString("Value: %1").arg(val)); + } } } if (xpixel <= rr.right()) @@ -3648,6 +3655,42 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra } } +//--------------------------------------------------------- +// checkIfOnLine +// check if our point is on the line defined by +// by first/last X/Y +//--------------------------------------------------------- + +bool checkIfOnLine(double mouseX, double mouseY, double firstX, double lastX, double firstY, double lastY, int circumference) +{ + double proportion = (mouseX-firstX)/(lastX-firstX); + + // 10 X(15) 20 + // proportion = 0.5 + // 10 + // / + // Y(5) + // / + // 1 + double calcY = (lastY-firstY)*proportion+firstY; + if(ABS(calcY-mouseY) < circumference || (lastX == firstX && ABS(mouseX-lastX) < circumference)) + return true; + return false; +} + +//--------------------------------------------------------- +// checkIfNearPoint +//--------------------------------------------------------- + +bool checkIfNearPoint(int mouseX, int mouseY, int eventX, int eventY, int circumference) +{ + int x1 = ABS(mouseX - eventX) ; + int y1 = ABS(mouseY - eventY); + if (x1 < circumference && y1 < circumference) { + return true; + } + return false; +} //--------------------------------------------------------- // checkAutomation @@ -3660,22 +3703,22 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, MusECore::AudioTra // controller added. //--------------------------------------------------------- -void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, bool addNewCtrl) +void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, bool NOTaddNewCtrl) { if (t->isMidiTrack()) return; - int currY; + int mouseY; int trackY = t->y(); int trackH = t->height(); { int y = pointer.y(); if(y < trackY || y >= (trackY + trackH)) return; - currY = mapy(y); } + mouseY = mapy(y); } - int currX = mapx(pointer.x()); - int circumference = 5; + int mouseX = mapx(pointer.x()); + int circumference = 10; MusECore::CtrlListList* cll = ((MusECore::AudioTrack*) t)->controller(); for(MusECore::CtrlListList::iterator icll =cll->begin();icll!=cll->end();++icll) @@ -3686,15 +3729,15 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo } MusECore::iCtrl ic=cl->begin(); - int oldX = mapx(0); - int xpixel = oldX; - int oldY = -1; - int ypixel = oldY; + int eventOldX = mapx(0); + int eventX = eventOldX; + int eventOldY = -1; + int eventY = eventOldY; double min, max; cl->range(&min,&max); bool discrete = cl->mode() == MusECore::CtrlList::DISCRETE; - // First check that there IS automation, ic == cl->end means no automation + // First check that there IS automation for this controller, ic == cl->end means no automation if (ic == cl->end()) { double y; @@ -3704,93 +3747,65 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo } else y = (cl->curVal() - min)/(max-min); // we need to set curVal between 0 and 1 - ypixel = oldY = mapy(trackY+trackH-1 - 2 - y * trackH); + eventY = eventOldY = mapy(trackY+trackH-1 - 2 - y * trackH); } - else + else // we have automation, loop through it { for (; ic !=cl->end(); ic++) { double y = ic->second.val; if (cl->valueType() == MusECore::VAL_LOG ) { // use db scale for volume - y = logToVal(y, min, max); // represent volume between 0 and 1 + y = logToVal(y, min, max); // represent volume between 0 and 1 if (y < 0) y = 0; } else y = (y-min)/(max-min); // we need to set curVal between 0 and 1 - ypixel = mapy(trackY + trackH - 2 - y * trackH); - xpixel = mapx(MusEGlobal::tempomap.frame2tick(ic->second.frame)); + eventY = mapy(trackY + trackH - 2 - y * trackH); + eventX = mapx(MusEGlobal::tempomap.frame2tick(ic->second.frame)); - if (oldY==-1) oldY = ypixel; + if (eventOldY==-1) eventOldY = eventY; - bool foundIt=false; - if (addNewCtrl) { - double firstX=oldX; - double lastX=xpixel; - double firstY=oldY; - double lastY = discrete ? oldY : ypixel; - - double proportion = (currX-firstX)/(lastX-firstX); - - if((currX < oldX) || (currX > lastX) || (firstX==lastX) ) - { - oldX = xpixel; - oldY = ypixel; - continue; // not the right region - } - - // 10 X(15) 20 - // proportion = 0.5 - // 10 - // / - // Y(5) - // / - // 1 - double calcY = (lastY-firstY)*proportion+firstY; - if(ABS(calcY-currY) < circumference || (xpixel == oldX && ABS(currX-xpixel) < circumference)) - foundIt=true; - - } else { - int x1 = ABS(currX - xpixel) ; - int y1 = ABS(currY - ypixel); - if (x1 < circumference && y1 < circumference && pointer.x() > 0 && pointer.y() > 0) { - foundIt=true; - } - - } - oldX = xpixel; - oldY = ypixel; - - if (foundIt) { - QWidget::setCursor(Qt::CrossCursor); - if (addNewCtrl) { - //automation.currentCtrl = 0; + //if (addNewCtrl) { + bool onLine = checkIfOnLine(mouseX, mouseY, eventOldX,eventX, eventOldY, discrete? eventOldY:eventY, circumference); + bool onPoint = false; + if ( pointer.x() > 0 && pointer.y() > 0) + onPoint = checkIfNearPoint(mouseX, mouseY, eventX, eventY, circumference); + + eventOldX = eventX; + eventOldY = eventY; + + if (onLine) { + if (!onPoint) { + QWidget::setCursor(Qt::CrossCursor); automation.currentCtrlValid = false; automation.controllerState = addNewController; }else { - automation.currentCtrlFrame = ic->second.frame; + QWidget::setCursor(Qt::OpenHandCursor); + automation.currentCtrlFrameList.clear(); + automation.currentCtrlFrameList.append(ic->second.frame); automation.currentCtrlValid = true; automation.controllerState = movingController; } automation.currentCtrlList = cl; automation.currentTrack = t; + update(); return; } } } - if (addNewCtrl) { - // check if we are reasonably close to a line, we only need to check Y - // as the line is straight after the last controller - //printf("post oldX:%d oldY:%d xpixel:%d ypixel:%d currX:%d currY:%d\n", oldX, oldY, xpixel, ypixel, currX, currY); - if(currX >= xpixel && ypixel == oldY && ABS(currY-ypixel) < circumference) { - QWidget::setCursor(Qt::CrossCursor); - automation.controllerState = addNewController; - automation.currentCtrlList = cl; - automation.currentTrack = t; - automation.currentCtrlValid = false; - return; - } + // we are now after the last existing controller + // check if we are reasonably close to a line, we only need to check Y + // as the line is straight after the last controller + //printf("post oldX:%d oldY:%d xpixel:%d ypixel:%d currX:%d currY:%d\n", oldX, oldY, xpixel, ypixel, currX, currY); + if(mouseX >= eventX && eventY == eventOldY && ABS(mouseY-eventY) < circumference) { + QWidget::setCursor(Qt::CrossCursor); + automation.controllerState = addNewController; + automation.currentCtrlList = cl; + automation.currentTrack = t; + automation.currentCtrlValid = false; + return; } } // if there are no hits we default to clearing all the data @@ -3798,6 +3813,7 @@ void PartCanvas::checkAutomation(MusECore::Track * t, const QPoint &pointer, boo automation.currentCtrlValid = false; automation.currentCtrlList = 0; automation.currentTrack = 0; + automation.currentCtrlFrameList.clear(); setCursor(); } @@ -3820,10 +3836,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) } // automation.moveController is set, lets rock. - int prevFrame = 0; int nextFrame = -1; - int currFrame = 0; if (automation.controllerState == addNewController) { @@ -3835,7 +3849,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) for (; ic !=automation.currentCtrlList->end(); ++ic) { MusECore::CtrlVal &cv = ic->second; if (cv.frame == frame) { - automation.currentCtrlFrame = cv.frame; + automation.currentCtrlFrameList.clear(); + automation.currentCtrlFrameList.append(cv.frame); automation.currentCtrlValid = true; automation.controllerState = movingController; break; @@ -3849,9 +3864,9 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) for (; ic !=automation.currentCtrlList->end(); ++ic) { MusECore::CtrlVal &cv = ic->second; - if (cv.frame == automation.currentCtrlFrame) + if (automation.currentCtrlFrameList.contains(cv.frame)) { - currFrame = cv.frame; + //currFrame = cv.frame; break; } prevFrame = cv.frame; @@ -3885,7 +3900,7 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) automation.currentCtrlList->range(&min,&max); double cvval; if (automation.currentCtrlList->valueType() == MusECore::VAL_LOG ) { // use db scale for volume - printf("log conversion val=%f min=%f max=%f\n", yfraction, min, max); + //printf("log conversion val=%f min=%f max=%f\n", yfraction, min, max); cvval = valToLog(yfraction, min, max); if (cvval< min) cvval=min; if (cvval>max) cvval=max; @@ -3900,7 +3915,8 @@ void PartCanvas::processAutomationMovements(QPoint pos, bool addPoint) if (cvval>max) cvval=max; } - automation.currentCtrlFrame = newFrame; + automation.currentCtrlFrameList.clear(); + automation.currentCtrlFrameList.append(newFrame); automation.currentCtrlValid = true; if(icc != automation.currentCtrlList->end()) diff --git a/muse2/muse/arranger/pcanvas.h b/muse2/muse/arranger/pcanvas.h index 7882ee5c..ab227eb2 100644 --- a/muse2/muse/arranger/pcanvas.h +++ b/muse2/muse/arranger/pcanvas.h @@ -59,19 +59,24 @@ class MidiEditor; //--------------------------------------------------------- class NPart : public CItem { + protected: + int _serial; + public: NPart(MusECore::Part* e); const QString name() const { return part()->name(); } void setName(const QString& s) { part()->setName(s); } MusECore::Track* track() const { return part()->track(); } + int serial() { return _serial; } bool leftBorderTouches; // Whether the borders touch other part borders. bool rightBorderTouches; + }; enum ControllerVals { doNothing, movingController, addNewController }; struct AutomationObject { - int currentCtrlFrame; + QList<int> currentCtrlFrameList; bool currentCtrlValid; MusECore::CtrlList *currentCtrlList; MusECore::Track *currentTrack; @@ -99,7 +104,7 @@ class PartCanvas : public Canvas { AutomationObject automation; virtual void keyPress(QKeyEvent*); - virtual void mousePress(QMouseEvent*); + virtual bool mousePress(QMouseEvent*); virtual void mouseMove(QMouseEvent* event); virtual void mouseRelease(const QPoint&); virtual void viewMouseDoubleClickEvent(QMouseEvent*); diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp index be997504..3d831ba9 100644 --- a/muse2/muse/arranger/tlist.cpp +++ b/muse2/muse/arranger/tlist.cpp @@ -34,6 +34,7 @@ #include <QWheelEvent> #include <QIcon> #include <QSpinBox> +#include <QToolTip> #include "popupmenu.h" #include "globals.h" @@ -164,6 +165,38 @@ void TList::redraw(const QRect& r) update(r); } + +//--------------------------------------------------------- +// event +//--------------------------------------------------------- + +bool TList::event(QEvent *event) +{ + if (event->type() == QEvent::ToolTip) { + QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event); + MusECore::TrackList* l = MusEGlobal::song->tracks(); + int idx = 0; + int yy = -ypos; + for (MusECore::iTrack i = l->begin(); i != l->end(); ++idx, yy += (*i)->height(), ++i) { + MusECore::Track* track = *i; + MusECore::Track::TrackType type = track->type(); + int trackHeight = track->height(); + if (trackHeight==0) // not visible + continue; + if (helpEvent->pos().y() > yy && helpEvent->pos().y() < yy + trackHeight) { + if (type == MusECore::Track::AUDIO_SOFTSYNTH) { + MusECore::SynthI *s = (MusECore::SynthI*)track; + QToolTip::showText(helpEvent->globalPos(),track->name() + " : " + s->synth()->description()); + } + else + QToolTip::showText(helpEvent->globalPos(),track->name()); + } + } + return true; + } + return QWidget::event(event); +} + //--------------------------------------------------------- // paint //--------------------------------------------------------- diff --git a/muse2/muse/arranger/tlist.h b/muse2/muse/arranger/tlist.h index ff25f16c..d3701451 100644 --- a/muse2/muse/arranger/tlist.h +++ b/muse2/muse/arranger/tlist.h @@ -115,6 +115,8 @@ class TList : public QWidget { void setHeaderToolTips(); PopupMenu* colorMenu(QColor c, int id, QWidget* parent); + protected: + bool event(QEvent *); private slots: void maybeUpdateVolatileCustomColumns(); // updates AFFECT_CPOS-columns when and only when the hwState has changed void returnPressed(); |