summaryrefslogtreecommitdiff
path: root/muse2/muse/arranger
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2012-05-28 14:15:52 +0000
committerFlorian Jung <flo@windfisch.org>2012-05-28 14:15:52 +0000
commitd2a88cfaad5ac385fc3c6212c09ad7fbc38e9454 (patch)
tree387da0b38255003e1a971629ea0de32273ac3d3c /muse2/muse/arranger
parent716f5a5b56a3b7ff59004ef0a1af5f98cb2a691c (diff)
merged with release_2_0
Diffstat (limited to 'muse2/muse/arranger')
-rw-r--r--muse2/muse/arranger/arranger.cpp151
-rw-r--r--muse2/muse/arranger/arranger.h5
-rw-r--r--muse2/muse/arranger/arrangerview.cpp2
-rw-r--r--muse2/muse/arranger/arrangerview.h3
-rw-r--r--muse2/muse/arranger/pcanvas.cpp262
-rw-r--r--muse2/muse/arranger/pcanvas.h9
-rw-r--r--muse2/muse/arranger/tlist.cpp33
-rw-r--r--muse2/muse/arranger/tlist.h2
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();