summaryrefslogtreecommitdiff
path: root/muse2/muse
diff options
context:
space:
mode:
authorTim E. Real <termtech@rogers.com>2011-08-05 08:28:29 +0000
committerTim E. Real <termtech@rogers.com>2011-08-05 08:28:29 +0000
commite2084952744efe4c6cf9137ba0c544c115064d5f (patch)
treec40c1a49039d86648075970866a20764eae07fa8 /muse2/muse
parent0dbef158d3bf5a96bbd2b4432bcc23223783d3d4 (diff)
Parts having hidden events now drawn using 'jagged' ends and special white edges.
Improved border drawing guaranteed to show L/R touching part borders. TODO: Top and bottom borders. Muted parts now show names and events. Filled with a special brush pattern for easy recognition. Huge changes to PartCanvas::drawItem(). And to all View::XmapXXX methods for better accuracy. Changed bool Part::hasHiddenNotes() to int Part::hasHiddenEvents(). Added int Part::cachedHasHiddenEvents().
Diffstat (limited to 'muse2/muse')
-rw-r--r--muse2/muse/arranger/pcanvas.cpp909
-rw-r--r--muse2/muse/arranger/pcanvas.h6
-rw-r--r--muse2/muse/driver/jack.cpp18
-rw-r--r--muse2/muse/functions.cpp6
-rw-r--r--muse2/muse/midiedit/dcanvas.cpp4
-rw-r--r--muse2/muse/midiedit/prcanvas.cpp6
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp4
-rw-r--r--muse2/muse/part.cpp40
-rw-r--r--muse2/muse/part.h13
-rw-r--r--muse2/muse/steprec.cpp4
-rw-r--r--muse2/muse/widgets/canvas.cpp143
-rw-r--r--muse2/muse/widgets/canvas.h1
-rw-r--r--muse2/muse/widgets/view.cpp178
-rw-r--r--muse2/muse/widgets/view.h5
14 files changed, 1179 insertions, 158 deletions
diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp
index 7298194c..402e8035 100644
--- a/muse2/muse/arranger/pcanvas.cpp
+++ b/muse2/muse/arranger/pcanvas.cpp
@@ -3,6 +3,7 @@
// Linux Music Editor
// $Id: pcanvas.cpp,v 1.48.2.26 2009/11/22 11:08:33 spamatica Exp $
// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+// Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)
//=========================================================
#include <stdio.h>
@@ -43,7 +44,6 @@
#include "midictrl.h"
#include "utils.h"
-
//---------------------------------------------------------
// colorRect
// paints a rectangular icon with a given color
@@ -67,6 +67,9 @@ QIcon colorRect(const QColor& color, int width, int height) {
NPart::NPart(Part* e) : CItem(Event(), e)
{
+ leftBorderTouches = false;
+ rightBorderTouches = false;
+
int th = track()->height();
int y = track()->y();
@@ -416,17 +419,31 @@ QPoint PartCanvas::raster(const QPoint& p) const
void PartCanvas::partsChanged()
{
items.clear();
- int idx = 0;
for (iTrack t = tracks->begin(); t != tracks->end(); ++t) {
PartList* pl = (*t)->parts();
for (iPart i = pl->begin(); i != pl->end(); ++i) {
- NPart* np = new NPart(i->second);
+ Part* part = i->second;
+ NPart* np = new NPart(part);
items.add(np);
if (i->second->selected()) {
selectItem(np, true);
}
- }
- ++idx;
+
+ // Check for touching borders. p4.0.29
+ Part* pp;
+ for(ciPart ii = pl->begin(); ii != pl->end(); ++ii)
+ {
+ pp = ii->second;
+ if(pp == part) // Ignore this part
+ continue;
+ if(pp->tick() > part->endTick())
+ break;
+ if(pp->endTick() == part->tick())
+ np->leftBorderTouches = true;
+ if(pp->tick() == part->endTick())
+ np->rightBorderTouches = true;
+ }
+ }
}
redraw();
}
@@ -1273,6 +1290,7 @@ void PartCanvas::keyPress(QKeyEvent* event)
// draws a part
//---------------------------------------------------------
+#if 0
void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)
{
int from = rect.x();
@@ -1296,84 +1314,215 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)
}
QRect r = item->bbox();
+ bool clone = part->events()->arefCount() > 1;
+ QBrush brush;
- int i = part->colorIndex();
- p.setPen(Qt::black);
- if (part->mute()) {
- QColor c(Qt::white);
+ //QRect rr = map(r);
+ //QRect rr = p.transform().mapRect(r);
+ //printf("PartCanvas::drawItem called map rx:%d rw:%d rrx:%d rrw:%d\n", r.x(), r.width(), rr.x(), rr.width());
+ //printf("PartCanvas::drawItem called map rx:%d rw:%d\n", r.x(), r.width());
+ //p.save();
+ //p.setWorldMatrixEnabled(false);
+
+ // NOTE: Optimization: For each item, hasHiddenEvents() is called once in Canvas::draw(), and we use cachedHasHiddenEvents().
+ // Not used for now.
+ //int het = part->cachedHasHiddenEvents();
+ int het = part->hasHiddenEvents();
+
+ int y_1 = rmapyDev(1); // Hack, try to replace.
+ double xs_0 = r.x();
+ double xe_0 = xs_0 + r.width();
+ double xs_m0 = rmapx_f(xs_0);
+ double xe_m0 = rmapx_f(xe_0);
+ double xs_1 = rmapxDev_f(xs_m0 + 1.0);
+ if(xs_1 > xe_0)
+ xs_1 = xe_0;
+ double xs_2 = rmapxDev_f(xs_m0 + 2.0);
+ if(xs_2 > xe_0)
+ xs_2 = xe_0;
+ double xs_6 = rmapxDev_f(xs_m0 + 6.0);
+ if(xs_6 > xe_0)
+ xs_6 = xe_0;
+
+ double xe_1 = rmapxDev_f(xe_m0 - 1.0);
+ if(xe_1 < xs_0)
+ xe_1 = xs_0;
+ double xe_2 = rmapxDev_f(xe_m0 - 2.0);
+ if(xe_2 < xs_0)
+ xe_2 = xs_0;
+ double xe_6 = rmapxDev_f(xe_m0 - 6.0);
+ if(xe_6 < xs_0)
+ xe_6 = xs_0;
+
+ double ys_0 = r.y();
+ double ye_0 = ys_0 + r.height();
+ double ys_m0 = rmapy_f(ys_0);
+ double ye_m0 = rmapy_f(ye_0);
+ double ys_1 = rmapyDev_f(ys_m0 + 1.0);
+ if(ys_1 > ye_0)
+ ys_1 = ye_0;
+ double ys_2 = rmapyDev_f(ys_m0 + 2.0);
+ if(ys_2 > ye_0)
+ ys_2 = ye_0;
+
+ double ye_1 = rmapyDev_f(ye_m0 - 1.0);
+ if(ye_1 < ys_0)
+ ye_1 = ys_0;
+ double ye_2 = rmapyDev_f(ye_m0 - 2.0);
+ if(ye_2 < ys_0)
+ ye_2 = ys_0;
+
+ int cidx = part->colorIndex();
+ if (item->isMoving())
+ {
+ QColor c(Qt::gray);
c.setAlpha(config.globalAlphaBlend);
QLinearGradient gradient(r.topLeft(), r.bottomLeft());
gradient.setColorAt(0, c);
gradient.setColorAt(1, c.darker());
- QBrush cc(gradient);
- p.setBrush(cc);
-
- // NOTE: For one-pixel border use first line For two-pixel border use second.
- p.drawRect(QRect(r.x(), r.y()-1, r.width(), r.height()));
-
- return;
- }
- if (item->isMoving()) {
- QColor c(Qt::gray);
+ brush = QBrush(gradient);
+ }
+ else
+ if (part->selected())
+ {
+ QColor c(Qt::black);
+ c.setAlpha(config.globalAlphaBlend);
+ QLinearGradient gradient(r.topLeft(), r.bottomLeft());
+ // Use a colour only about 20% lighter than black, rather than the 50% we use in gGradientFromQColor
+ // and is used in darker()/lighter(), so that it is distinguished a bit better from grey non-part tracks.
+ //c.setRgba(64, 64, 64, c.alpha());
+ gradient.setColorAt(0, QColor(51, 51, 51, config.globalAlphaBlend));
+ gradient.setColorAt(1, c);
+ brush = QBrush(gradient);
+ }
+ else
+ if (part->mute())
+ {
+ QColor c(Qt::white);
c.setAlpha(config.globalAlphaBlend);
QLinearGradient gradient(r.topLeft(), r.bottomLeft());
gradient.setColorAt(0, c);
gradient.setColorAt(1, c.darker());
- QBrush cc(gradient);
- p.setBrush(cc);
-
- // NOTE: For one-pixel border use first line. For two-pixel border use second.
- p.drawRect(QRect(r.x(), r.y()-1, r.width(), r.height()));
- }
- else if (part->selected()) {
- bool clone = part->events()->arefCount() > 1;
-
- // NOTE: For one-pixel border use first line and don't bother with setCosmetic.
- // For a two-pixel border use second line and MUST use setCosmetic! Tim.
- //p.setPen(QPen(config.partColors[i], 0, clone ? Qt::DashLine : Qt::SolidLine));
- QPen pen(config.partColors[i], 2, clone ? Qt::DashLine : Qt::SolidLine);
- pen.setCosmetic(true);
-
- p.setPen(pen);
- // Hm, put some kind of lower limit? If so do that globally to the adjustment.
- QColor c(Qt::black);
- c.setAlpha(config.globalAlphaBlend);
-
- QLinearGradient gradient(r.topLeft(), r.bottomLeft());
- //gradient.setColorAt(0, c);
- //gradient.setColorAt(1, c.darker());
- // Use a colour only about 20% lighter than black, rather than the 50% we use in gGradientFromQColor
- // and is used in darker()/lighter(), so that it is distinguished a bit better from grey non-part tracks.
- //c.setRgba(64, 64, 64, c.alpha());
- gradient.setColorAt(0, QColor(51, 51, 51, config.globalAlphaBlend));
- gradient.setColorAt(1, c);
- QBrush cc(gradient);
- //QBrush cc(gGradientFromQColor(c, r.topLeft(), r.bottomLeft()));
+ brush = QBrush(gradient);
- p.setBrush(cc);
- p.drawRect(r);
- }
- else {
- bool clone = part->events()->arefCount() > 1;
-
- // NOTE: Pixel width: See above note.
- //p.setPen(QPen(Qt::black, 0, clone ? Qt::DashLine : Qt::SolidLine));
- QPen pen(Qt::black, 2, clone ? Qt::DashLine : Qt::SolidLine);
- pen.setCosmetic(true);
-
- p.setPen(pen);
- QColor c(config.partColors[i]);
+ // Not good. Aliasing missing lines happening at different mags.
+ // And it's too much. If notes + automation is displayed (by removing 'return' below), cross hatch interferes.
+ // TODO: Maybe try to draw a nice gradient SINGLE cross (or STAR) from corner to corner instead.
+ // Then remove the 'return' below and let it draw the name and notes.
+ //brush.setStyle(Qt::DiagCrossPattern);
+ //p.fillRect(rf, brush);
+ }
+ else
+ {
+ QColor c(config.partColors[cidx]);
c.setAlpha(config.globalAlphaBlend);
- //QLinearGradient gradient(r.topLeft(), r.bottomLeft());
- //gradient.setColorAt(0, c);
- //gradient.setColorAt(1, c.darker());
- //QBrush cc(gradient);
- QBrush cc(gGradientFromQColor(c, r.topLeft(), r.bottomLeft()));
- p.setBrush(cc);
-
- p.drawRect(r);
- }
+ brush = QBrush(gGradientFromQColor(c, r.topLeft(), r.bottomLeft()));
+ }
+ double h = r.height();
+ double s = h / 4.0;
+ double y0 = r.y();
+ double y1 = y0 + s;
+ double y2 = y0 + s * 2.0;
+ double y3 = y0 + s * 3.0;
+ double y4 = y0 + h;
+
+ QPointF points[16];
+ int pts;
+
+ //
+ // Fill the part rectangles, accounting for hidden events by using 'jagged' edges...
+ //
+
+ p.setBrush(brush);
+ p.setPen(Qt::NoPen);
+ if(het)
+ {
+ pts = 0;
+ if(het == (Part::LeftEventsHidden | Part::RightEventsHidden))
+ {
+ points[pts++] = QPointF(xs_0, y0);
+ points[pts++] = QPointF(xe_0, y0);
+ points[pts++] = QPointF(xe_6, y1);
+ points[pts++] = QPointF(xe_0, y2);
+ points[pts++] = QPointF(xe_6, y3);
+ points[pts++] = QPointF(xe_0, y4);
+ points[pts++] = QPointF(xs_0, y4);
+ points[pts++] = QPointF(xs_6, y3);
+ points[pts++] = QPointF(xs_0, y2);
+ points[pts++] = QPointF(xs_6, y1);
+ p.drawConvexPolygon(points, pts); // Help says may be faster on some platforms (X11).
+ }
+ else
+ if(het == Part::LeftEventsHidden)
+ {
+ points[pts++] = QPointF(xs_0, y0);
+ points[pts++] = QPointF(xe_0, y0);
+ points[pts++] = QPointF(xe_0, y4);
+ points[pts++] = QPointF(xs_0, y4);
+ points[pts++] = QPointF(xs_6, y3);
+ points[pts++] = QPointF(xs_0, y2);
+ points[pts++] = QPointF(xs_6, y1);
+ p.drawConvexPolygon(points, pts);
+ }
+ else
+ if(het == Part::RightEventsHidden)
+ {
+ points[pts++] = QPointF(xs_0, y0);
+ points[pts++] = QPointF(xe_0, y0);
+
+ points[pts++] = QPointF(xe_6, y1);
+ points[pts++] = QPointF(xe_0, y2);
+ points[pts++] = QPointF(xe_6, y3);
+ points[pts++] = QPointF(xe_0, y4);
+ points[pts++] = QPointF(xs_0, y4);
+ p.drawConvexPolygon(points, pts);
+ }
+
+ //
+ // Draw remaining 'hidden events' decorations with 'jagged' edges...
+ //
+
+ int part_r, part_g, part_b, brightness, color_brightness;
+ config.partColors[cidx].getRgb(&part_r, &part_g, &part_b);
+ brightness = part_r*29 + part_g*59 + part_b*12;
+ //if ((brightness < 12000 || part->selected()) && !part->mute() && !item->isMoving())
+ // color_brightness=223; // too dark: use lighter color
+ //else
+ // color_brightness=32; // otherwise use dark color
+ if ((brightness >= 12000 && !part->selected()))
+ color_brightness=32; // too light: use dark color
+ else
+ color_brightness=223; // too dark: use lighter color
+ QColor c(color_brightness,color_brightness,color_brightness, config.globalAlphaBlend);
+ p.setBrush(QBrush(gGradientFromQColor(c, r.topLeft(), r.bottomLeft())));
+ //p.setBrush(QBrush(c));
+ if(het & Part::RightEventsHidden)
+ {
+ pts = 0;
+ points[pts++] = QPointF(xe_0, y0);
+ points[pts++] = QPointF(xe_0, y4);
+ points[pts++] = QPointF(xe_6, y3);
+ points[pts++] = QPointF(xe_0, y2);
+ points[pts++] = QPointF(xe_6, y1);
+ p.drawConvexPolygon(points, pts);
+ }
+ if(het & Part::LeftEventsHidden)
+ {
+ pts = 0;
+ points[pts++] = QPointF(xs_0, y0);
+ points[pts++] = QPointF(xs_6, y1);
+ points[pts++] = QPointF(xs_0, y2);
+ points[pts++] = QPointF(xs_6, y3);
+ points[pts++] = QPointF(xs_0, y4);
+ p.drawConvexPolygon(points, pts);
+ }
+ }
+ else
+ {
+ p.fillRect(r, brush);
+ }
+
MidiPart* mp = 0;
WavePart* wp = 0;
Track::TrackType type = part->track()->type();
@@ -1391,40 +1540,602 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)
drawMidiPart(p, rect, mp->events(), (MidiTrack*)part->track(), mp, r, mp->tick(), from, to);
}
+ #if 0
+ //
+ // Now draw the borders...
+ // Works great but requires clones be drawn with the highest priority on top of all other parts, in Canvas::draw.
+ //
+
+ QPen pen(part->selected() ? config.partColors[i] : Qt::black, 2.0, clone ? Qt::DotLine : Qt::SolidLine);
+ pen.setCosmetic(true);
+ p.setPen(pen);
+ p.setBrush(Qt::NoBrush);
+ p.drawRect(r);
+
+ #else
+ //
+ // Now draw the borders, using custom segments...
+ //
+
+ // FIXME NOTE: For 1-pixel wide lines, setting pen style to anything other than solid didn't work out well.
+ // Much too screwy - the single-width lines kept getting shifted one pixel over intermittently.
+ // I tried EVERYTHING to make sure x is proper but the painter keeps shifting them over.
+ // Meanwhile the fills are correct. Seems painter doesn't like line patterns, whether stock or custom.
+ // Therefore I was forced to manually draw the left and right segments.
+ // It works. Which seems to be more proof that painter is handling line patterns and pen widths badly...
+ // DO NOT ERASE COMMENTED CODE BELOW for now, in case it can be fixed. Tim. p4.0.29
+
+ p.setBrush(Qt::NoBrush);
+
+ QColor pc((part->mute() || item->isMoving())? Qt::white : config.partColors[cidx]);
+ QPen penSelect1H(pc);
+ QPen penSelect2H(pc, 2.0);
+ QPen penSelect1V(pc);
+ QPen penSelect2V(pc, 2.0);
+ penSelect1H.setCosmetic(true);
+ penSelect2H.setCosmetic(true);
+ penSelect1V.setCosmetic(true);
+ penSelect2V.setCosmetic(true);
+
+ pc = Qt::black;
+ QPen penNormal1H(pc);
+ QPen penNormal2H(pc, 2.0);
+ QPen penNormal1V(pc);
+ QPen penNormal2V(pc, 2.0);
+ penNormal1H.setCosmetic(true);
+ penNormal2H.setCosmetic(true);
+ penNormal1V.setCosmetic(true);
+ penNormal2V.setCosmetic(true);
+
+ QVector<qreal> customDashPattern;
+ if(clone)
+ {
+ customDashPattern << 4.0 << 8.0;
+ penSelect1H.setDashPattern(customDashPattern);
+ penNormal1H.setDashPattern(customDashPattern);
+ //penSelect1V.setDashPattern(customDashPattern);
+ //penNormal1V.setDashPattern(customDashPattern);
+ customDashPattern.clear();
+ customDashPattern << 2.0 << 4.0;
+ penSelect2H.setDashPattern(customDashPattern);
+ penNormal2H.setDashPattern(customDashPattern);
+ //penSelect2V.setDashPattern(customDashPattern);
+ //penNormal2V.setDashPattern(customDashPattern);
+ }
+
+ pc = Qt::white;
+ QPen penHidden1(pc);
+ QPen penHidden2(pc, 2.0);
+ penHidden2.setCosmetic(true);
+ //customDashPattern.clear();
+ //customDashPattern << 2.0 << 10.0;
+ //penHidden1.setDashPattern(customDashPattern);
+ //customDashPattern.clear();
+ //customDashPattern << 1.0 << 5.0;
+ //penHidden2.setDashPattern(customDashPattern);
+
+ bool lbt = ((NPart*)item)->leftBorderTouches;
+ bool rbt = ((NPart*)item)->rightBorderTouches;
+
+ QLineF l1( lbt?xs_1:xs_0, ys_0, rbt?xe_1:xe_0, ys_0); // Top
+ //QLineF l2(rbt?xe_1:xe_0, r.y() + (rbt?y_1:y_2) - 1, rbt?xe_1:xe_0, r.y() + r.height() - 1); // Right
+ QLineF l3( lbt?xs_1:xs_0, ye_0, rbt?xe_1:xe_0, ye_0); // Bottom
+ //QLineF l4(r.x(), r.y() + (lbt?y_1:y_2), r.x(), r.y() + r.height() - (lbt?y_1:y_2)); // Left
+
+ if(het & Part::RightEventsHidden)
+ p.setPen(((NPart*)item)->rightBorderTouches ? penHidden1 : penHidden2);
+ else
+ {
+ if(((NPart*)item)->rightBorderTouches)
+ p.setPen(part->selected() ? penSelect1V : penNormal1V);
+ else
+ p.setPen(part->selected() ? penSelect2V : penNormal2V);
+ }
+ //p.drawLine(l2); // Right line
+
+ double xx = rbt?xe_1:xe_0;
+ if(clone)
+ {
+ double yinc = 7.0 * y_1;
+ for(double yy = (rbt?ys_1:ys_2); yy < ye_2; yy += yinc)
+ {
+ double yi = (rbt?3.0:2.0) * y_1;
+ if(yy + yi > ye_2)
+ yi = ye_2 - yy;
+ p.drawLine(QPointF(xx, yy), QPointF(xx, yy + yi)); // Right dashed line
+ }
+ }
+ else
+ p.drawLine(QPointF(xx, rbt?ys_1:ys_2), QPointF(xx, rbt?ye_1:ye_2)); // Right line
+
+ if(het & Part::LeftEventsHidden)
+ p.setPen(((NPart*)item)->leftBorderTouches ? penHidden1 : penHidden2);
+ else
+ {
+ if(((NPart*)item)->leftBorderTouches)
+ p.setPen(part->selected() ? penSelect1V : penNormal1V);
+ else
+ p.setPen(part->selected() ? penSelect2V : penNormal2V);
+ }
+ //p.drawLine(l4); // Left line
+
+ xx = xs_0;
+ if(clone)
+ {
+ double yinc = 7.0 * y_1;
+ for(double yy = (lbt?ys_1:ys_2); yy < ye_2; yy += yinc)
+ {
+ double yi = (lbt?3.0:2.0) * y_1;
+ if(yy + yi > ye_2)
+ yi = ye_2 - yy;
+ p.drawLine(QPointF(xx, yy), QPointF(xx, yy + yi)); // Left dashed line
+ }
+ }
+ else
+ p.drawLine(QPointF(xx, lbt?ys_1:ys_2), QPointF(xx, lbt?ye_1:ye_2)); // Left line
+
+ p.setPen(part->selected() ? penSelect2H : penNormal2H);
+ p.drawLine(l1); // Top line
+ p.drawLine(l3); // Bottom line
+
+ #endif
+
+ //p.restore();
+
if (config.canvasShowPartType & 1) { // show names
// draw name
// FN: Set text color depending on part color (black / white)
int part_r, part_g, part_b, brightness;
- //config.partColors[i].getRgb(&part_r, &part_g, &part_b);
// Since we'll draw the text on the bottom (to accommodate drum 'slivers'),
// get the lowest colour in the gradient used to draw the part.
QRect rr = map(r);
rr.setX(rr.x() + 3);
- gGradientFromQColor(config.partColors[i], rr.topLeft(), rr.bottomLeft()).stops().last().second.getRgb(&part_r, &part_g, &part_b);
+ gGradientFromQColor(config.partColors[cidx], rr.topLeft(), rr.bottomLeft()).stops().last().second.getRgb(&part_r, &part_g, &part_b);
brightness = part_r*29 + part_g*59 + part_b*12;
- //if (brightness < 12000 || part->selected())
- // p.setPen(Qt::white); /* too dark: use white for text color */
- //else
- // p.setPen(Qt::black); /* otherwise use black */
- bool rev = brightness < 12000 || part->selected();
- //QRect rr = map(r);
- //rr.setX(rr.x() + 3);
+ //bool rev = (brightness < 12000 || part->selected()) && !part->mute() && !item->isMoving();
+ bool rev = brightness >= 12000 && !part->selected();
p.save();
p.setFont(config.fonts[1]);
p.setWorldMatrixEnabled(false);
if (rev)
- p.setPen(Qt::black);
- else
p.setPen(Qt::white);
+ else
+ p.setPen(Qt::black);
p.drawText(rr.translated(1, 1), Qt::AlignBottom|Qt::AlignLeft, part->name());
if (rev)
- p.setPen(Qt::white);
- else
p.setPen(Qt::black);
+ else
+ p.setPen(Qt::white);
p.drawText(rr, Qt::AlignBottom|Qt::AlignLeft, part->name());
p.restore();
}
}
+#endif
+
+void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)
+ {
+ int from = rect.x();
+ int to = from + rect.width();
+
+ //printf("from %d to %d\n", from,to);
+ Part* part = ((NPart*)item)->part();
+ int pTick = part->tick();
+ from -= pTick;
+ to -= pTick;
+ if(from < 0)
+ from = 0;
+ if((unsigned int)to > part->lenTick())
+ to = part->lenTick();
+
+ // Item bounding box x is in tick coordinates, same as rectangle.
+ if(item->bbox().intersect(rect).isNull())
+ {
+ //printf("PartCanvas::drawItem rectangle is null\n");
+ return;
+ }
+
+ QRect r = item->bbox();
+ bool clone = part->events()->arefCount() > 1;
+ QBrush brush;
+
+ //QRect rr = map(r); // Produced inconsistent positions. FIXME
+ //QRect rr = p.transform().mapRect(r); // Same.
+ QRect rr(QPoint(mapx(r.x()), mapy(r.y())),
+ QPoint(mapx(r.x() + r.width()) - 1, mapy(r.y() + r.height() - 1))); // Test OK so far.
+
+ //printf("PartCanvas::drawItem called map rx:%d rw:%d rrx:%d rrw:%d\n", r.x(), r.width(), rr.x(), rr.width());
+ //printf("PartCanvas::drawItem called map rx:%d rw:%d\n", r.x(), r.width());
+
+ p.save();
+ p.setWorldMatrixEnabled(false);
+
+ // NOTE: Optimization: For each item, hasHiddenEvents() is called once in Canvas::draw(), and we use cachedHasHiddenEvents().
+ // Not used for now.
+ //int het = part->cachedHasHiddenEvents();
+ int het = part->hasHiddenEvents();
+
+ int xs_0 = rr.x();
+ int xe_0 = xs_0 + rr.width();
+ int xs_1 = xs_0 + 1;
+ if(xs_1 > xe_0)
+ xs_1 = xe_0;
+ int xs_2 = xs_0 + 2;
+ if(xs_2 > xe_0)
+ xs_2 = xe_0;
+ int xs_6 = xs_0 + 6;
+ if(xs_6 > xe_0)
+ xs_6 = xe_0;
+
+ int xe_1 = xe_0 - 1;
+ if(xe_1 < xs_0)
+ xe_1 = xs_0;
+ int xe_2 = xe_0 - 2;
+ if(xe_2 < xs_0)
+ xe_2 = xs_0;
+ int xe_6 = xe_0 - 6;
+ if(xe_6 < xs_0)
+ xe_6 = xs_0;
+
+ int ys_0 = rr.y();
+ int ye_0 = ys_0 + rr.height();
+ int ys_1 = ys_0 + 1;
+ if(ys_1 > ye_0)
+ ys_1 = ye_0;
+ int ys_2 = ys_0 + 2;
+ if(ys_2 > ye_0)
+ ys_2 = ye_0;
+
+ int ye_1 = ye_0 - 1;
+ if(ye_1 < ys_0)
+ ye_1 = ys_0;
+ int ye_2 = ye_0 - 2;
+ if(ye_2 < ys_0)
+ ye_2 = ys_0;
+
+ int cidx = part->colorIndex();
+ if (item->isMoving())
+ {
+ QColor c(Qt::gray);
+ c.setAlpha(config.globalAlphaBlend);
+ QLinearGradient gradient(rr.topLeft(), rr.bottomLeft());
+ gradient.setColorAt(0, c);
+ gradient.setColorAt(1, c.darker());
+ brush = QBrush(gradient);
+ }
+ else
+ if (part->selected())
+ {
+ QColor c(Qt::black);
+ c.setAlpha(config.globalAlphaBlend);
+ QLinearGradient gradient(rr.topLeft(), rr.bottomLeft());
+ // Use a colour only about 20% lighter than black, rather than the 50% we use in gGradientFromQColor
+ // and is used in darker()/lighter(), so that it is distinguished a bit better from grey non-part tracks.
+ //c.setRgba(64, 64, 64, c.alpha());
+ gradient.setColorAt(0, QColor(51, 51, 51, config.globalAlphaBlend));
+ gradient.setColorAt(1, c);
+ brush = QBrush(gradient);
+ }
+ else
+ if (part->mute())
+ {
+ QColor c(Qt::white);
+ c.setAlpha(config.globalAlphaBlend);
+ QLinearGradient gradient(rr.topLeft(), rr.bottomLeft());
+ gradient.setColorAt(0, c);
+ gradient.setColorAt(1, c.darker());
+ brush = QBrush(gradient);
+ }
+ else
+ {
+ QColor c(config.partColors[cidx]);
+ c.setAlpha(config.globalAlphaBlend);
+ brush = QBrush(gGradientFromQColor(c, rr.topLeft(), rr.bottomLeft()));
+ }
+
+ int h = rr.height();
+ double s = double(h) / 4.0;
+ int y0 = rr.y();
+ int y1 = y0 + lrint(s);
+ int y2 = y0 + lrint(s * 2.0);
+ int y3 = y0 + lrint(s * 3.0);
+ int y4 = y0 + h;
+
+ QPoint points[16];
+ int pts;
+
+ //
+ // Fill the part rectangles, accounting for hidden events by using 'jagged' edges...
+ //
+
+ p.setBrush(brush);
+ p.setPen(Qt::NoPen);
+ if(het)
+ {
+ pts = 0;
+ if(het == (Part::LeftEventsHidden | Part::RightEventsHidden))
+ {
+ points[pts++] = QPoint(xs_0, y0);
+ points[pts++] = QPoint(xe_0, y0);
+ points[pts++] = QPoint(xe_6, y1);
+ points[pts++] = QPoint(xe_0, y2);
+ points[pts++] = QPoint(xe_6, y3);
+ points[pts++] = QPoint(xe_0, y4);
+ points[pts++] = QPoint(xs_0, y4);
+ points[pts++] = QPoint(xs_6, y3);
+ points[pts++] = QPoint(xs_0, y2);
+ points[pts++] = QPoint(xs_6, y1);
+ p.drawConvexPolygon(points, pts); // Help says may be faster on some platforms (X11).
+ }
+ else
+ if(het == Part::LeftEventsHidden)
+ {
+ points[pts++] = QPoint(xs_0, y0);
+ points[pts++] = QPoint(xe_0, y0);
+ points[pts++] = QPoint(xe_0, y4);
+ points[pts++] = QPoint(xs_0, y4);
+ points[pts++] = QPoint(xs_6, y3);
+ points[pts++] = QPoint(xs_0, y2);
+ points[pts++] = QPoint(xs_6, y1);
+ p.drawConvexPolygon(points, pts);
+ }
+ else
+ if(het == Part::RightEventsHidden)
+ {
+ points[pts++] = QPoint(xs_0, y0);
+ points[pts++] = QPoint(xe_0, y0);
+
+ points[pts++] = QPoint(xe_6, y1);
+ points[pts++] = QPoint(xe_0, y2);
+ points[pts++] = QPoint(xe_6, y3);
+ points[pts++] = QPoint(xe_0, y4);
+ points[pts++] = QPoint(xs_0, y4);
+ p.drawConvexPolygon(points, pts);
+ }
+
+ //
+ // Draw remaining 'hidden events' decorations with 'jagged' edges...
+ //
+
+ int part_r, part_g, part_b, brightness, color_brightness;
+ config.partColors[cidx].getRgb(&part_r, &part_g, &part_b);
+ brightness = part_r*29 + part_g*59 + part_b*12;
+ //if ((brightness < 12000 || part->selected()) && !part->mute() && !item->isMoving())
+ // color_brightness=223; // too dark: use lighter color
+ //else
+ // color_brightness=32; // otherwise use dark color
+ if ((brightness >= 12000 && !part->selected()))
+ color_brightness=32; // too light: use dark color
+ else
+ color_brightness=223; // too dark: use lighter color
+ QColor c(color_brightness,color_brightness,color_brightness, config.globalAlphaBlend);
+ p.setBrush(QBrush(gGradientFromQColor(c, rr.topLeft(), rr.bottomLeft())));
+ //p.setBrush(QBrush(c));
+ if(het & Part::RightEventsHidden)
+ {
+ pts = 0;
+ points[pts++] = QPoint(xe_0, y0);
+ points[pts++] = QPoint(xe_0, y4);
+ points[pts++] = QPoint(xe_6, y3);
+ points[pts++] = QPoint(xe_0, y2);
+ points[pts++] = QPoint(xe_6, y1);
+ p.drawConvexPolygon(points, pts);
+ }
+ if(het & Part::LeftEventsHidden)
+ {
+ pts = 0;
+ points[pts++] = QPoint(xs_0, y0);
+ points[pts++] = QPoint(xs_6, y1);
+ points[pts++] = QPoint(xs_0, y2);
+ points[pts++] = QPoint(xs_6, y3);
+ points[pts++] = QPoint(xs_0, y4);
+ p.drawConvexPolygon(points, pts);
+ }
+ }
+ else
+ {
+ p.fillRect(rr, brush);
+ }
+
+ // Draw a pattern brush on muted parts...
+ if(part->mute())
+ {
+ p.setPen(Qt::NoPen);
+ //brush.setStyle(Qt::DiagCrossPattern);
+ brush.setStyle(Qt::Dense7Pattern);
+
+ p.fillRect(rr, brush); // FIXME: Some shifting going on
+ //p.fillRect(QRect(rr.x(), rr.y(), rr.width() + 1, rr.height() + 1), brush); // Same here
+ }
+
+ p.setWorldMatrixEnabled(true);
+
+ MidiPart* mp = 0;
+ WavePart* wp = 0;
+ Track::TrackType type = part->track()->type();
+ if (type == Track::WAVE) {
+ wp =(WavePart*)part;
+ }
+ else {
+ mp = (MidiPart*)part;
+ }
+
+ if (wp)
+ drawWavePart(p, rect, wp, r);
+ else if (mp)
+ {
+ drawMidiPart(p, rect, mp->events(), (MidiTrack*)part->track(), mp, r, mp->tick(), from, to);
+ }
+
+ p.setWorldMatrixEnabled(false);
+
+ #if 0
+ //
+ // Now draw the borders...
+ // Works great but requires clones be drawn with the highest priority on top of all other parts, in Canvas::draw.
+ //
+
+ QPen pen(part->selected() ? config.partColors[i] : Qt::black, 2.0, clone ? Qt::DotLine : Qt::SolidLine);
+ pen.setCosmetic(true);
+ p.setPen(pen);
+ p.setBrush(Qt::NoBrush);
+ p.drawRect(r);
+
+ #else
+ //
+ // Now draw the borders, using custom segments...
+ //
+
+ // FIXME NOTE: For 1-pixel wide lines, setting pen style to anything other than solid didn't work out well.
+ // Much too screwy - the single-width lines kept getting shifted one pixel over intermittently.
+ // I tried EVERYTHING to make sure x is proper but the painter keeps shifting them over.
+ // Meanwhile the fills are correct. Seems painter doesn't like line patterns, whether stock or custom.
+ // Therefore I was forced to manually draw the left and right segments.
+ // It works. Which seems to be more proof that painter is handling line patterns and pen widths badly...
+ // DO NOT ERASE COMMENTED CODE BELOW for now, in case it can be fixed. Tim. p4.0.29
+
+ p.setBrush(Qt::NoBrush);
+
+ QColor pc((part->mute() || item->isMoving())? Qt::white : config.partColors[cidx]);
+ QPen penSelect1H(pc);
+ QPen penSelect2H(pc, 2.0);
+ QPen penSelect1V(pc);
+ QPen penSelect2V(pc, 2.0);
+ penSelect1H.setCosmetic(true);
+ penSelect2H.setCosmetic(true);
+ penSelect1V.setCosmetic(true);
+ penSelect2V.setCosmetic(true);
+
+ pc = Qt::black;
+ QPen penNormal1H(pc);
+ QPen penNormal2H(pc, 2.0);
+ QPen penNormal1V(pc);
+ QPen penNormal2V(pc, 2.0);
+ penNormal1H.setCosmetic(true);
+ penNormal2H.setCosmetic(true);
+ penNormal1V.setCosmetic(true);
+ penNormal2V.setCosmetic(true);
+
+ QVector<qreal> customDashPattern;
+ if(clone)
+ {
+ customDashPattern << 4.0 << 8.0;
+ penSelect1H.setDashPattern(customDashPattern);
+ penNormal1H.setDashPattern(customDashPattern);
+ //penSelect1V.setDashPattern(customDashPattern);
+ //penNormal1V.setDashPattern(customDashPattern);
+ customDashPattern.clear();
+ customDashPattern << 2.0 << 4.0;
+ penSelect2H.setDashPattern(customDashPattern);
+ penNormal2H.setDashPattern(customDashPattern);
+ //penSelect2V.setDashPattern(customDashPattern);
+ //penNormal2V.setDashPattern(customDashPattern);
+ }
+
+ pc = Qt::white;
+ QPen penHidden1(pc);
+ QPen penHidden2(pc, 2.0);
+ penHidden2.setCosmetic(true);
+ //customDashPattern.clear();
+ //customDashPattern << 2.0 << 10.0;
+ //penHidden1.setDashPattern(customDashPattern);
+ //customDashPattern.clear();
+ //customDashPattern << 1.0 << 5.0;
+ //penHidden2.setDashPattern(customDashPattern);
+
+ bool lbt = ((NPart*)item)->leftBorderTouches;
+ bool rbt = ((NPart*)item)->rightBorderTouches;
+
+ QLine l1( lbt?xs_1:xs_0, ys_0, rbt?xe_1:xe_0, ys_0); // Top
+ //QLine l2(rbt?xe_1:xe_0, r.y() + (rbt?y_1:y_2) - 1, rbt?xe_1:xe_0, r.y() + r.height() - 1); // Right
+ QLine l3( lbt?xs_1:xs_0, ye_0, rbt?xe_1:xe_0, ye_0); // Bottom
+ //QLine l4(r.x(), r.y() + (lbt?y_1:y_2), r.x(), r.y() + r.height() - (lbt?y_1:y_2)); // Left
+
+ if(het & Part::RightEventsHidden)
+ p.setPen(((NPart*)item)->rightBorderTouches ? penHidden1 : penHidden2);
+ else
+ {
+ if(((NPart*)item)->rightBorderTouches)
+ p.setPen(part->selected() ? penSelect1V : penNormal1V);
+ else
+ p.setPen(part->selected() ? penSelect2V : penNormal2V);
+ }
+ //p.drawLine(l2); // Right line
+
+ int xx = rbt?xe_1:xe_0;
+ if(clone)
+ {
+ int yinc = 7;
+ for(int yy = (rbt?ys_1:ys_2); yy < ye_2; yy += yinc)
+ {
+ int yi = rbt?3:2;
+ if(yy + yi > ye_2)
+ yi = ye_2 - yy;
+ p.drawLine(QPoint(xx, yy), QPoint(xx, yy + yi)); // Right dashed line
+ }
+ }
+ else
+ p.drawLine(QPoint(xx, rbt?ys_1:ys_2), QPoint(xx, rbt?ye_1:ye_2)); // Right line
+
+ if(het & Part::LeftEventsHidden)
+ p.setPen(((NPart*)item)->leftBorderTouches ? penHidden1 : penHidden2);
+ else
+ {
+ if(((NPart*)item)->leftBorderTouches)
+ p.setPen(part->selected() ? penSelect1V : penNormal1V);
+ else
+ p.setPen(part->selected() ? penSelect2V : penNormal2V);
+ }
+ //p.drawLine(l4); // Left line
+
+ xx = xs_0;
+ if(clone)
+ {
+ int yinc = 7;
+ for(int yy = (lbt?ys_1:ys_2); yy < ye_2; yy += yinc)
+ {
+ int yi = lbt?3:2;
+ if(yy + yi > ye_2)
+ yi = ye_2 - yy;
+ p.drawLine(QPoint(xx, yy), QPoint(xx, yy + yi)); // Left dashed line
+ }
+ }
+ else
+ p.drawLine(QPoint(xx, lbt?ys_1:ys_2), QPoint(xx, lbt?ye_1:ye_2)); // Left line
+
+ p.setPen(part->selected() ? penSelect2H : penNormal2H);
+ p.drawLine(l1); // Top line
+ p.drawLine(l3); // Bottom line
+
+ #endif
+
+ if (config.canvasShowPartType & 1) { // show names
+ // draw name
+ // FN: Set text color depending on part color (black / white)
+ int part_r, part_g, part_b, brightness;
+ // Since we'll draw the text on the bottom (to accommodate drum 'slivers'),
+ // get the lowest colour in the gradient used to draw the part.
+ //QRect rr = map(r);
+ QRect tr = rr;
+ tr.setX(tr.x() + 3);
+ gGradientFromQColor(config.partColors[cidx], tr.topLeft(), tr.bottomLeft()).stops().last().second.getRgb(&part_r, &part_g, &part_b);
+ brightness = part_r*29 + part_g*59 + part_b*12;
+ //bool rev = (brightness < 12000 || part->selected()) && !part->mute() && !item->isMoving();
+ bool rev = brightness >= 12000 && !part->selected();
+ p.setFont(config.fonts[1]);
+ if (rev)
+ p.setPen(Qt::white);
+ else
+ p.setPen(Qt::black);
+ p.drawText(tr.translated(1, 1), Qt::AlignBottom|Qt::AlignLeft, part->name());
+ if (rev)
+ p.setPen(Qt::black);
+ else
+ p.setPen(Qt::white);
+ p.drawText(tr, Qt::AlignBottom|Qt::AlignLeft, part->name());
+ }
+ p.restore();
+ p.setWorldMatrixEnabled(true);
+ }
//---------------------------------------------------------
// drawMoving
@@ -1434,19 +2145,11 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)
void PartCanvas::drawMoving(QPainter& p, const CItem* item, const QRect&)
{
p.setPen( Qt::black);
-
- //p.setBrush( Qt::NoBrush);
- //QColor c(Qt::gray);
Part* part = ((NPart*)item)->part();
- QColor c(config.partColors[part->colorIndex()]);
-
- ///c.setAlpha(config.globalAlphaBlend);
+ QColor c(part->mute() ? Qt::white : config.partColors[part->colorIndex()]);
+ //c.setAlpha(config.globalAlphaBlend);
c.setAlpha(128); // Fix this regardless of global setting. Should be OK.
-
p.setBrush(c);
-
- // NOTE: For one-pixel border use second line. For two-pixel border use first.
- //p.drawRect(item->mp().x(), item->mp().y()+1, item->width(), item->height());
p.drawRect(item->mp().x(), item->mp().y(), item->width(), item->height());
}
@@ -1466,10 +2169,14 @@ void PartCanvas::drawMidiPart(QPainter& p, const QRect&, EventList* events, Midi
int part_r, part_g, part_b, brightness;
config.partColors[pt->colorIndex()].getRgb(&part_r, &part_g, &part_b);
brightness = part_r*29 + part_g*59 + part_b*12;
- if (brightness < 12000 || pt->selected())
- color_brightness=192; // too dark: use lighter color
+ //if ((brightness < 12000 || pt->selected()) && !pt->mute())
+ // color_brightness=192; // too dark: use lighter color
+ //else
+ // color_brightness=64; // otherwise use dark color
+ if (brightness >= 12000 && !pt->selected())
+ color_brightness=64; // too bright: use dark color
else
- color_brightness=64; // otherwise use dark color
+ color_brightness=192; // too dark: use lighter color
}
else
color_brightness=80;
@@ -1654,9 +2361,11 @@ void PartCanvas::drawMidiPart(QPainter& p, const QRect&, EventList* events, Midi
if (te < (from + pTick))
continue;
- if (te > (to + pTick))
- te = to + pTick;
-
+ //if (te > (to + pTick))
+ // te = to + pTick;
+ if (te >= (to + pTick))
+ te = lrint(rmapxDev_f(rmapx_f(to + pTick) - 1.0));
+
EventType type = i->second.type();
if (type == Note) {
int pitch = i->second.pitch();
diff --git a/muse2/muse/arranger/pcanvas.h b/muse2/muse/arranger/pcanvas.h
index ccfb1fcc..5f0aabae 100644
--- a/muse2/muse/arranger/pcanvas.h
+++ b/muse2/muse/arranger/pcanvas.h
@@ -3,11 +3,14 @@
// Linux Music Editor
// $Id: pcanvas.h,v 1.11.2.4 2009/05/24 21:43:44 terminator356 Exp $
// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+// Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)
//=========================================================
#ifndef __PCANVAS_H__
#define __PCANVAS_H__
+#include <QVector>
+
#include "song.h"
#include "canvas.h"
#include "trackautomationview.h"
@@ -33,6 +36,9 @@ class NPart : public CItem {
const QString name() const { return part()->name(); }
void setName(const QString& s) { part()->setName(s); }
Track* track() const { return part()->track(); }
+
+ bool leftBorderTouches; // Whether the borders touch other part borders.
+ bool rightBorderTouches;
};
enum ControllerVals { doNothing, movingController, addNewController };
diff --git a/muse2/muse/driver/jack.cpp b/muse2/muse/driver/jack.cpp
index 4857ede5..529e8a60 100644
--- a/muse2/muse/driver/jack.cpp
+++ b/muse2/muse/driver/jack.cpp
@@ -977,7 +977,8 @@ void JackAudioDevice::graphChanged()
// p3.3.37
//delete ports;
- free(ports);
+ //free(ports);
+ jack_free(ports); // p4.0.29
ports = NULL;
}
@@ -1063,7 +1064,8 @@ void JackAudioDevice::graphChanged()
// p3.3.37
//delete ports;
- free(ports);
+ //free(ports);
+ jack_free(ports); // p4.0.29
ports = NULL;
}
@@ -1182,7 +1184,8 @@ void JackAudioDevice::graphChanged()
// p3.3.55
// Done with ports. Free them.
- free(ports);
+ //free(ports);
+ jack_free(ports); // p4.0.29
}
}
}
@@ -1279,7 +1282,8 @@ void JackAudioDevice::graphChanged()
}
// p3.3.55
// Done with ports. Free them.
- free(ports);
+ //free(ports);
+ jack_free(ports); // p4.0.29
}
}
}
@@ -1662,7 +1666,8 @@ std::list<QString> JackAudioDevice::outputPorts(bool midi, int aliases)
// p3.3.37
if(ports)
- free(ports);
+ //free(ports);
+ jack_free(ports); // p4.0.29
return clientList;
}
@@ -1734,7 +1739,8 @@ std::list<QString> JackAudioDevice::inputPorts(bool midi, int aliases)
// p3.3.37
if(ports)
- free(ports);
+ //free(ports);
+ jack_free(ports); // p4.0.29
return clientList;
}
diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp
index 66257401..2568899a 100644
--- a/muse2/muse/functions.cpp
+++ b/muse2/muse/functions.cpp
@@ -307,7 +307,7 @@ bool modify_notelen(const set<Part*>& parts, int range, int rate, int offset)
if (len <= 0)
len = 1;
- if ((event.tick()+len > part->lenTick()) && (!part->hasHiddenNotes()))
+ if ((event.tick()+len > part->lenTick()) && (!part->hasHiddenEvents()))
partlen[part]=event.tick()+len; // schedule auto-expanding
if (event.lenTick() != len)
@@ -510,7 +510,7 @@ bool move_notes(const set<Part*>& parts, int range, signed int ticks)
if (newEvent.endTick() > part->lenTick()) //if exceeding the part's end:
{
- if (part->hasHiddenNotes()) // auto-expanding is forbidden, clip
+ if (part->hasHiddenEvents()) // auto-expanding is forbidden, clip
{
if (part->lenTick() > newEvent.tick())
newEvent.setLenTick(part->lenTick() - newEvent.tick());
@@ -764,7 +764,7 @@ void paste_at(Part* dest_part, const QString& pt, int pos)
if (e.endTick() > dest_part->lenTick()) // event exceeds part?
{
- if (dest_part->hasHiddenNotes()) // auto-expanding is forbidden?
+ if (dest_part->hasHiddenEvents()) // auto-expanding is forbidden?
{
if (e.tick() < dest_part->lenTick())
e.setLenTick(dest_part->lenTick() - e.tick()); // clip
diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp
index d0a5ee31..578e2616 100644
--- a/muse2/muse/midiedit/dcanvas.cpp
+++ b/muse2/muse/midiedit/dcanvas.cpp
@@ -160,7 +160,7 @@ Undo DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp
Part* opart = ip2c->first;
int diff = ip2c->second.xdiff;
- if (opart->hasHiddenNotes())
+ if (opart->hasHiddenEvents())
{
forbidden=true;
break;
@@ -352,7 +352,7 @@ void DrumCanvas::newItem(CItem* item, bool noSnap, bool replace)
Undo operations;
int diff = event.endTick()-part->lenTick();
- if (! ((diff > 0) && part->hasHiddenNotes()) ) //operation is allowed
+ if (! ((diff > 0) && part->hasHiddenEvents()) ) //operation is allowed
{
operations.push_back(UndoOp(UndoOp::AddEvent,event, part, false, false));
diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp
index 5fb59099..eba1a13c 100644
--- a/muse2/muse/midiedit/prcanvas.cpp
+++ b/muse2/muse/midiedit/prcanvas.cpp
@@ -316,7 +316,7 @@ Undo PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty
Part* opart = ip2c->first;
int diff = ip2c->second.xdiff;
- if (opart->hasHiddenNotes())
+ if (opart->hasHiddenEvents())
{
forbidden=true;
break;
@@ -470,7 +470,7 @@ void PianoCanvas::newItem(CItem* item, bool noSnap)
Undo operations;
int diff = event.endTick()-part->lenTick();
- if (! ((diff > 0) && part->hasHiddenNotes()) ) //operation is allowed
+ if (! ((diff > 0) && part->hasHiddenEvents()) ) //operation is allowed
{
operations.push_back(UndoOp(UndoOp::AddEvent,event, part, false, false));
@@ -515,7 +515,7 @@ void PianoCanvas::resizeItem(CItem* item, bool noSnap, bool) // experime
Undo operations;
int diff = event.tick()+len-part->lenTick();
- if (! ((diff > 0) && part->hasHiddenNotes()) ) //operation is allowed
+ if (! ((diff > 0) && part->hasHiddenEvents()) ) //operation is allowed
{
newEvent.setLenTick(len);
operations.push_back(UndoOp(UndoOp::ModifyEvent,newEvent, event, nevent->part(), false, false));
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index 785ac7a5..b6b2c6d9 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -3931,7 +3931,7 @@ void ScoreCanvas::mouseMoveEvent (QMouseEvent* event)
unsigned newpartlen=dragged_event_part->lenTick();
if (tmp.endTick() > dragged_event_part->lenTick())
{
- if (dragged_event_part->hasHiddenNotes()) // do not allow autoexpand
+ if (dragged_event_part->hasHiddenEvents()) // do not allow autoexpand
{
tmp.setLenTick(dragged_event_part->lenTick() - tmp.tick());
if (debugMsg) cout << "resized note would exceed its part; limiting length to " << tmp.lenTick() << endl;
@@ -4481,7 +4481,7 @@ void staff_t::update_part_indices()
* o add "move other notes" or "overwrite notes" or "mix with notes" to paste
*
* IMPORTANT TODO
- * o draw the edge of parts hiding notes "jagged" (hasHiddenNotes() is interesting for this)
+ * o draw the edge of parts hiding notes "jagged" (hasHiddenEvents() is interesting for this) - Done. Tim.
* o shrink a part from its beginning as well! watch out for clones!
* o insert empty measure should also work inside parts, that is,
* move notes _within_ parts
diff --git a/muse2/muse/part.cpp b/muse2/muse/part.cpp
index 67cf441e..3e371bf4 100644
--- a/muse2/muse/part.cpp
+++ b/muse2/muse/part.cpp
@@ -4,6 +4,7 @@
// $Id: part.cpp,v 1.12.2.17 2009/06/25 05:13:02 terminator356 Exp $
//
// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
+// Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)
//=========================================================
#include <stdio.h>
@@ -655,6 +656,7 @@ Part* PartList::find(int idx)
Part::Part(Track* t)
{
+ _hiddenEvents = NoEventsHidden;
_prevClone = this;
_nextClone = this;
setSn(newSn());
@@ -673,6 +675,7 @@ Part::Part(Track* t)
Part::Part(Track* t, EventList* ev)
{
+ _hiddenEvents = NoEventsHidden;
_prevClone = this;
_nextClone = this;
setSn(newSn());
@@ -1169,15 +1172,38 @@ WavePart* WavePart::clone() const
return new WavePart(*this);
}
+/*
+bool Part::hasHiddenNotes()
+{
+ unsigned lastNote=0;
+ for (iEvent ev=events()->begin(); ev!=events()->end(); ev++)
+ if (ev->second.endTick() > lastNote)
+ lastNote=ev->second.endTick();
+
+ return lastNote > lenTick();
+}
+*/
-bool Part::hasHiddenNotes()
+//---------------------------------------------------------
+// hasHiddenEvents
+// Returns combination of HiddenEventsType enum.
+//---------------------------------------------------------
+
+int Part::hasHiddenEvents()
{
- unsigned lastNote=0;
+ unsigned len = lenTick();
- for (iEvent ev=events()->begin(); ev!=events()->end(); ev++)
- if (ev->second.endTick() > lastNote)
- lastNote=ev->second.endTick();
-
- return lastNote > lenTick();
+ // TODO: For now, we don't support events before the left border, only events past the right border.
+ for(iEvent ev=events()->begin(); ev!=events()->end(); ev++)
+ {
+ if(ev->second.endTick() > len)
+ {
+ _hiddenEvents = RightEventsHidden; // Cache the result for later.
+ return _hiddenEvents;
+ }
+ }
+ _hiddenEvents = NoEventsHidden; // Cache the result for later.
+ return _hiddenEvents;
}
+
diff --git a/muse2/muse/part.h b/muse2/muse/part.h
index ff7091a6..67a67dbb 100644
--- a/muse2/muse/part.h
+++ b/muse2/muse/part.h
@@ -4,6 +4,7 @@
// $Id: part.h,v 1.5.2.4 2009/05/24 21:43:44 terminator356 Exp $
//
// (C) Copyright 1999/2000 Werner Schweer (ws@seh.de)
+// Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)
//=========================================================
#ifndef __PART_H__
@@ -40,6 +41,10 @@ typedef CloneList::iterator iClone;
//---------------------------------------------------------
class Part : public PosLen {
+ public:
+ enum HiddenEventsType { NoEventsHidden = 0, LeftEventsHidden, RightEventsHidden };
+
+ private:
static int snGen;
int _sn;
@@ -48,6 +53,8 @@ class Part : public PosLen {
bool _mute;
int _colorIndex;
+ int _hiddenEvents; // Combination of HiddenEventsType.
+
protected:
Track* _track;
EventList* _events;
@@ -82,7 +89,11 @@ class Part : public PosLen {
void setPrevClone(Part* p) { _prevClone = p; }
void setNextClone(Part* p) { _nextClone = p; }
- bool hasHiddenNotes();
+ // Returns combination of HiddenEventsType enum.
+ int hasHiddenEvents();
+ // If repeated calls to hasHiddenEvents() are desired, then to avoid re-iteration of the event list,
+ // call this after hasHiddenEvents().
+ int cachedHasHiddenEvents() const { return _hiddenEvents; }
iEvent addEvent(Event& p);
diff --git a/muse2/muse/steprec.cpp b/muse2/muse/steprec.cpp
index c1fc23b1..45af3930 100644
--- a/muse2/muse/steprec.cpp
+++ b/muse2/muse/steprec.cpp
@@ -77,7 +77,7 @@ void StepRec::record(Part* part, int pitch, int len, int step, int velo, bool ct
{
// if we already entered the note, delete it
// if we would find a note after part->lenTick(), the above "if"
- // avoids this. this has to be avoided because then part->hasHiddenNotes() is true
+ // avoids this. this has to be avoided because then part->hasHiddenEvents() is true
// which results in forbidding any action beyond its end
EventRange range = events->equal_range(tick - part->tick());
for (iEvent i = range.first; i != range.second; ++i)
@@ -173,7 +173,7 @@ void StepRec::record(Part* part, int pitch, int len, int step, int velo, bool ct
}
steprec_record_foot:
- if (!((lasttick > part->lenTick()) && part->hasHiddenNotes())) // allowed?
+ if (!((lasttick > part->lenTick()) && part->hasHiddenEvents())) // allowed?
{
if (lasttick > part->lenTick()) // we have to expand the part?
schedule_resize_all_same_len_clone_parts(part, lasttick, operations);
diff --git a/muse2/muse/widgets/canvas.cpp b/muse2/muse/widgets/canvas.cpp
index a74e8a8f..c2c329a9 100644
--- a/muse2/muse/widgets/canvas.cpp
+++ b/muse2/muse/widgets/canvas.cpp
@@ -3,6 +3,7 @@
// Linux Music Editor
// $Id: canvas.cpp,v 1.10.2.17 2009/05/03 04:14:01 terminator356 Exp $
// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+// Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)
//=========================================================
#include <stdio.h>
@@ -18,6 +19,8 @@
#include <QMouseEvent>
#include <QWheelEvent>
+#include <vector>
+
#include "song.h"
#include "event.h"
#include "citem.h"
@@ -148,6 +151,11 @@ void Canvas::draw(QPainter& p, const QRect& rect)
int h = rect.height();
int x2 = x + w;
+ std::vector<CItem*> list1;
+ std::vector<CItem*> list2;
+ //std::vector<CItem*> list3;
+ std::vector<CItem*> list4;
+
if (virt()) {
drawCanvas(p, rect);
@@ -157,22 +165,24 @@ void Canvas::draw(QPainter& p, const QRect& rect)
iCItem to(items.lower_bound(x2));
+ /*
// Draw items from other parts behind all others.
// Only for items with events (not arranger parts).
for(iCItem i = items.begin(); i != to; ++i)
{
CItem* ci = i->second;
+ // NOTE Optimization: For each item call this once now, then use cached results later via cachedHasHiddenEvents().
+ ci->part()->hasHiddenEvents();
if(!ci->event().empty() && ci->part() != curPart)
- {
drawItem(p, ci, rect);
- }
}
-
+
+ // Draw unselected parts behind selected.
for (iCItem i = items.begin(); i != to; ++i)
{
CItem* ci = i->second;
- // Draw unselected parts behind selected.
- if(!ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
+ if((!ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
+ && !(ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents()))) // p4.0.29
{
drawItem(p, ci, rect);
}
@@ -181,12 +191,57 @@ void Canvas::draw(QPainter& p, const QRect& rect)
// Draw selected parts in front of unselected.
for (iCItem i = items.begin(); i != to; ++i)
{
- CItem* ci = i->second;
- if(ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
- {
- drawItem(p, ci, rect);
- }
+ CItem* ci = i->second;
+ if(ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
+ //if((ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
+ // || (ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents())))
+ {
+ drawItem(p, ci, rect);
+ }
+ }
+ */
+
+ // p4.0.29
+ for(iCItem i = items.begin(); i != to; ++i)
+ {
+ CItem* ci = i->second;
+ // NOTE Optimization: For each item call this once now, then use cached results later via cachedHasHiddenEvents().
+ // Not required for now.
+ //ci->part()->hasHiddenEvents();
+
+ // Draw items from other parts behind all others.
+ // Only for items with events (not arranger parts).
+ if(!ci->event().empty() && ci->part() != curPart)
+ list1.push_back(ci);
+ else if(!ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
+ {
+ // Draw selected parts in front of all others.
+ if(ci->isSelected())
+ list4.push_back(ci);
+ // Draw clone parts, and parts with hidden events, in front of others all except selected.
+ //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents()))
+ // Draw clone parts in front of others all except selected.
+ //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1))
+ // list3.push_back(ci);
+ else
+ // Draw unselected parts.
+ list2.push_back(ci);
+ }
}
+ int i;
+ int sz = list1.size();
+ for(i = 0; i != sz; ++i)
+ drawItem(p, list1[i], rect);
+ sz = list2.size();
+ for(i = 0; i != sz; ++i)
+ drawItem(p, list2[i], rect);
+ //sz = list3.size();
+ //for(i = 0; i != sz; ++i)
+ // drawItem(p, list3[i], rect);
+ sz = list4.size();
+ for(i = 0; i != sz; ++i)
+ drawItem(p, list4[i], rect);
+
to = moving.lower_bound(x2);
for (iCItem i = moving.begin(); i != to; ++i)
{
@@ -237,21 +292,22 @@ void Canvas::draw(QPainter& p, const QRect& rect)
//---------------------------------------------------
// draw Canvas Items
//---------------------------------------------------
-
+
+ /*
// Draw items from other parts behind all others.
// Only for items with events (not arranger parts).
for(iCItem i = items.begin(); i != items.end(); ++i)
{
CItem* ci = i->second;
+ // NOTE Optimization: For each item call this once now, then use cached results later via cachedHasHiddenEvents().
+ ci->part()->hasHiddenEvents();
if(!ci->event().empty() && ci->part() != curPart)
- {
drawItem(p, ci, rect);
- }
- }
-
+ }
+
+ // Draw unselected parts behind selected.
for (iCItem i = items.begin(); i != items.end(); ++i) {
CItem* ci = i->second;
- // Draw unselected parts behind selected.
if(!ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
{
drawItem(p, ci, rect);
@@ -262,10 +318,55 @@ void Canvas::draw(QPainter& p, const QRect& rect)
for (iCItem i = items.begin(); i != items.end(); ++i) {
CItem* ci = i->second;
if(ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
- {
- drawItem(p, ci, rect);
- }
- }
+ //if((ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
+ // || (ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents())))
+ {
+ drawItem(p, ci, rect);
+ }
+ }
+ */
+
+ // p4.0.29
+ for(iCItem i = items.begin(); i != items.end(); ++i)
+ {
+ CItem* ci = i->second;
+ // NOTE Optimization: For each item call this once now, then use cached results later via cachedHasHiddenEvents().
+ // Not required for now.
+ //ci->part()->hasHiddenEvents();
+
+ // Draw items from other parts behind all others.
+ // Only for items with events (not arranger parts).
+ if(!ci->event().empty() && ci->part() != curPart)
+ list1.push_back(ci);
+ else if(!ci->isMoving() && (ci->event().empty() || ci->part() == curPart))
+ {
+ // Draw selected parts in front of all others.
+ if(ci->isSelected())
+ list4.push_back(ci);
+ // Draw clone parts, and parts with hidden events, in front of others all except selected.
+ //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents()))
+ // Draw clone parts in front of others all except selected.
+ //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1))
+ // list3.push_back(ci);
+ else
+ // Draw unselected parts.
+ list2.push_back(ci);
+ }
+ }
+ int i;
+ int sz = list1.size();
+ for(i = 0; i != sz; ++i)
+ drawItem(p, list1[i], rect);
+ sz = list2.size();
+ for(i = 0; i != sz; ++i)
+ drawItem(p, list2[i], rect);
+ //sz = list3.size();
+ //for(i = 0; i != sz; ++i)
+ // drawItem(p, list3[i], rect);
+ sz = list4.size();
+ for(i = 0; i != sz; ++i)
+ drawItem(p, list4[i], rect);
+
for (iCItem i = moving.begin(); i != moving.end(); ++i)
{
drawItem(p, i->second, rect);
@@ -273,7 +374,7 @@ void Canvas::draw(QPainter& p, const QRect& rect)
drawTopItem(p, QRect(x,y,w,h));
p.save();
setPainter(p);
- }
+ }
//---------------------------------------------------
// draw marker
diff --git a/muse2/muse/widgets/canvas.h b/muse2/muse/widgets/canvas.h
index dbe13fcb..99bbabee 100644
--- a/muse2/muse/widgets/canvas.h
+++ b/muse2/muse/widgets/canvas.h
@@ -3,6 +3,7 @@
// Linux Music Editor
// $Id: canvas.h,v 1.3.2.8 2009/02/02 21:38:01 terminator356 Exp $
// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+// Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)
//=========================================================
#ifndef __CANVAS_H__
diff --git a/muse2/muse/widgets/view.cpp b/muse2/muse/widgets/view.cpp
index fb480527..49f559c6 100644
--- a/muse2/muse/widgets/view.cpp
+++ b/muse2/muse/widgets/view.cpp
@@ -3,6 +3,7 @@
// Linux Music Editor
// $Id: view.cpp,v 1.3.2.2 2009/04/06 01:24:55 terminator356 Exp $
// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+// Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)
//=========================================================
#include "view.h"
@@ -16,6 +17,8 @@
#include <QKeyEvent>
#include <QPaintEvent>
+#include "math.h"
+
// Don't use this, it was just for debugging.
// It's much slower than muse-1 no matter how hard I tried.
// The left/right pixmap shifters in seXPos setYPos
@@ -545,9 +548,26 @@ void View::setPainter(QPainter& p)
// map
//---------------------------------------------------------
+QRect View::mapDev(const QRect& r) const
+ {
+ return QRect(mapxDev(r.x()), mapyDev(r.y()),
+ rmapxDev(r.width()), rmapyDev(r.height()));
+ }
+
+QPoint View::mapDev(const QPoint& r) const
+ {
+ return QPoint(mapxDev(r.x()), mapyDev(r.y()));
+ }
+
+#if 0
+ //
+ // Calculations using integer rounding methods...
+ //
+
QRect View::map(const QRect& r) const
{
int x, y, w, h;
+ //printf("View::map xmag:%d xpos:%d xorg:%d\n", xmag, xpos, xorg);
if (xmag < 0) {
x = r.x()/(-xmag) - (xpos + rmapx(xorg)); // round down
w = (r.width()-xmag-1) / (-xmag); // round up
@@ -585,17 +605,6 @@ QPoint View::map(const QPoint& p) const
return QPoint(x, y);
}
-QRect View::mapDev(const QRect& r) const
- {
- return QRect(mapxDev(r.x()), mapyDev(r.y()),
- rmapxDev(r.width()), rmapyDev(r.height()));
- }
-
-QPoint View::mapDev(const QPoint& r) const
- {
- return QPoint(mapxDev(r.x()), mapyDev(r.y()));
- }
-
int View::mapx(int x) const
{
if (xmag < 0) {
@@ -664,6 +673,153 @@ int View::rmapyDev(int y) const
return (y + ymag/2) / ymag;
}
+
+#else
+ //
+ // Calculations using more accurate methods... p4.0.29 Tim.
+ //
+
+QRect View::map(const QRect& r) const
+ {
+ int x, y, w, h;
+ //printf("View::map xmag:%d xpos:%d xorg:%d\n", xmag, xpos, xorg);
+ if (xmag < 0) {
+ x = lrint(double(r.x())/double(-xmag) - rmapx_f(xorg)) - xpos;
+ w = lrint(double(r.width()) / double(-xmag));
+ }
+ else {
+ x = r.x()*xmag - xpos - lrint(rmapx_f(xorg));
+ w = r.width() * xmag;
+ }
+ if (ymag < 0) {
+ y = lrint(double(r.y())/double(-ymag) - rmapy_f(yorg)) - ypos;
+ h = lrint(double(r.height()) / double(-ymag));
+ }
+ else {
+ y = r.y()*ymag - ypos - lrint(rmapy_f(yorg));
+ h = r.height() * ymag;
+ }
+ return QRect(x, y, w, h);
+ }
+
+QPoint View::map(const QPoint& p) const
+ {
+ int x, y;
+ if (xmag < 0) {
+ x = lrint(double(p.x())/double(-xmag) - rmapx_f(xorg)) - xpos;
+ }
+ else {
+ x = p.x()*xmag - xpos - lrint(rmapx_f(xorg));
+ }
+ if (ymag < 0) {
+ y = lrint(double(p.y())/double(-ymag) - rmapy_f(yorg)) - ypos;
+ }
+ else {
+ y = p.y()*ymag - ypos - lrint(rmapy_f(yorg));
+ }
+ return QPoint(x, y);
+ }
+
+int View::mapx(int x) const
+ {
+ if (xmag < 0) {
+ return lrint(double(x)/double(-xmag) - rmapx_f(xorg)) - xpos;
+ }
+ else {
+ return x*xmag - xpos - lrint(rmapx_f(xorg));
+ }
+ }
+int View::mapy(int y) const
+ {
+ if (ymag < 0) {
+ return lrint(double(y)/double(-ymag) - rmapy_f(yorg)) - ypos;
+ }
+ else {
+ return y*ymag - ypos - lrint(rmapy_f(yorg));
+ }
+ }
+int View::mapxDev(int x) const
+ {
+ int val;
+ if (xmag <= 0)
+ val = lrint((double(x + xpos) + rmapx_f(xorg)) * double(-xmag));
+ else
+ val = lrint((double(x + xpos) + rmapx_f(xorg)) / double(xmag));
+ if (val < 0) // DEBUG
+ val = 0;
+ return val;
+ }
+
+int View::mapyDev(int y) const
+ {
+ if (ymag <= 0)
+ return lrint((double(y + ypos) + rmapy_f(yorg)) * double(-ymag));
+ else
+ return lrint((double(y + ypos) + rmapy_f(yorg)) / double(ymag));
+ }
+
+// r == relative conversion
+int View::rmapx(int x) const
+ {
+ if (xmag < 0)
+ return lrint(double(x) / double(-xmag));
+ else
+ return x * xmag;
+ }
+int View::rmapy(int y) const
+ {
+ if (ymag < 0)
+ return lrint(double(y) / double(-ymag));
+ else
+ return y * ymag;
+ }
+int View::rmapxDev(int x) const
+ {
+ if (xmag <= 0)
+ return x * (-xmag);
+ else
+ return lrint(double(x) / double(xmag));
+ }
+int View::rmapyDev(int y) const
+ {
+ if (ymag <= 0)
+ return y * (-ymag);
+ else
+ return lrint(double(y) / double(ymag));
+ }
+#endif
+
+double View::rmapx_f(double x) const
+ {
+ if (xmag < 0)
+ return x / double(-xmag);
+ else
+ return x * double(xmag);
+ }
+double View::rmapy_f(double y) const
+ {
+ if (ymag < 0)
+ return y / double(-ymag);
+ else
+ return y * double(ymag);
+ }
+double View::rmapxDev_f(double x) const
+ {
+ if (xmag <= 0)
+ return x * double(-xmag);
+ else
+ return x / double(xmag);
+ }
+double View::rmapyDev_f(double y) const
+ {
+ if (ymag <= 0)
+ return y * double(-ymag);
+ else
+ return y / double(ymag);
+ }
+
+
+
/*
QRect View::devToVirt(const QRect& r)
{
diff --git a/muse2/muse/widgets/view.h b/muse2/muse/widgets/view.h
index f53c4c72..ad0a6cf9 100644
--- a/muse2/muse/widgets/view.h
+++ b/muse2/muse/widgets/view.h
@@ -3,6 +3,7 @@
// Linux Music Editor
// $Id: view.h,v 1.2.2.1 2008/01/26 07:23:21 terminator356 Exp $
// (C) Copyright 1999 Werner Schweer (ws@seh.de)
+// Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)
//=========================================================
#ifndef __VIEW_H__
@@ -77,6 +78,10 @@ class View : public QWidget {
int rmapy(int y) const;
int rmapyDev(int y) const;
//QRect devToVirt(const QRect&);
+ double rmapx_f(double x) const;
+ double rmapy_f(double y) const;
+ double rmapxDev_f(double x) const;
+ double rmapyDev_f(double y) const;
void setPainter(QPainter& p);