From e2084952744efe4c6cf9137ba0c544c115064d5f Mon Sep 17 00:00:00 2001 From: "Tim E. Real" Date: Fri, 5 Aug 2011 08:28:29 +0000 Subject: 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(). --- muse2/ChangeLog | 6 + muse2/muse/arranger/pcanvas.cpp | 909 +++++++++++++++++++++++++++++++++----- muse2/muse/arranger/pcanvas.h | 6 + muse2/muse/driver/jack.cpp | 18 +- muse2/muse/functions.cpp | 6 +- muse2/muse/midiedit/dcanvas.cpp | 4 +- muse2/muse/midiedit/prcanvas.cpp | 6 +- muse2/muse/midiedit/scoreedit.cpp | 4 +- muse2/muse/part.cpp | 40 +- muse2/muse/part.h | 13 +- muse2/muse/steprec.cpp | 4 +- muse2/muse/widgets/canvas.cpp | 143 +++++- muse2/muse/widgets/canvas.h | 1 + muse2/muse/widgets/view.cpp | 178 +++++++- muse2/muse/widgets/view.h | 5 + 15 files changed, 1185 insertions(+), 158 deletions(-) (limited to 'muse2') diff --git a/muse2/ChangeLog b/muse2/ChangeLog index 625ab3f4..854d87bf 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,9 @@ +05.08.2011: + - Parts having hidden events now drawn using 'jagged' ends and special white edges. (Tim p4.0.29) + - Improved border drawing guaranteed to show L/R touching part borders. TODO: Top and bottom borders. (Tim) + - Muted parts now show names and events. Filled with a special brush pattern for easy recognition. (Tim) + - Huge changes to PartCanvas::drawItem(). And to all View::XmapXXX methods for better accuracy. (Tim) + - Changed bool Part::hasHiddenNotes() to int Part::hasHiddenEvents(). Added int Part::cachedHasHiddenEvents(). (Tim) 02.08.2011: - Changed behaviour of part clones (flo93) 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 @@ -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 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 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 + #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 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 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& 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& 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 @@ -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 @@ -18,6 +19,8 @@ #include #include +#include + #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 list1; + std::vector list2; + //std::vector list3; + std::vector 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 #include +#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); -- cgit v1.2.3 From 5271f995194cffc3f9fe409198537b1422d1329b Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Sat, 6 Aug 2011 11:21:26 +0000 Subject: fixed "resize wave part crashes muse" bug --- muse2/muse/part.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'muse2') diff --git a/muse2/muse/part.cpp b/muse2/muse/part.cpp index 3e371bf4..239d53d5 100644 --- a/muse2/muse/part.cpp +++ b/muse2/muse/part.cpp @@ -852,7 +852,6 @@ void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len, bool doClo Event newEvent = e.clone(); newEvent.setLenFrame(new_partlength - event_startframe); // Do not do port controller values and clone parts. - audio->msgChangeEvent(e, newEvent, nPart, false, false, false); operations.push_back(UndoOp(UndoOp::ModifyEvent, newEvent, e, nPart, false,false)); } } @@ -892,7 +891,6 @@ void Song::cmdResizePart(Track* track, Part* oPart, unsigned int len, bool doClo nPart->setLenFrame(new_partlength); // Do not do port controller values and clone parts. - audio->msgChangePart(oPart, nPart, false, false, false); operations.push_back(UndoOp(UndoOp::ModifyPart, oPart, nPart, false, false)); song->applyOperationGroup(operations); } -- cgit v1.2.3 From 94bd607ca280fe72a14a144c3d2b869ec9b37f8f Mon Sep 17 00:00:00 2001 From: Orcan Ogetbil Date: Sat, 13 Aug 2011 19:11:31 +0000 Subject: Make the shininess of the Knob ring a little smarter --- muse2/ChangeLog | 2 ++ muse2/muse/widgets/knob.cpp | 31 ++++++++++++++++++++++++++++++- muse2/muse/widgets/knob.h | 5 +++++ 3 files changed, 37 insertions(+), 1 deletion(-) (limited to 'muse2') diff --git a/muse2/ChangeLog b/muse2/ChangeLog index 854d87bf..d333b4fc 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,5 @@ +13.08.2011: + - Make the shininess of the Knob ring a little smarter (Orcan) 05.08.2011: - Parts having hidden events now drawn using 'jagged' ends and special white edges. (Tim p4.0.29) - Improved border drawing guaranteed to show L/R touching part borders. TODO: Top and bottom borders. (Tim) diff --git a/muse2/muse/widgets/knob.cpp b/muse2/muse/widgets/knob.cpp index ae88e2f4..dc41e1c4 100644 --- a/muse2/muse/widgets/knob.cpp +++ b/muse2/muse/widgets/knob.cpp @@ -64,6 +64,9 @@ Knob::Knob(QWidget* parent, const char* name) d_markerColor = palette().dark().color().darker(125); d_dotWidth = 8; + l_slope = 0; + l_const = 100; + setMinimumSize(30,30); setUpdateTime(50); } @@ -93,6 +96,31 @@ void Knob::setTotalAngle (double angle) d_scale.setAngleRange( -0.5 * d_totalAngle, 0.5 * d_totalAngle); } +//------------------------------------------------------------ +// Knob::setRange +// Set the range and step size of the knob +// +// Sets the paramaters that define the shininess of the ring +// surrounding the knob and then proceeds by passing the +// parameters to the parent class' setRange() function. +//------------------------------------------------------------ + +void Knob::setRange(double vmin, double vmax, double vstep, int pagesize) + { + // divide by zero protection. probably too cautious + if (! (vmin == vmax || qMax(-vmin, vmax) == 0)) + { + if (vmin * vmax < 0) + l_slope = 80.0 / qMax(-vmin, vmax); + else + { + l_slope = 80.0 / (vmax - vmin); + l_const = 100 - l_slope * vmin; + } + } + SliderBase::setRange(vmin, vmax, vstep, pagesize); + } + //------------------------------------------------------------ // QwtKnob::drawKnob // const QRect &r -- borders of the knob @@ -132,7 +160,8 @@ void Knob::drawKnob(QPainter* p, const QRect& r) QPen pn; pn.setCapStyle(Qt::FlatCap); - pn.setColor(d_shinyColor.lighter(100+ abs(d_angle*100)/300)); + + pn.setColor(d_shinyColor.lighter(l_const + abs(value() * l_slope))); pn.setWidth(d_shineWidth * 2); p->setPen(pn); p->drawArc(aRect, 0, 360 * 16); diff --git a/muse2/muse/widgets/knob.h b/muse2/muse/widgets/knob.h index 09e13c93..2a553c4e 100644 --- a/muse2/muse/widgets/knob.h +++ b/muse2/muse/widgets/knob.h @@ -36,6 +36,9 @@ class Knob : public SliderBase, public ScaleIf double d_totalAngle; double d_nTurns; + double l_const; + double l_slope; + QRect kRect; bool _faceColSel; QColor d_faceColor; @@ -62,6 +65,8 @@ class Knob : public SliderBase, public ScaleIf Knob(QWidget* parent = 0, const char *name = 0); ~Knob() {} + void setRange(double vmin, double vmax, double vstep = 0.0, + int pagesize = 1); void setKnobWidth(int w); void setTotalAngle (double angle); void setBorderWidth(int bw); -- cgit v1.2.3 From 6ea3ca331aeef0b0702ff2d3c3e529cd226c5d8b Mon Sep 17 00:00:00 2001 From: Orcan Ogetbil Date: Tue, 16 Aug 2011 03:03:59 +0000 Subject: Remodel the Meter and the VerticalMeter --- muse2/ChangeLog | 2 + muse2/muse/widgets/meter.cpp | 168 ++++++++++++++++++++++++++++++----- muse2/muse/widgets/meter.h | 37 +++++++- muse2/muse/widgets/verticalmeter.cpp | 81 +++++++++++++---- muse2/muse/widgets/verticalmeter.h | 2 +- 5 files changed, 248 insertions(+), 42 deletions(-) (limited to 'muse2') diff --git a/muse2/ChangeLog b/muse2/ChangeLog index d333b4fc..e9be48f4 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,5 @@ +15.08.2011: + - Remodel the Meter and the VerticalMeter (Orcan) 13.08.2011: - Make the shininess of the Knob ring a little smarter (Orcan) 05.08.2011: diff --git a/muse2/muse/widgets/meter.cpp b/muse2/muse/widgets/meter.cpp index 6619d1dc..9f13059e 100644 --- a/muse2/muse/widgets/meter.cpp +++ b/muse2/muse/widgets/meter.cpp @@ -2,11 +2,11 @@ // MusE // Linux Music Editor // $Id: meter.cpp,v 1.4.2.2 2009/05/03 04:14:00 terminator356 Exp $ +// redesigned by oget on 2011/08/15 // // (C) Copyright 2000 Werner Schweer (ws@seh.de) //========================================================= -#include #include #include @@ -30,7 +30,8 @@ Meter::Meter(QWidget* parent, MeterType type) // This is absolutely required for speed! Otherwise painfully slow because we get // full rect paint events even on small scrolls! See help on QPainter::scroll(). setAttribute(Qt::WA_OpaquePaintEvent); - + //setFrameStyle(QFrame::Raised | QFrame::StyledPanel); + mtype = type; overflow = false; val = 0.0; @@ -41,6 +42,57 @@ Meter::Meter(QWidget* parent, MeterType type) redScale = 0; setLineWidth(0); setMidLineWidth(0); + + dark_red_end = QColor(0x8e0000); + dark_red_begin = QColor(0x8e3800); + + dark_yellow_end = QColor(0x8e6800); + dark_yellow_center = QColor(0x8e8e00); + dark_yellow_begin = QColor(0x6a8400); + + dark_green_end = QColor(0x467800); + dark_green_begin = QColor(0x007000); + + light_red_end = QColor(0xff0000); + light_red_begin = QColor(0xdd8800); + + light_yellow_end = QColor(0xddcc00); + light_yellow_center = QColor(0xffff00); + light_yellow_begin = QColor(0xddff00); + + light_green_end = QColor(0x88ff00); + light_green_begin = QColor(0x00ff00); + + mask_center = QColor(225, 225, 225, 64); + mask_edge = QColor(30, 30, 30, 64); + + separator_color = QColor(0x666666); + peak_color = QColor(0xeeeeee); + + darkGradGreen.setColorAt(1, dark_green_begin); + darkGradGreen.setColorAt(0, dark_green_end); + + darkGradYellow.setColorAt(1, dark_yellow_begin); + darkGradYellow.setColorAt(0.5, dark_yellow_center); + darkGradYellow.setColorAt(0, dark_yellow_end); + + darkGradRed.setColorAt(1, dark_red_begin); + darkGradRed.setColorAt(0, dark_red_end); + + lightGradGreen.setColorAt(1, light_green_begin); + lightGradGreen.setColorAt(0, light_green_end); + + lightGradYellow.setColorAt(1, light_yellow_begin); + lightGradYellow.setColorAt(0.5, light_yellow_center); + lightGradYellow.setColorAt(0, light_yellow_end); + + lightGradRed.setColorAt(1, light_red_begin); + lightGradRed.setColorAt(0, light_red_end); + + maskGrad.setColorAt(0, mask_edge); + maskGrad.setColorAt(0.5, mask_center); + maskGrad.setColorAt(1, mask_edge); + } //--------------------------------------------------------- @@ -106,17 +158,23 @@ void Meter::setRange(double min, double max) // paintEvent //--------------------------------------------------------- -void Meter::paintEvent(QPaintEvent* /*ev*/) +void Meter::paintEvent(QPaintEvent* ev) { // TODO: Could make better use of event rectangle, for speed. QPainter p(this); + //p.setRenderHint(QPainter::Antialiasing); double range = maxScale - minScale; - + /* int fw = frameWidth(); int w = width() - 2*fw; int h = height() - 2*fw; + */ + + QRect rect = ev->rect(); + int w = rect.width(); + int h = rect.height(); int yv; if(mtype == DBMeter) @@ -135,10 +193,17 @@ void Meter::paintEvent(QPaintEvent* /*ev*/) ymax = maxVal == 0 ? 0 : int(((maxScale - (fast_log10(maxVal) * 20.0)) * h)/range); else ymax = maxVal == 0 ? 0 : int(((maxScale - maxVal) * h)/range); - p.setPen(Qt::white); + p.setPen(peak_color); p.drawLine(0, ymax, w, ymax); + + // Draw the transparent layer on top of everything to give a 3d look + maskGrad.setStart(QPointF(0, 0)); + maskGrad.setFinalStop(QPointF(w, 0)); + p.fillRect(0, 0, w, h, QBrush(maskGrad)); + } + //--------------------------------------------------------- // drawVU //--------------------------------------------------------- @@ -150,60 +215,119 @@ void Meter::drawVU(QPainter& p, int w, int h, int yv) double range = maxScale - minScale; int y1 = int((maxScale - redScale) * h / range); int y2 = int((maxScale - yellowScale) * h / range); - + + darkGradGreen.setStart(QPointF(0, y2)); + darkGradGreen.setFinalStop(QPointF(0, h)); + darkGradYellow.setStart(QPointF(0, y1)); + darkGradYellow.setFinalStop(QPointF(0, y2)); + darkGradRed.setStart(QPointF(0, 0)); + darkGradRed.setFinalStop(QPointF(0, y1)); + + lightGradGreen.setStart(QPointF(0, y2)); + lightGradGreen.setFinalStop(QPointF(0, h)); + lightGradYellow.setStart(QPointF(0, y1)); + lightGradYellow.setFinalStop(QPointF(0, y2)); + lightGradRed.setStart(QPointF(0, 0)); + lightGradRed.setFinalStop(QPointF(0, y1)); + if(yv < y1) { // Red section: - p.fillRect(0, 0, w, yv, QBrush(0x8e0000)); // dark red - p.fillRect(0, yv, w, y1-yv, QBrush(0xff0000)); // light red + p.fillRect(0, 0, w, yv, QBrush(darkGradRed)); // dark red + p.fillRect(0, yv, w, y1-yv, QBrush(lightGradRed)); // light red // Yellow section: - p.fillRect(0, y1, w, y2-y1, QBrush(0xffff00)); // light yellow + p.fillRect(0, y1, w, y2-y1, QBrush(lightGradYellow)); // light yellow // Green section: - p.fillRect(0, y2, w, h-y2, QBrush(0x00ff00)); // light green + p.fillRect(0, y2, w, h-y2, QBrush(lightGradGreen)); // light green } else if(yv < y2) { // Red section: - p.fillRect(0, 0, w, y1, QBrush(0x8e0000)); // dark red + p.fillRect(0, 0, w, y1, QBrush(darkGradRed)); // dark red // Yellow section: - p.fillRect(0, y1, w, yv-y1, QBrush(0x8e8e00)); // dark yellow - p.fillRect(0, yv, w, y2-yv, QBrush(0xffff00)); // light yellow + p.fillRect(0, y1, w, yv-y1, QBrush(darkGradYellow)); // dark yellow + p.fillRect(0, yv, w, y2-yv, QBrush(lightGradYellow)); // light yellow // Green section: - p.fillRect(0, y2, w, h-y2, QBrush(0x00ff00)); // light green + p.fillRect(0, y2, w, h-y2, QBrush(lightGradGreen)); // light green } else //if(yv <= y3) { // Red section: - p.fillRect(0, 0, w, y1, QBrush(0x8e0000)); // dark red + p.fillRect(0, 0, w, y1, QBrush(darkGradRed)); // dark red // Yellow section: - p.fillRect(0, y1, w, y2-y1, QBrush(0x8e8e00)); // dark yellow + p.fillRect(0, y1, w, y2-y1, QBrush(darkGradYellow)); // dark yellow // Green section: - p.fillRect(0, y2, w, yv-y2, QBrush(0x007000)); // dark green - p.fillRect(0, yv, w, h-yv, QBrush(0x00ff00)); // light green + p.fillRect(0, y2, w, yv-y2, QBrush(darkGradGreen)); // dark green + p.fillRect(0, yv, w, h-yv, QBrush(lightGradGreen)); // light green } + + p.fillRect(0,y1, w, 1, separator_color); + p.fillRect(0,y2, w, 1, separator_color); + } else { - p.fillRect(0, 0, w, yv, QBrush(0x007000)); // dark green - p.fillRect(0, yv, w, h-yv, QBrush(0x00ff00)); // light green + darkGradGreen.setStart(QPointF(0, 0)); + darkGradGreen.setFinalStop(QPointF(0, h)); + + lightGradGreen.setStart(QPointF(0, 0)); + lightGradGreen.setFinalStop(QPointF(0, h)); + + p.fillRect(0, 0, w, yv, QBrush(darkGradGreen)); // dark green + p.fillRect(0, yv, w, h-yv, QBrush(lightGradGreen)); // light green } + } //--------------------------------------------------------- // resizeEvent //--------------------------------------------------------- -void Meter::resizeEvent(QResizeEvent* /*ev*/) +void Meter::resizeEvent(QResizeEvent* ev) { - + // Round corners of the widget. + + QSize size = ev->size(); + int w = size.width(); + int h = size.height(); + QPainterPath rounded_rect; + rounded_rect.addRoundedRect(0,0,w,h, w/2.5, w/3); + QRegion maskregion(rounded_rect.toFillPolygon().toPolygon()); + setMask(maskregion); + + /* + // Another method to do the above. I don't know yet which one is more efficient - Orcan + QRect rect(0,0,w,h); + int r = 6; + + QRegion region; + // middle and borders + region += rect.adjusted(r, 0, -r, 0); + region += rect.adjusted(0, r, 0, -r); + // top left + QRect corner(rect.topLeft(), QSize(r*2, r*2)); + region += QRegion(corner, QRegion::Ellipse); + // top right + corner.moveTopRight(rect.topRight()); + region += QRegion(corner, QRegion::Ellipse); + // bottom left + corner.moveBottomLeft(rect.bottomLeft()); + region += QRegion(corner, QRegion::Ellipse); + // bottom right + corner.moveBottomRight(rect.bottomRight()); + region += QRegion(corner, QRegion::Ellipse); + // return region; + setMask(region); + */ + } //--------------------------------------------------------- diff --git a/muse2/muse/widgets/meter.h b/muse2/muse/widgets/meter.h index cced6e7a..848ae855 100644 --- a/muse2/muse/widgets/meter.h +++ b/muse2/muse/widgets/meter.h @@ -2,6 +2,7 @@ // MusE // Linux Music Editor // $Id: meter.h,v 1.1.1.1.2.2 2009/05/03 04:14:00 terminator356 Exp $ +// redesigned by oget on 2011/08/15 // // (C) Copyright 2000 Werner Schweer (ws@seh.de) //========================================================= @@ -20,6 +21,41 @@ class Meter : public QFrame { Q_OBJECT public: enum MeterType {DBMeter, LinMeter}; + + protected: + QLinearGradient darkGradRed; + QColor dark_red_end; + QColor dark_red_begin; + + QLinearGradient darkGradYellow; + QColor dark_yellow_end; + QColor dark_yellow_center; + QColor dark_yellow_begin; + + QLinearGradient darkGradGreen; + QColor dark_green_end; + QColor dark_green_begin; + + QLinearGradient lightGradRed; + QColor light_red_end; + QColor light_red_begin; + + QLinearGradient lightGradYellow; + QColor light_yellow_end; + QColor light_yellow_center; + QColor light_yellow_begin; + + QLinearGradient lightGradGreen; + QColor light_green_end; + QColor light_green_begin; + + QLinearGradient maskGrad; + QColor mask_center; + QColor mask_edge; + + QColor separator_color;; + QColor peak_color; + private: MeterType mtype; bool overflow; @@ -30,7 +66,6 @@ class Meter : public QFrame { void drawVU(QPainter& p, int, int, int); - void paintEvent(QPaintEvent*); void resizeEvent(QResizeEvent*); void mousePressEvent(QMouseEvent*); diff --git a/muse2/muse/widgets/verticalmeter.cpp b/muse2/muse/widgets/verticalmeter.cpp index dbe50723..76f8dcd1 100644 --- a/muse2/muse/widgets/verticalmeter.cpp +++ b/muse2/muse/widgets/verticalmeter.cpp @@ -2,11 +2,11 @@ // MusE // Linux Music Editor // $Id: meter.cpp,v 1.4.2.2 2009/05/03 04:14:00 terminator356 Exp $ +// redesigned by oget on 2011/08/15 // // (C) Copyright 2000 Werner Schweer (ws@seh.de) //========================================================= -#include #include #include @@ -107,7 +107,7 @@ void VerticalMeter::setRange(double min, double max) // paintEvent //--------------------------------------------------------- -void VerticalMeter::paintEvent(QPaintEvent* /*ev*/) +void VerticalMeter::paintEvent(QPaintEvent* ev) { // TODO: Could make better use of event rectangle, for speed. @@ -115,9 +115,15 @@ void VerticalMeter::paintEvent(QPaintEvent* /*ev*/) double range = maxScale - minScale; + /* int fw = frameWidth(); int w = width() - 2*fw; int h = height() - 2*fw; + */ + + QRect rect = ev->rect(); + int w = rect.width(); + int h = rect.height(); int xv; @@ -139,8 +145,13 @@ void VerticalMeter::paintEvent(QPaintEvent* /*ev*/) xcenter = maxVal == 0 ? 0 : int(((maxScale - (fast_log10(0) * 20.0)) * w)/range); else xcenter = maxVal == 0 ? 0 : int(((0) * w)/range); - p.setPen(Qt::white); + p.setPen(peak_color); p.drawLine(xcenter, 0, xcenter, h); + + // Draw the transparent layer on top of everything to give a 3d look + maskGrad.setStart(QPointF(0, 0)); + maskGrad.setFinalStop(QPointF(0, h)); + p.fillRect(0, 0, w, h, QBrush(maskGrad)); } //--------------------------------------------------------- @@ -154,58 +165,92 @@ void VerticalMeter::drawVU(QPainter& p, int w, int h, int xv) double range = maxScale - minScale; int x1 = int((maxScale - redScale) * w / range); int x2 = int((maxScale - yellowScale) * w / range); + + darkGradGreen.setStart(QPointF(x2, 0)); + darkGradGreen.setFinalStop(QPointF(w, 0)); + darkGradYellow.setStart(QPointF(x1, 0)); + darkGradYellow.setFinalStop(QPointF(x2, 0)); + darkGradRed.setStart(QPointF(0, 0)); + darkGradRed.setFinalStop(QPointF(x1, 0)); + + lightGradGreen.setStart(QPointF(x2, 0)); + lightGradGreen.setFinalStop(QPointF(w, 0)); + lightGradYellow.setStart(QPointF(x1, 0)); + lightGradYellow.setFinalStop(QPointF(x2, 0)); + lightGradRed.setStart(QPointF(0, 0)); + lightGradRed.setFinalStop(QPointF(x1, 0)); + if(xv < x1) { // Red section: - p.fillRect(0, 0, xv, h, QBrush(0x8e0000)); // dark red - p.fillRect(xv, 0, x1-xv, h, QBrush(0xff0000)); // light red + p.fillRect(0, 0, xv, h, QBrush(darkGradRed)); // dark red + p.fillRect(xv, 0, x1-xv, h, QBrush(lightGradRed)); // light red // Yellow section: - p.fillRect(x1, 0, x2-x1, h, QBrush(0xffff00)); // light yellow + p.fillRect(x1, 0, x2-x1, h, QBrush(lightGradYellow)); // light yellow // Green section: - p.fillRect(x2, 0, w-x2, h, QBrush(0x00ff00)); // light green + p.fillRect(x2, 0, w-x2, h, QBrush(lightGradGreen)); // light green } else if(xv < x2) { // Red section: - p.fillRect(0, 0, x1, h, QBrush(0x8e0000)); // dark red + p.fillRect(0, 0, x1, h, QBrush(darkGradRed)); // dark red // Yellow section: - p.fillRect(x1, 0, xv-x1, h, QBrush(0x8e8e00)); // dark yellow - p.fillRect(xv, 0, x2-xv, h, QBrush(0xffff00)); // light yellow + p.fillRect(x1, 0, xv-x1, h, QBrush(darkGradYellow)); // dark yellow + p.fillRect(xv, 0, x2-xv, h, QBrush(lightGradYellow)); // light yellow // Green section: - p.fillRect(x2, 0, w-x2, h, QBrush(0x00ff00)); // light green + p.fillRect(x2, 0, w-x2, h, QBrush(lightGradGreen)); // light green } else //if(yv <= y3) { // Red section: - p.fillRect(0, 0, x1, h, QBrush(0x8e0000)); // dark red + p.fillRect(0, 0, x1, h, QBrush(darkGradRed)); // dark red // Yellow section: - p.fillRect(x1, 0, x2-x1, h, QBrush(0x8e8e00)); // dark yellow + p.fillRect(x1, 0, x2-x1, h, QBrush(darkGradYellow)); // dark yellow // Green section: - p.fillRect(x2, 0, xv-x2, h, QBrush(0x007000)); // dark green - p.fillRect(xv, 0, w-xv, h, QBrush(0x00ff00)); // light green + p.fillRect(x2, 0, xv-x2, h, QBrush(darkGradGreen)); // dark green + p.fillRect(xv, 0, w-xv, h, QBrush(lightGradGreen)); // light green } + + p.fillRect(x1,0, 1, h, separator_color); + p.fillRect(x2,0, 1, h, separator_color); + } else { - p.fillRect(0, 0, xv, h, QBrush(0x00ff00)); // dark green - p.fillRect(xv, 0, w-xv, h, QBrush(0x007000)); // light green + darkGradGreen.setStart(QPointF(0, 0)); + darkGradGreen.setFinalStop(QPointF(w, 0)); + + lightGradGreen.setStart(QPointF(0, 0)); + lightGradGreen.setFinalStop(QPointF(w, 0)); + + p.fillRect(0, 0, xv, h, QBrush(lightGradGreen)); // light green + p.fillRect(xv, 0, w-xv, h, QBrush(darkGradGreen)); // dark green } + } //--------------------------------------------------------- // resizeEvent //--------------------------------------------------------- -void VerticalMeter::resizeEvent(QResizeEvent* /*ev*/) +void VerticalMeter::resizeEvent(QResizeEvent* ev) { + // Round corners of the widget. + QSize size = ev->size(); + int w = size.width(); + int h = size.height(); + QPainterPath rounded_rect; + rounded_rect.addRoundedRect(0,0,w,h, h/3, h/2.5); + QRegion maskregion(rounded_rect.toFillPolygon().toPolygon()); + setMask(maskregion); } diff --git a/muse2/muse/widgets/verticalmeter.h b/muse2/muse/widgets/verticalmeter.h index facc8b8c..9613ec43 100644 --- a/muse2/muse/widgets/verticalmeter.h +++ b/muse2/muse/widgets/verticalmeter.h @@ -9,9 +9,9 @@ #ifndef __VERTICALMETER_H__ #define __VERTICALMETER_H__ -#include #include "meter.h" +class QPaintEvent; class QResizeEvent; class QMouseEvent; class QPainter; -- cgit v1.2.3 From 96cd2ef23505deaadb030ea0f1ef284e8a753452 Mon Sep 17 00:00:00 2001 From: "Tim E. Real" Date: Tue, 16 Aug 2011 07:40:48 +0000 Subject: More drawing fixes, improved accuracy (grids, timescales, edges, markers guaranteed to align now). Much drawing changed to device (pixel) space instead of virtual space, for accuracy. Fixed display of audio automation graphs. (But not editing). --- muse2/ChangeLog | 4 + muse2/muse/app.cpp | 4 +- muse2/muse/arranger/pcanvas.cpp | 457 ++++++++++++++++++++++++-------------- muse2/muse/arranger/pcanvas.h | 2 +- muse2/muse/arranger/tlist.cpp | 3 +- muse2/muse/ctrl/ctrlcanvas.cpp | 3 - muse2/muse/master/master.cpp | 3 - muse2/muse/midiedit/dcanvas.cpp | 4 +- muse2/muse/midiedit/dlist.cpp | 12 +- muse2/muse/midiedit/drumedit.cpp | 2 +- muse2/muse/midiedit/pianoroll.cpp | 2 +- muse2/muse/midiedit/prcanvas.cpp | 155 ++++++++----- muse2/muse/midiedit/scoreedit.cpp | 2 +- muse2/muse/widgets/canvas.cpp | 31 ++- muse2/muse/widgets/view.cpp | 142 ++++++++++-- muse2/muse/widgets/view.h | 1 + 16 files changed, 563 insertions(+), 264 deletions(-) (limited to 'muse2') diff --git a/muse2/ChangeLog b/muse2/ChangeLog index e9be48f4..562361c7 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,7 @@ +16.08.2011: + - More drawing fixes, improved accuracy (grids, timescales, edges, markers guaranteed to align now). (Tim p4.0.30) + Much drawing changed to device (pixel) space instead of virtual space, for accuracy. + - Fixed display of audio automation graphs. (But not editing). (Tim) 15.08.2011: - Remodel the Meter and the VerticalMeter (Orcan) 13.08.2011: diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index 3abb116f..2227e7b0 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -1849,7 +1849,7 @@ void MusE::closeEvent(QCloseEvent* event) n = QMessageBox::warning(this, appName, tr("The current Project contains unsaved data\n" "Save Current Project?"), - tr("&Save"), tr("&Skip"), tr("&Cancel"), 0, 2); + tr("&Save"), tr("S&kip"), tr("&Cancel"), 0, 2); if (n == 0) { if (!save()) // dont quit if save failed { @@ -3212,7 +3212,7 @@ bool MusE::clearSong(bool clear_all) tr("The current Project contains unsaved data\n" "Load overwrites current Project:\n" "Save Current Project?"), - tr("&Save"), tr("&Skip"), tr("&Abort"), 0, 2); + tr("&Save"), tr("S&kip"), tr("&Abort"), 0, 2); switch (n) { case 0: if (!save()) // abort if save failed diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index 402e8035..82f2de45 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -70,17 +70,9 @@ NPart::NPart(Part* e) : CItem(Event(), e) leftBorderTouches = false; rightBorderTouches = false; - int th = track()->height(); int y = track()->y(); - - ///setPos(QPoint(e->tick(), y + 1)); setPos(QPoint(e->tick(), y)); - - ///setBBox(QRect(e->tick(), y + 1, e->lenTick(), th)); - // NOTE: For adjustable border size: If using a two-pixel border width while drawing, use second line. - // If one-pixel width, use first line. Tim. - //setBBox(QRect(e->tick(), y, e->lenTick(), th)); - setBBox(QRect(e->tick(), y + 1, e->lenTick(), th)); + setBBox(QRect(e->tick(), y, e->lenTick(), track()->height())); } //--------------------------------------------------------- @@ -1727,22 +1719,24 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) if((unsigned int)to > part->lenTick()) to = part->lenTick(); + bool clone = part->events()->arefCount() > 1; + QBrush brush; + + QRect r = item->bbox(); + // Compensation required for two pixel wide border. FIXME Prefer to do this after the map, but r is needed below. + r.moveTop(r.y() + rmapyDev(1)); + //QRect rr = p.transform().mapRect(r); // Gives inconsistent positions. Source shows wrong operation for our needs. + QRect rr = map(r); // Use our own map instead. + // Item bounding box x is in tick coordinates, same as rectangle. - if(item->bbox().intersect(rect).isNull()) + //if(item->bbox().intersect(rect).isNull()) + //if((item->bbox() & rect).isNull()) + if((rr & map(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()); @@ -1762,9 +1756,9 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) 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 xs_j = xs_0 + 8; + if(xs_j > xe_0) + xs_j = xe_0; int xe_1 = xe_0 - 1; if(xe_1 < xs_0) @@ -1772,11 +1766,11 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) 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 xe_j = xe_0 - 8; + if(xe_j < xs_0) + xe_j = xs_0; - int ys_0 = rr.y(); + int ys_0 = rr.y(); int ye_0 = ys_0 + rr.height(); int ys_1 = ys_0 + 1; if(ys_1 > ye_0) @@ -1784,6 +1778,9 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) int ys_2 = ys_0 + 2; if(ys_2 > ye_0) ys_2 = ye_0; + int ys_3 = ys_0 + 3; + if(ys_3 > ye_0) + ys_3 = ye_0; int ye_1 = ye_0 - 1; if(ye_1 < ys_0) @@ -1834,13 +1831,14 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) int h = rr.height(); double s = double(h) / 4.0; - int y0 = rr.y(); - int y1 = y0 + lrint(s); + int y0 = ys_0; + //int y1 = y0 + lrint(s); int y2 = y0 + lrint(s * 2.0); - int y3 = y0 + lrint(s * 3.0); + //int y3 = y0 + lrint(s * 3.0); int y4 = y0 + h; - QPoint points[16]; + //QPoint points[12]; + QPoint points[8]; int pts; // @@ -1854,41 +1852,62 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) pts = 0; if(het == (Part::LeftEventsHidden | Part::RightEventsHidden)) { + //points[pts++] = QPoint(xs_0, y0); + //points[pts++] = QPoint(xe_0, y0); + //points[pts++] = QPoint(xe_j, y1); + //points[pts++] = QPoint(xe_0, y2); + //points[pts++] = QPoint(xe_j, y3); + //points[pts++] = QPoint(xe_0, y4); + //points[pts++] = QPoint(xs_0, y4); + //points[pts++] = QPoint(xs_j, y3); + //points[pts++] = QPoint(xs_0, y2); + //points[pts++] = QPoint(xs_j, y1); + 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_j, y2); 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); + points[pts++] = QPoint(xs_j, y2); + 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_j, y3); + //points[pts++] = QPoint(xs_0, y2); + //points[pts++] = QPoint(xs_j, y1); + 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); + points[pts++] = QPoint(xs_j, y2); + 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_j, y1); + //points[pts++] = QPoint(xe_0, y2); + //points[pts++] = QPoint(xe_j, y3); + //points[pts++] = QPoint(xe_0, y4); + //points[pts++] = QPoint(xs_0, y4); + 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_j, y2); points[pts++] = QPoint(xe_0, y4); points[pts++] = QPoint(xs_0, y4); + p.drawConvexPolygon(points, pts); } @@ -1904,30 +1923,40 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) //else // color_brightness=32; // otherwise use dark color if ((brightness >= 12000 && !part->selected())) - color_brightness=32; // too light: use dark color + color_brightness=96; //0; // too light: use dark color else - color_brightness=223; // too dark: use lighter color + color_brightness=180; //255; // 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_j, y3); + //points[pts++] = QPoint(xe_0, y2); + //points[pts++] = QPoint(xe_j, y1); + 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); + points[pts++] = QPoint(xe_j, y2); + p.drawConvexPolygon(points, pts); } if(het & Part::LeftEventsHidden) { pts = 0; + //points[pts++] = QPoint(xs_0, y0); + //points[pts++] = QPoint(xs_j, y1); + //points[pts++] = QPoint(xs_0, y2); + //points[pts++] = QPoint(xs_j, y3); + //points[pts++] = QPoint(xs_0, y4); + 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_j, y2); points[pts++] = QPoint(xs_0, y4); + p.drawConvexPolygon(points, pts); } } @@ -1985,14 +2014,6 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) // 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]); @@ -2015,52 +2036,57 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) penNormal1V.setCosmetic(true); penNormal2V.setCosmetic(true); + //pc = Qt::white; + //pc = Qt::darkGray; + //QPen penHidden1(pc); + //QPen penHidden2(pc, 2.0); + //penHidden2.setCosmetic(true); + QVector customDashPattern; + if(clone) { - customDashPattern << 4.0 << 8.0; + customDashPattern << 4.0 << 6.0; penSelect1H.setDashPattern(customDashPattern); penNormal1H.setDashPattern(customDashPattern); - //penSelect1V.setDashPattern(customDashPattern); - //penNormal1V.setDashPattern(customDashPattern); + penSelect1V.setDashPattern(customDashPattern); + penNormal1V.setDashPattern(customDashPattern); + penSelect1V.setDashOffset(2.0); + penNormal1V.setDashOffset(2.0); + //penHidden1.setDashPattern(customDashPattern); customDashPattern.clear(); - customDashPattern << 2.0 << 4.0; + customDashPattern << 2.0 << 3.0; penSelect2H.setDashPattern(customDashPattern); penNormal2H.setDashPattern(customDashPattern); - //penSelect2V.setDashPattern(customDashPattern); - //penNormal2V.setDashPattern(customDashPattern); + penSelect2V.setDashPattern(customDashPattern); + penNormal2V.setDashPattern(customDashPattern); + penSelect2V.setDashOffset(1.0); + penNormal2V.setDashOffset(1.0); + //penHidden2.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 + QLine l1(lbt?xs_1:xs_0, ys_0, rbt?xe_1:xe_0, ys_0); // Top + //QLine l2(rbt?xe_1:xe_0, rbt?ys_1:ys_2, rbt?xe_1:xe_0, rbt?ye_1:ye_2); // Right + QLine l2(rbt?xe_1:xe_0, ys_0, rbt?xe_1:xe_0, ye_0); // Right + QLine l3(lbt?xs_1:xs_0, ye_0, rbt?xe_1:xe_0, ye_0); // Bottom + //QLine l4(xs_0, lbt?ys_1:ys_2, xs_0, lbt?ye_1:ye_2); // Left + QLine l4(xs_0, ys_0, xs_0, ye_0); // Left - if(het & Part::RightEventsHidden) - p.setPen(((NPart*)item)->rightBorderTouches ? penHidden1 : penHidden2); - else + //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 + p.drawLine(l2); // Right line + /* int xx = rbt?xe_1:xe_0; if(clone) { @@ -2075,18 +2101,20 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) } 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(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 + p.drawLine(l4); // Left line + /* xx = xs_0; if(clone) { @@ -2101,6 +2129,7 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) } 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 @@ -2133,8 +2162,9 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) p.setPen(Qt::white); p.drawText(tr, Qt::AlignBottom|Qt::AlignLeft, part->name()); } + p.restore(); - p.setWorldMatrixEnabled(true); + //p.setWorldMatrixEnabled(true); } //--------------------------------------------------------- @@ -2174,9 +2204,9 @@ void PartCanvas::drawMidiPart(QPainter& p, const QRect&, EventList* events, Midi //else // color_brightness=64; // otherwise use dark color if (brightness >= 12000 && !pt->selected()) - color_brightness=64; // too bright: use dark color + color_brightness=64; // 96; // too bright: use dark color else - color_brightness=192; // too dark: use lighter color + color_brightness=190; //160; // too dark: use lighter color } else color_brightness=80; @@ -2392,8 +2422,10 @@ void PartCanvas::drawMidiPart(QPainter& p, const QRect&, EventList* events, Midi void PartCanvas::drawWavePart(QPainter& p, const QRect& bb, WavePart* wp, const QRect& _pr) { - QRect rr = p.worldMatrix().mapRect(bb); - QRect pr = p.worldMatrix().mapRect(_pr); + //QRect rr = p.worldMatrix().mapRect(bb); // Gives inconsistent positions. Source shows wrong operation for our needs. + QRect rr = map(bb); // Use our own map instead. + //QRect pr = p.worldMatrix().mapRect(_pr); + QRect pr = map(_pr); p.save(); p.resetTransform(); @@ -3066,9 +3098,22 @@ void PartCanvas::viewDropEvent(QDropEvent* event) void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) { int x = rect.x(); - int y = rect.y(); + //int y = rect.y(); int w = rect.width(); - int h = rect.height(); + //int h = rect.height(); + + // Changed to draw in device coordinate space instead of virtual, transformed space. Tim. p4.0.30 + + //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. + + p.save(); + p.setWorldMatrixEnabled(false); + + int mx = mr.x(); + int my = mr.y(); + int mw = mr.width(); + int mh = mr.height(); ////////// // GRID // @@ -3086,13 +3131,17 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) AL::sigmap.tickValues(x, &bar, &beat, &tick); for (;;) { int xt = AL::sigmap.bar2tick(bar++, 0, 0); + //int xt = mapx(AL::sigmap.bar2tick(bar++, 0, 0)); if (xt >= x + w) + //if (xt >= mx + mw) break; if (!((bar-1) % 4)) p.setPen(baseColor.dark(115)); else p.setPen(baseColor); - p.drawLine(xt, y, xt, y+h); + //p.drawLine(xt, y, xt, y+h); + int xtm = mapx(xt); + p.drawLine(xtm, my, xtm, my+mh); // append int noDivisors=0; @@ -3118,20 +3167,28 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) noDivisors=noDivisors/2; } p.setPen(baseColor); + int xx; for (int t=1;t< noDivisors;t++) - p.drawLine(xt+r*t, y, xt+r*t, y+h); + { + //p.drawLine(xt+r*t, y, xt+r*t, y+h); + xx = mapx(xt + r * t); + p.drawLine(xx, my, xx, my+mh); + } } } } + //-------------------------------- // horizontal lines //-------------------------------- TrackList* tl = song->tracks(); - int yy = 0; + //int yy = 0; + int yy = -rmapy(yorg) - ypos; int th; for (iTrack it = tl->begin(); it != tl->end(); ++it) { - if (yy > y + h) + //if (yy > y + h) + if (yy > my + mh) break; Track* track = *it; th = track->height(); @@ -3140,22 +3197,46 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) if (config.canvasShowGrid && (track->isMidiTrack() || track->type() == Track::WAVE)) // Tim. { p.setPen(baseColor.dark(130)); - p.drawLine(x, yy + th, x + w, yy + th); // Tim. - p.setPen(baseColor); - } - if (!track->isMidiTrack() && (track->type() != Track::WAVE)) { - QRect r = rect & QRect(x, yy, w, track->height()); - drawAudioTrack(p, r, (AudioTrack*)track); - p.setPen(baseColor); + //p.drawLine(x, yy + th, x + w, yy + th); + p.drawLine(mx, yy + th, mx + mw, yy + th); + //p.setPen(baseColor); } - if (!track->isMidiTrack()) { // draw automation - QRect r = rect & QRect(x, yy, w, track->height()); - drawAutomation(p, r, (AudioTrack*)track); - p.setPen(baseColor); - - } - yy += track->height(); + + // The update rectangle (rect and mr etc) is clipped at x<0 and y<0 in View::pdraw(). + // The 'corrupt drawing' bug of drawAudioTrack was actually because the recently added gradient + // used the update rectangle, so the gradient was also being clipped at 0,0. + // One could remove that limiter, but no, that is the correct way. So instead let's construct a + // 'pseudo bounding box' (half update rectangle, half bounding box), un-clipped. The gradient needs this! + // + // Here is a different situation than PartCanvas::drawItem which uses un-clipped part bounding boxes and + // 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)) + { + if (!track->isMidiTrack() && (track->type() != Track::WAVE)) { + //QRect r = rect & QRect(x, yy, w, track->height()); + drawAudioTrack(p, mr, r, (AudioTrack*)track); + //p.setPen(baseColor); + } + + // 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() != Track::WAVE)) { + //QRect r = rect & QRect(x, yy, w, track->height()); + drawAutomation(p, r, (AudioTrack*)track); + //p.setPen(baseColor); + } + //p.setWorldMatrixEnabled(false); + */ } + yy += th; + } + + p.restore(); + //p.setWorldMatrixEnabled(true); } //--------------------------------------------------------- @@ -3163,36 +3244,55 @@ void PartCanvas::drawCanvas(QPainter& p, const QRect& rect) //--------------------------------------------------------- void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) { - int x = rect.x(); - int y = rect.y(); - int w = rect.width(); - int h = rect.height(); + //int x = rect.x(); + //int y = rect.y(); + //int w = rect.width(); + //int h = rect.height(); + // Changed to draw in device coordinate space instead of virtual, transformed space. Tim. p4.0.30 + + //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. + + //printf("PartCanvas::drawTopItem x:%d y:%d w:%d h:%d\n", rect.x(), rect.y(), rect.width(), rect.height()); + + int mx = mr.x(); + int my = mr.y(); + int mw = mr.width(); + int mh = mr.height(); + QColor baseColor(config.partCanvasBg.light(104)); - p.setPen(baseColor); + //p.setPen(baseColor); + p.save(); + p.setWorldMatrixEnabled(false); + TrackList* tl = song->tracks(); - int yy = 0; + int yoff = -rmapy(yorg) - ypos; + //int yy = 0; + int yy = yoff; int th; for (iTrack it = tl->begin(); it != tl->end(); ++it) { - if (yy > y + h) + //if (yy > y + h) + if (yy > my + mh) break; Track* track = *it; th = track->height(); if (!th) continue; if (!track->isMidiTrack()) { // draw automation - QRect r = rect & QRect(x, yy, w, track->height()); - drawAutomation(p, r, (AudioTrack*)track); - p.setPen(baseColor); - + //QRect r = rect & QRect(x, yy, w, track->height()); + QRect r(mx, yy, mw, th); + if(r.intersects(mr)) + { + drawAutomation(p, r, (AudioTrack*)track); + //p.setPen(baseColor); + } } - yy += track->height(); + //yy += track->height(); + yy += th; } - QRect rr = p.worldMatrix().mapRect(rect); - - unsigned int startPos = audio->getStartRecordPos().tick(); if (song->punchin()) startPos=song->lpos(); @@ -3200,38 +3300,47 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) int width = mapx(song->cpos()) - mapx(startPos); if (song->cpos() < startPos) { + //p.setWorldMatrixEnabled(true); + p.restore(); return; // no drawing if we are before punch out } if (song->punchout() && song->cpos() > song->rpos()) { + //p.setWorldMatrixEnabled(true); + p.restore(); return; // no drawing if we are beyond punch out. } - p.save(); - p.resetTransform(); + ///p.save(); + ///p.resetTransform(); // write recording while it happens to get feedback // should be enhanced with solution that draws waveform also - int yPos=0; + //int yPos=0; + int yPos = yoff; if (song->record() && audio->isPlaying()) { for (iTrack it = tl->begin(); it != tl->end(); ++it) { Track* track = *it; + th = track->height(); + if (!th) + continue; if (track->recordFlag()) { QPen pen(Qt::black, 0, Qt::SolidLine); p.setPen(pen); QColor c(config.partColors[0]); c.setAlpha(config.globalAlphaBlend); - QLinearGradient gradient(QPoint(startx,yPos), QPoint(startx,yPos+track->height())); + QLinearGradient gradient(QPoint(startx,yPos), QPoint(startx,yPos+th)); gradient.setColorAt(0, c); gradient.setColorAt(1, c.darker()); QBrush cc(gradient); p.setBrush(cc); - p.drawRect(startx,yPos, width, track->height()); + p.drawRect(startx,yPos, width, th); } - yPos+=track->height(); + yPos+=th; } } p.restore(); + //p.setWorldMatrixEnabled(true); // draw midi events on yPos=0; @@ -3275,53 +3384,71 @@ void PartCanvas::drawTopItem(QPainter& p, const QRect& rect) } } - } //--------------------------------------------------------- // drawAudioTrack //--------------------------------------------------------- -void PartCanvas::drawAudioTrack(QPainter& p, const QRect& r, AudioTrack* /* t */) +void PartCanvas::drawAudioTrack(QPainter& p, const QRect& r, const QRect& bbox, AudioTrack* /*t*/) { - // 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. - QPen pen(Qt::black, 0, Qt::SolidLine); - //p.setPen(QPen(Qt::black, 2, Qt::SolidLine)); - //pen.setCosmetic(true); - p.setPen(pen); - //p.setBrush(Qt::gray); - + QRect mr = r & bbox; + if(mr.isNull()) + return; + int mx = mr.x(); + int my = mr.y(); + int mw = mr.width(); + int mh = mr.height(); + int mex = bbox.x(); + int mey = bbox.y(); + //int mew = bbox.width(); + int meh = bbox.height(); + + p.setPen(Qt::black); QColor c(Qt::gray); c.setAlpha(config.globalAlphaBlend); - QLinearGradient gradient(r.topLeft(), r.bottomLeft()); + //QLinearGradient gradient(r.topLeft(), r.bottomLeft()); + QLinearGradient gradient(mex + 1, mey + 1, mex + 1, mey + meh - 1); // Inside the border gradient.setColorAt(0, c); gradient.setColorAt(1, c.darker()); - QBrush cc(gradient); - p.setBrush(cc); - p.drawRect(r); - - // Factor in pen stroking size: - //QRect rr(r); - //rr.setHeight(rr.height() -1); + QBrush brush(gradient); + p.fillRect(mr, brush); // p4.0.30 ... -// p.fillRect(r, cc); + //int xx = -rmapx(xorg) - xpos; + //printf("PartCanvas::drawAudioTrack x:%d y:%d w:%d h:%d th:%d xx:%d\n", r.x(), r.y(), r.width(), r.height(), t->height(), xx); + //if(r.x() <= xx) + // p.drawLine(r.x(), r.y(), r.x(), r.y() + r.height()); // The left edge + //p.drawLine(r.x(), r.y(), r.x() + r.width(), r.y()); // The top edge + //p.drawLine(r.x(), r.y() + r.height(), r.x() + r.width(), r.y() + r.height()); // The bottom edge + + if(mex >= mx && mex <= mx + mw) + p.drawLine(mex, my, mex, my + mh - 1); // The left edge + //if(mex + mew >= mx && mex + mew <= mx + mw) + // p.drawLine(mex + mew, my, mex + mew, my + mh - 1); // The right edge. Not used - infinite to the right + if(mey >= my && mey <= my + mh) + p.drawLine(mx, mey, mx + mw - 1, mey); // The top edge + if(mey + meh >= my && mey + meh <= my + mh) + p.drawLine(mx, mey + meh, mx + mw - 1, mey + meh); // The bottom edge. Special for Audio track - draw one past bottom. } //--------------------------------------------------------- // drawAutomation //--------------------------------------------------------- -void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) +void PartCanvas::drawAutomation(QPainter& p, const QRect& rr, AudioTrack *t) { - QRect rr = p.worldMatrix().mapRect(r); + ///QRect rr = p.worldMatrix().mapRect(r); - p.save(); - p.resetTransform(); + ///p.save(); + ///p.resetTransform(); int height=rr.bottom()-rr.top()-4; // limit height + //printf("PartCanvas::drawAutomation x:%d y:%d w:%d h:%d height:%d\n", rr.x(), rr.y(), rr.width(), rr.height(), height); + + p.setBrush(Qt::NoBrush); + CtrlListList* cll = t->controller(); - bool firstRun=true; + ///bool firstRun=true; for(CtrlListList::iterator icll =cll->begin();icll!=cll->end();++icll) { //iCtrlList *icl = icll->second; @@ -3332,7 +3459,8 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) iCtrl ic=cl->begin(); if (!cl->isVisible()) continue; // skip this iteration if this controller isn't in the visible list - p.setPen(QPen(cl->color(),1,Qt::SolidLine)); + ///p.setPen(QPen(cl->color(),1,Qt::SolidLine)); + p.setPen(QPen(cl->color(), 0, Qt::SolidLine)); // First check that there ARE automation, ic == cl->end means no automation if (ic != cl->end()) { @@ -3358,6 +3486,7 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-2)-prevVal*height-1, 3, 3); p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5); + bool firstRun=true; for (; ic !=cl->end(); ++ic) { CtrlVal cv = ic->second; @@ -3378,6 +3507,7 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) } int currentPixel = mapx(tempomap.frame2tick(cv.frame)); + //printf(" line x1:%d x2:%d prevVal:%f nextVal:%f\n", leftX, currentPixel, prevVal, nextVal); p.drawLine( leftX, (rr.bottom()-2)-prevVal*height, currentPixel, @@ -3390,20 +3520,23 @@ void PartCanvas::drawAutomation(QPainter& p, const QRect& r, AudioTrack *t) prevPosFrame=cv.frame; prevVal=nextVal; if (currentPixel > rr.x()+ rr.width()) - goto quitDrawing; + ///goto quitDrawing; + break; // draw a square around the point p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-2, (rr.bottom()-2)-prevVal*height-2, 5, 5); p.drawRect(mapx(tempomap.frame2tick(prevPosFrame))-1, (rr.bottom()-1)-prevVal*height-2, 3, 3); } + //printf(" endline prevVal:%f\n", prevVal); p.drawLine(mapx(tempomap.frame2tick(prevPosFrame)), (rr.bottom()-2)-prevVal*height, rr.x()+rr.width(), (rr.bottom()-2)-prevVal*height); } } -quitDrawing: - p.restore(); +///quitDrawing: + ///p.restore(); + return; } diff --git a/muse2/muse/arranger/pcanvas.h b/muse2/muse/arranger/pcanvas.h index 5f0aabae..05f380e6 100644 --- a/muse2/muse/arranger/pcanvas.h +++ b/muse2/muse/arranger/pcanvas.h @@ -115,7 +115,7 @@ class PartCanvas : public Canvas { //void drawMidiPart(QPainter&, const QRect& rect, EventList* events, MidiTrack*mt, const QRect& r, int pTick, int from, int to); void drawMidiPart(QPainter&, const QRect& rect, EventList* events, MidiTrack*mt, MidiPart*pt, const QRect& r, int pTick, int from, int to); Track* y2Track(int) const; - void drawAudioTrack(QPainter& p, const QRect& r, AudioTrack* track); + void drawAudioTrack(QPainter& p, const QRect& r, const QRect& bbox, AudioTrack* track); void drawAutomation(QPainter& p, const QRect& r, AudioTrack* track); void drawTopItem(QPainter& p, const QRect& rect); diff --git a/muse2/muse/arranger/tlist.cpp b/muse2/muse/arranger/tlist.cpp index d7cda62f..6fe2f31d 100644 --- a/muse2/muse/arranger/tlist.cpp +++ b/muse2/muse/arranger/tlist.cpp @@ -227,8 +227,7 @@ void TList::paint(const QRect& r) for (int index = 0; index < header->count(); ++index) { int section = header->logicalIndex(index); int w = header->sectionSize(section); - //QRect r = p.xForm(QRect(x+2, yy, w-4, trackHeight)); - QRect r = p.combinedTransform().mapRect(QRect(x+2, yy, w-4, trackHeight)); + QRect r = p.combinedTransform().mapRect(QRect(x+2, yy, w-4, trackHeight)); switch (section) { case COL_RECORD: diff --git a/muse2/muse/ctrl/ctrlcanvas.cpp b/muse2/muse/ctrl/ctrlcanvas.cpp index 678cd823..68e29f20 100644 --- a/muse2/muse/ctrl/ctrlcanvas.cpp +++ b/muse2/muse/ctrl/ctrlcanvas.cpp @@ -25,9 +25,6 @@ #include "ctrlpanel.h" #include "midiedit/drummap.h" -extern void drawTickRaster(QPainter& p, int x, int y, - int w, int h, int quant); - static MidiCtrlValList veloList(CTRL_VELOCITY); // dummy //--------------------------------------------------------- diff --git a/muse2/muse/master/master.cpp b/muse2/muse/master/master.cpp index 4a33a8c4..6293e64c 100644 --- a/muse2/muse/master/master.cpp +++ b/muse2/muse/master/master.cpp @@ -22,9 +22,6 @@ #include "icons.h" #include "audio.h" -extern void drawTickRaster(QPainter& p, int x, int y, - int w, int h, int quant); - //--------------------------------------------------------- // Master //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp index 578e2616..d4ee9999 100644 --- a/muse2/muse/midiedit/dcanvas.cpp +++ b/muse2/muse/midiedit/dcanvas.cpp @@ -158,7 +158,7 @@ Undo DrumCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dtyp for(iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c) { Part* opart = ip2c->first; - int diff = ip2c->second.xdiff; + //int diff = ip2c->second.xdiff; if (opart->hasHiddenEvents()) { @@ -465,8 +465,6 @@ void DrumCanvas::drawMoving(QPainter& p, const CItem* item, const QRect& rect) // drawCanvas //--------------------------------------------------------- -extern void drawTickRaster(QPainter& p, int, int, int, int, int); - void DrumCanvas::drawCanvas(QPainter& p, const QRect& rect) { int x = rect.x(); diff --git a/muse2/muse/midiedit/dlist.cpp b/muse2/muse/midiedit/dlist.cpp index 66922e83..d2d5659c 100644 --- a/muse2/muse/midiedit/dlist.cpp +++ b/muse2/muse/midiedit/dlist.cpp @@ -52,15 +52,18 @@ void DList::draw(QPainter& p, const QRect& rect) // else // p.eraseRect(x, yy, w, TH); QHeaderView *h = header; + p.save(); + p.setWorldMatrixEnabled(false); for (int k = 0; k < h->count(); ++k) { int x = h->sectionPosition(k); int w = h->sectionSize(k); - QRect r = p.combinedTransform().mapRect(QRect(x+2, yy, w-4, TH)); + //QRect r = p.combinedTransform().mapRect(QRect(x+2, yy, w-4, TH)); // Gives inconsistent positions. Source shows wrong operation for our needs. + QRect r = map(QRect(x+2, yy, w-4, TH)); // Use our own map instead. QString s; int align = Qt::AlignVCenter | Qt::AlignHCenter; - p.save(); - p.setWorldMatrixEnabled(false); + //p.save(); + //p.setWorldMatrixEnabled(false); switch (k) { case COL_VOL: s.setNum(dm->vol); @@ -114,8 +117,9 @@ void DList::draw(QPainter& p, const QRect& rect) } if (!s.isEmpty()) p.drawText(r, align, s); - p.restore(); + //p.restore(); } + p.restore(); } //--------------------------------------------------- diff --git a/muse2/muse/midiedit/drumedit.cpp b/muse2/muse/midiedit/drumedit.cpp index 1e678432..ee610683 100644 --- a/muse2/muse/midiedit/drumedit.cpp +++ b/muse2/muse/midiedit/drumedit.cpp @@ -229,7 +229,7 @@ DrumEdit::DrumEdit(PartList* pl, QWidget* parent, const char* name, unsigned ini signalMapper->setMapping(nextAction, DrumCanvas::CMD_SELECT_NEXT_PART); // Functions - menuFunctions = menuBar()->addMenu(tr("&Functions")); + menuFunctions = menuBar()->addMenu(tr("Fu&nctions")); menuFunctions->setTearOffEnabled(true); diff --git a/muse2/muse/midiedit/pianoroll.cpp b/muse2/muse/midiedit/pianoroll.cpp index b2fe55ee..9ab5e063 100644 --- a/muse2/muse/midiedit/pianoroll.cpp +++ b/muse2/muse/midiedit/pianoroll.cpp @@ -174,7 +174,7 @@ PianoRoll::PianoRoll(PartList* pl, QWidget* parent, const char* name, unsigned i connect(colorMapper, SIGNAL(mapped(int)), this, SLOT(eventColorModeChanged(int))); - menuFunctions = menuBar()->addMenu(tr("&Functions")); + menuFunctions = menuBar()->addMenu(tr("Fu&nctions")); menuFunctions->setTearOffEnabled(true); diff --git a/muse2/muse/midiedit/prcanvas.cpp b/muse2/muse/midiedit/prcanvas.cpp index eba1a13c..9e99f24d 100644 --- a/muse2/muse/midiedit/prcanvas.cpp +++ b/muse2/muse/midiedit/prcanvas.cpp @@ -37,6 +37,7 @@ #include "song.h" #include "audio.h" #include "functions.h" +#include "gconfig.h" #define CHORD_TIMEOUT 75 @@ -101,7 +102,7 @@ PianoCanvas::PianoCanvas(MidiEditor* pr, QWidget* parent, int sx, int sy) int PianoCanvas::pitch2y(int pitch) const { int tt[] = { - 5, 12, 19, 26, 33, 44, 51, 58, 64, 71, 78, 85 + 5, 13, 19, 26, 34, 44, 52, 58, 65, 71, 78, 85 }; int y = (75 * KH) - (tt[pitch%12] + (7 * KH) * (pitch/12)); if (y < 0) @@ -146,9 +147,23 @@ void PianoCanvas::drawItem(QPainter& p, const CItem* item, QRect r = item->bbox(); if(!virt()) r.moveCenter(map(item->pos())); - r = r.intersected(rect); - if(!r.isValid()) + + //QRect rr = p.transform().mapRect(rect); // Gives inconsistent positions. Source shows wrong operation for our needs. + QRect rr = map(rect); // Use our own map instead. + QRect mer = map(r); + + ///r = r.intersected(rect); + //QRect rr = r & rect; + ///if(!r.isValid()) + //if(!rr.isValid()) + // return; + QRect mr = rr & mer; + //if(!mr.isValid()) + if(mr.isNull()) return; + + //p.save(); + p.setPen(Qt::black); struct Triple { int r, g, b; @@ -169,25 +184,25 @@ void PianoCanvas::drawItem(QPainter& p, const CItem* item, { 0xff, 0xbf, 0x7a } }; + QColor color; NEvent* nevent = (NEvent*) item; Event event = nevent->event(); if (nevent->part() != curPart){ if(item->isMoving()) - p.setBrush(Qt::gray); + color = Qt::gray; else if(item->isSelected()) - p.setBrush(Qt::black); + color = Qt::black; else - p.setBrush(Qt::lightGray); + color = Qt::lightGray; } else { if (item->isMoving()) { - p.setBrush(Qt::gray); + color = Qt::gray; } else if (item->isSelected()) { - p.setBrush(Qt::black); + color = Qt::black; } else { - QColor color; color.setRgb(0, 0, 255); switch(colorMode) { case 0: @@ -208,10 +223,50 @@ void PianoCanvas::drawItem(QPainter& p, const CItem* item, } break; } - p.setBrush(color); } } - p.drawRect(r); + + bool wmtxen = p.worldMatrixEnabled(); + p.setWorldMatrixEnabled(false); + int mx = mr.x(); + int my = mr.y(); + int mw = mr.width(); + int mh = mr.height(); + int mex = mer.x(); + int mey = mer.y(); + int mew = mer.width(); + int meh = mer.height(); + //int mfx = mx; + //if(mfx == mex) mfx += 1; + //int mfy = my; + //if(mfy == mey) mfy += 1; + //int mfw = mw; + //if(mfw == mew) mfw -= 1; + //if(mfx == mex) mfw -= 1; + //int mfh = mh; + //if(mfh == meh) mfh -= 1; + //if(mfy == mey) mfh -= 1; + color.setAlpha(config.globalAlphaBlend); + //QLinearGradient gradient(mex + 1, mey + 1, mex + 1, mey + meh - 2); // Inside the border + //gradient.setColorAt(0, color); + //gradient.setColorAt(1, color.darker()); + //QBrush brush(gradient); + QBrush brush(color); + p.fillRect(mr, brush); + //p.fillRect(mfx, mfy, mfw, mfh, brush); + + if(mex >= mx && mex <= mx + mw) + p.drawLine(mex, my, mex, my + mh - 1); // The left edge + if(mex + mew >= mx && mex + mew <= mx + mw) + p.drawLine(mex + mew, my, mex + mew, my + mh - 1); // The right edge + if(mey >= my && mey <= my + mh) + p.drawLine(mx, mey, mx + mw - 1, mey); // The top edge + if(mey + meh >= my && mey + meh <= my + mh) + p.drawLine(mx, mey + meh - 1, mx + mw - 1, mey + meh - 1); // The bottom edge + + //p.setWorldMatrixEnabled(true); + p.setWorldMatrixEnabled(wmtxen); + //p.restore(); } //--------------------------------------------------------- @@ -314,7 +369,7 @@ Undo PianoCanvas::moveCanvasItems(CItemList& items, int dp, int dx, DragType dty for(iPartToChange ip2c = parts2change.begin(); ip2c != parts2change.end(); ++ip2c) { Part* opart = ip2c->first; - int diff = ip2c->second.xdiff; + //int diff = ip2c->second.xdiff; if (opart->hasHiddenEvents()) { @@ -681,48 +736,6 @@ void PianoCanvas::pianoReleased(int pitch, bool) audio->msgPlayMidiEvent(&e); } -//--------------------------------------------------------- -// drawTickRaster -//--------------------------------------------------------- - -void drawTickRaster(QPainter& p, int x, int y, int w, int h, int raster) - { - int bar1, bar2, beat; - unsigned tick; - AL::sigmap.tickValues(x, &bar1, &beat, &tick); - AL::sigmap.tickValues(x+w, &bar2, &beat, &tick); - ++bar2; - int y2 = y + h; - for (int bar = bar1; bar < bar2; ++bar) { - unsigned x = AL::sigmap.bar2tick(bar, 0, 0); - p.setPen(Qt::black); - p.drawLine(x, y, x, y2); - int z, n; - AL::sigmap.timesig(x, z, n); - ///int q = p.xForm(QPoint(raster, 0)).x() - p.xForm(QPoint(0, 0)).x(); - int q = p.combinedTransform().map(QPoint(raster, 0)).x() - p.combinedTransform().map(QPoint(0, 0)).x(); - int qq = raster; - if (q < 8) // grid too dense - qq *= 2; - p.setPen(Qt::lightGray); - if (raster>=4) { - int xx = x + qq; - int xxx = AL::sigmap.bar2tick(bar, z, 0); - while (xx <= xxx) { - p.drawLine(xx, y, xx, y2); - xx += qq; - } - xx = xxx; - } - p.setPen(Qt::gray); - for (int beat = 1; beat < z; beat++) { - int xx = AL::sigmap.bar2tick(bar, beat, 0); - p.drawLine(xx, y, xx, y2); - } - - } - } - //--------------------------------------------------------- // draw //--------------------------------------------------------- @@ -734,31 +747,63 @@ void PianoCanvas::drawCanvas(QPainter& p, const QRect& rect) int w = rect.width(); int h = rect.height(); + // Changed to draw in device coordinate space instead of virtual, transformed space. Tim. p4.0.30 + + //int mx = mapx(x); + //int my = mapy(y); + //int mw = mapx(x + w) - mx; + //int mw = mapx(x + w) - mx - 1; + //int mh = mapy(y + h) - my; + //int mh = mapy(y + h) - my - 1; + + // p.save(); + // FIXME Can't get horizontal lines quite right yet. Draw in virtual space for now... + ///p.setWorldMatrixEnabled(false); + //--------------------------------------------------- // horizontal lines //--------------------------------------------------- int yy = ((y-1) / KH) * KH + KH; + //int yy = my + KH; + //int yy = ((my-1) / KH) * KH + KH; + //int yoff = -rmapy(yorg) - ypos; int key = 75 - (yy / KH); + + //printf("PianoCanvas::drawCanvas x:%d y:%d w:%d h:%d mx:%d my:%d mw:%d mh:%d yy:%d key:%d\n", x, y, w, h, mx, my, mw, mh, yy, key); + for (; yy < y + h; yy += KH) { + //for (; yy + yoff < my + mh; yy += KH) { + //for (; yy < my + mh; yy += KH) { switch (key % 7) { case 0: case 3: p.setPen(Qt::black); p.drawLine(x, yy, x + w, yy); + //p.drawLine(mx, yy + yoff, mx + mw, yy + yoff); + //p.drawLine(mx, yy, mx + mw, yy); break; default: p.fillRect(x, yy-3, w, 6, QBrush(QColor(230,230,230))); + //p.fillRect(mx, yy-3 + yoff, mw, 6, QBrush(QColor(230,230,230))); + //p.fillRect(mx, yy-3, mw, 6, QBrush(QColor(230,230,230))); break; } --key; } - + //p.restore(); + ///p.setWorldMatrixEnabled(true); + + //p.setWorldMatrixEnabled(false); + //--------------------------------------------------- // vertical lines //--------------------------------------------------- drawTickRaster(p, x, y, w, h, editor->raster()); + + //p.restore(); + //p.setWorldMatrixEnabled(true); } //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index b6b2c6d9..4b2db2fc 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -419,7 +419,7 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos) menu_mapper->setMapping(set_name_action, CMD_SET_NAME); - QMenu* functions_menu = menuBar()->addMenu(tr("&Functions")); + QMenu* functions_menu = menuBar()->addMenu(tr("Fu&nctions")); func_quantize_action = functions_menu->addAction(tr("&Quantize"), menu_mapper, SLOT(map())); func_notelen_action = functions_menu->addAction(tr("Change note &length"), menu_mapper, SLOT(map())); diff --git a/muse2/muse/widgets/canvas.cpp b/muse2/muse/widgets/canvas.cpp index c2c329a9..c7186a2d 100644 --- a/muse2/muse/widgets/canvas.cpp +++ b/muse2/muse/widgets/canvas.cpp @@ -380,13 +380,20 @@ void Canvas::draw(QPainter& p, const QRect& rect) // draw marker //--------------------------------------------------- - int y2 = y + h; + //p.save(); + bool wmtxen = p.worldMatrixEnabled(); + p.setWorldMatrixEnabled(false); + + int my = mapy(y); + //int y2 = y + h; + int my2 = mapy(y + h); MarkerList* marker = song->marker(); for (iMarker m = marker->begin(); m != marker->end(); ++m) { int xp = m->second.tick(); if (xp >= x && xp < x+w) { p.setPen(Qt::green); - p.drawLine(xp, y, xp, y2); + //p.drawLine(xp, y, xp, y2); + p.drawLine(mapx(xp), my, mapx(xp), my2); } } @@ -395,16 +402,28 @@ void Canvas::draw(QPainter& p, const QRect& rect) //--------------------------------------------------- p.setPen(Qt::blue); + int mx; if (pos[1] >= unsigned(x) && pos[1] < unsigned(x2)) { - p.drawLine(pos[1], y, pos[1], y2); + //p.drawLine(pos[1], y, pos[1], y2); + mx = mapx(pos[1]); + p.drawLine(mx, my, mx, my2); + } + if (pos[2] >= unsigned(x) && pos[2] < unsigned(x2)) { + //p.drawLine(pos[2], y, pos[2], y2); + mx = mapx(pos[2]); + p.drawLine(mx, my, mx, my2); } - if (pos[2] >= unsigned(x) && pos[2] < unsigned(x2)) - p.drawLine(pos[2], y, pos[2], y2); p.setPen(Qt::red); if (pos[0] >= unsigned(x) && pos[0] < unsigned(x2)) { - p.drawLine(pos[0], y, pos[0], y2); + //p.drawLine(pos[0], y, pos[0], y2); + mx = mapx(pos[0]); + p.drawLine(mx, my, mx, my2); } + //p.restore(); + //p.setWorldMatrixEnabled(true); + p.setWorldMatrixEnabled(wmtxen); + //--------------------------------------------------- // draw lasso //--------------------------------------------------- diff --git a/muse2/muse/widgets/view.cpp b/muse2/muse/widgets/view.cpp index 49f559c6..57955c19 100644 --- a/muse2/muse/widgets/view.cpp +++ b/muse2/muse/widgets/view.cpp @@ -19,6 +19,8 @@ #include "math.h" +#include "al/sig.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 @@ -494,26 +496,33 @@ void View::pdraw(QPainter& p, const QRect& r) int w = r.width(); int h = r.height(); if (xmag <= 0) { - x -= 1; + // TODO These adjustments are required, otherwise gaps. Tried, unable to remove them for now. p4.0.30 + x -= 1; w += 2; - x = (x + xpos + rmapx(xorg)) * (-xmag); + //x = (x + xpos + rmapx(xorg)) * (-xmag); + x = lrint((double(x + xpos) + rmapx_f(xorg)) * double(-xmag)); w = w * (-xmag); } else { - x = (x + xpos + rmapx(xorg)) / xmag; - w = (w + xmag - 1) / xmag; + //x = (x + xpos + rmapx(xorg)) / xmag; + x = lrint((double(x + xpos) + rmapx_f(xorg)) / double(xmag)); + //w = (w + xmag - 1) / xmag; + w = lrint(double(w) / double(xmag)); x -= 1; w += 2; } if (ymag <= 0) { y -= 1; h += 2; - y = (y + ypos + rmapy(yorg)) * (-ymag); + //y = (y + ypos + rmapy(yorg)) * (-ymag); + y = lrint((double(y + ypos) + rmapy_f(yorg)) * double(-ymag)); h = h * (-ymag); } else { - y = (y + ypos + rmapy(yorg)) / ymag; - h = (h + ymag - 1) / ymag; + //y = (y + ypos + rmapy(yorg)) / ymag; + y = lrint((double(y + ypos) + rmapy_f(yorg)) / double(ymag)); + //h = (h + ymag - 1) / ymag; + h = lrint(double(h) / double(ymag)); y -= 1; h += 2; } @@ -538,12 +547,92 @@ void View::setPainter(QPainter& p) p.resetMatrix(); // Q3 support says use resetMatrix instead, but resetMatrix advises resetTransform instead... //p.resetTransform(); - p.translate(double(-(xpos+rmapx(xorg))), double(-(ypos+rmapy(yorg)))); - double xMag = (xmag < 0) ? 1.0/(-xmag) : double(xmag); - double yMag = (ymag < 0) ? 1.0/(-ymag) : double(ymag); + //p.translate(double(-(xpos+rmapx(xorg))), double(-(ypos+rmapy(yorg)))); + p.translate( -(double(xpos) + rmapx_f(xorg)) , -(double(ypos) + rmapy(yorg))); + //double xMag = (xmag < 0) ? 1.0/(-xmag) : double(xmag); + //double yMag = (ymag < 0) ? 1.0/(-ymag) : double(ymag); + double xMag = (xmag < 0) ? 1.0/double(-xmag) : double(xmag); + double yMag = (ymag < 0) ? 1.0/double(-ymag) : double(ymag); p.scale(xMag, yMag); } +//--------------------------------------------------------- +// drawTickRaster +//--------------------------------------------------------- + +void View::drawTickRaster(QPainter& p, int x, int y, int w, int h, int raster) + { + // Changed to draw in device coordinate space instead of virtual, transformed space. Tim. p4.0.30 + + //int mx = mapx(x); + int my = mapy(y); + //int mw = mapx(x + w) - mx; + //int mw = mapx(x + w) - mx - 1; + //int mh = mapy(y + h) - my; + //int mh = mapy(y + h) - my - 1; + + //p.save(); + bool wmtxen = p.worldMatrixEnabled(); + p.setWorldMatrixEnabled(false); + + int xx,bar1, bar2, beat; + unsigned tick; + AL::sigmap.tickValues(x, &bar1, &beat, &tick); + AL::sigmap.tickValues(x+w, &bar2, &beat, &tick); + ++bar2; + ///int y2 = y + h; + //int y2 = my + mh; + int y2 = mapy(y + h) - 1; + //printf("View::drawTickRaster x:%d y:%d w:%d h:%d mx:%d my:%d mw:%d mh:%d y2:%d bar1:%d bar2:%d\n", x, y, w, h, mx, my, mw, mh, y2, bar1, bar2); + //printf("View::drawTickRaster x:%d y:%d w:%d h:%d my:%d mh:%d y2:%d bar1:%d bar2:%d\n", x, y, w, h, my, mh, y2, bar1, bar2); + for (int bar = bar1; bar < bar2; ++bar) { + ///unsigned x = AL::sigmap.bar2tick(bar, 0, 0); + unsigned xb = AL::sigmap.bar2tick(bar, 0, 0); + int xt = mapx(xb); + p.setPen(Qt::black); + ///p.drawLine(x, y, x, y2); + p.drawLine(xt, my, xt, y2); + int z, n; + ///AL::sigmap.timesig(x, z, n); + AL::sigmap.timesig(xb, z, n); + ///int q = p.xForm(QPoint(raster, 0)).x() - p.xForm(QPoint(0, 0)).x(); + ///int q = p.combinedTransform().map(QPoint(raster, 0)).x() - p.combinedTransform().map(QPoint(0, 0)).x(); + //int q = rmapx(raster); + int qq = raster; + //if (q < 8) // grid too dense + if (rmapx(raster) < 8) // grid too dense + qq *= 2; + p.setPen(Qt::lightGray); + if (raster>=4) { + ///int xx = x + qq; + //int xx = mapx(xb + qq); + xx = xb + qq; + int xxx = AL::sigmap.bar2tick(bar, z, 0); + //int xxx = mapx(AL::sigmap.bar2tick(bar, z, 0)); + while (xx <= xxx) { + ///p.drawLine(xx, y, xx, y2); + int x = mapx(xx); + p.drawLine(x, my, x, y2); + xx += qq; + //xx += rmapx(qq); + } + //xx = xxx; + } + p.setPen(Qt::gray); + for (int beat = 1; beat < z; beat++) { + ///int xx = AL::sigmap.bar2tick(bar, beat, 0); + xx = mapx(AL::sigmap.bar2tick(bar, beat, 0)); + //printf(" bar:%d z:%d beat:%d xx:%d\n", bar, z, beat, xx); + ///p.drawLine(xx, y, xx, y2); + p.drawLine(xx, my, xx, y2); + } + + } + //p.setWorldMatrixEnabled(true); + p.setWorldMatrixEnabled(wmtxen); + //p.restore(); + } + //--------------------------------------------------------- // map //--------------------------------------------------------- @@ -681,29 +770,40 @@ int View::rmapyDev(int y) const QRect View::map(const QRect& r) const { - int x, y, w, h; + //int x, y, w, h; + double x, y, w, h; + int xx, yy, ww, hh; //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)); + //x = lrint(double(r.x())/double(-xmag) - rmapx_f(xorg)) - xpos; + x = double(r.x())/double(-xmag) - rmapx_f(xorg) - xpos; + //w = lrint(double(r.width()) / double(-xmag)); + w = double(r.width()) / double(-xmag); + xx = lrint(x); + ww = lrint(x + w) - xx; } else { - x = r.x()*xmag - xpos - lrint(rmapx_f(xorg)); - w = r.width() * xmag; + xx = r.x()*xmag - xpos - lrint(rmapx_f(xorg)); + ww = r.width() * xmag; } if (ymag < 0) { - y = lrint(double(r.y())/double(-ymag) - rmapy_f(yorg)) - ypos; - h = lrint(double(r.height()) / double(-ymag)); + //y = lrint(double(r.y())/double(-ymag) - rmapy_f(yorg)) - ypos; + y = double(r.y())/double(-ymag) - rmapy_f(yorg) - ypos; + //h = lrint(double(r.height()) / double(-ymag)); + h = double(r.height()) / double(-ymag); + yy = lrint(y); + hh = lrint(y + h) - yy; } else { - y = r.y()*ymag - ypos - lrint(rmapy_f(yorg)); - h = r.height() * ymag; + yy = r.y()*ymag - ypos - lrint(rmapy_f(yorg)); + hh = r.height() * ymag; } - return QRect(x, y, w, h); + return QRect(xx, yy, ww, hh); } QPoint View::map(const QPoint& p) const { + /* int x, y; if (xmag < 0) { x = lrint(double(p.x())/double(-xmag) - rmapx_f(xorg)) - xpos; @@ -718,6 +818,8 @@ QPoint View::map(const QPoint& p) const y = p.y()*ymag - ypos - lrint(rmapy_f(yorg)); } return QPoint(x, y); + */ + return QPoint(mapx(p.x()), mapy(p.y())); } int View::mapx(int x) const diff --git a/muse2/muse/widgets/view.h b/muse2/muse/widgets/view.h index ad0a6cf9..a932f173 100644 --- a/muse2/muse/widgets/view.h +++ b/muse2/muse/widgets/view.h @@ -50,6 +50,7 @@ class View : public QWidget { virtual void draw(QPainter&, const QRect&) {} virtual void drawOverlay(QPainter&) {} virtual QRect overlayRect() const { return QRect(0, 0, 0, 0); } + virtual void drawTickRaster(QPainter& p, int x, int y, int w, int h, int raster); virtual void pdraw(QPainter&, const QRect&); -- cgit v1.2.3 From 516a5fafd56fa9d70d6aba20978d6e177cdf5502 Mon Sep 17 00:00:00 2001 From: "Tim E. Real" Date: Wed, 17 Aug 2011 01:17:50 +0000 Subject: Fixed unreadable Master Edit tempo scale (on left side), and added toolbar saving and restoring. --- muse2/ChangeLog | 1 + muse2/muse/master/masteredit.cpp | 12 ++++++++++++ muse2/muse/master/tscale.cpp | 12 +++++++----- 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'muse2') diff --git a/muse2/ChangeLog b/muse2/ChangeLog index 562361c7..32d65061 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -2,6 +2,7 @@ - More drawing fixes, improved accuracy (grids, timescales, edges, markers guaranteed to align now). (Tim p4.0.30) Much drawing changed to device (pixel) space instead of virtual space, for accuracy. - Fixed display of audio automation graphs. (But not editing). (Tim) + - Fixed unreadable Master Edit tempo scale (on left side), and added toolbar saving and restoring. (Tim p4.0.31) 15.08.2011: - Remodel the Meter and the VerticalMeter (Orcan) 13.08.2011: diff --git a/muse2/muse/master/masteredit.cpp b/muse2/muse/master/masteredit.cpp index 9053f3a8..fafa3b4f 100644 --- a/muse2/muse/master/masteredit.cpp +++ b/muse2/muse/master/masteredit.cpp @@ -31,6 +31,7 @@ #include #include #include +#include int MasterEdit::_rasterInit = 0; int MasterEdit::_widthInit = 600; @@ -43,6 +44,10 @@ QByteArray MasterEdit::_toolbarInit; void MasterEdit::closeEvent(QCloseEvent* e) { + QSettings settings("MusE", "MusE-qt"); + //settings.setValue("MasterEdit/geometry", saveGeometry()); + settings.setValue("MasterEdit/windowState", saveState()); + emit deleted((unsigned long)this); e->accept(); } @@ -94,12 +99,14 @@ MasterEdit::MasterEdit() //---------ToolBar---------------------------------- tools = addToolBar(tr("Master tools")); + tools->setObjectName("Master tools"); tools->addActions(undoRedo->actions()); EditToolBar* tools2 = new EditToolBar(this, PointerTool | PencilTool | RubberTool); addToolBar(tools2); QToolBar* enableMaster = addToolBar(tr("Enable master")); + enableMaster->setObjectName("Enable master"); enableButton = new QToolButton(); enableButton->setCheckable(true); enableButton->setText(tr("Enable")); @@ -109,6 +116,7 @@ MasterEdit::MasterEdit() connect(enableButton, SIGNAL(toggled(bool)), song, SLOT(setMasterFlag(bool))); QToolBar* info = addToolBar(tr("Info")); + info->setObjectName("Info"); QLabel* label = new QLabel(tr("Cursor")); label->setAlignment(Qt::AlignRight|Qt::AlignVCenter); label->setIndent(3); @@ -235,6 +243,10 @@ MasterEdit::MasterEdit() if (!_toolbarInit.isEmpty()) restoreState(_toolbarInit); + + QSettings settings("MusE", "MusE-qt"); + //restoreGeometry(settings.value("MasterEdit/geometry").toByteArray()); + restoreState(settings.value("MasterEdit/windowState").toByteArray()); } //--------------------------------------------------------- diff --git a/muse2/muse/master/tscale.cpp b/muse2/muse/master/tscale.cpp index d37d5924..9ea34fba 100644 --- a/muse2/muse/master/tscale.cpp +++ b/muse2/muse/master/tscale.cpp @@ -20,8 +20,9 @@ TScale::TScale(QWidget* parent, int ymag) : View(parent, 1, ymag) { - setFont(config.fonts[3]); - int w = 4 * QFontMetrics(config.fonts[4]).width('0'); + setFont(config.fonts[4]); + //int w = 4 * QFontMetrics(config.fonts[4]).width('0'); + int w = 4 * fontMetrics().width('0'); setFixedWidth(w); setMouseTracking(true); } @@ -34,7 +35,7 @@ void TScale::pdraw(QPainter& p, const QRect& r) { int y = r.y(); int h = r.height(); - p.setFont(config.fonts[4]); + //p.setFont(config.fonts[4]); QString s; for (int i = 30000; i <= 250000; i += 10000) { int yy = mapy(280000 - i); @@ -44,8 +45,9 @@ void TScale::pdraw(QPainter& p, const QRect& r) continue; p.drawLine(0, yy, width(), yy); s.setNum(i/1000); - QFontMetrics fm(config.fonts[4]); - p.drawText(width() - fm.width(s) - 1, yy-2, s); + //QFontMetrics fm(config.fonts[4]); + //p.drawText(width() - fm.width(s) - 1, yy-2, s); + p.drawText(width() - fontMetrics().width(s) - 1, yy-2, s); // Use the window font. Tim p4.0.31 } } -- cgit v1.2.3 From 35c95c10cca9938210818c0b809b1ff4f9c4ad3d Mon Sep 17 00:00:00 2001 From: Orcan Ogetbil Date: Wed, 17 Aug 2011 05:09:27 +0000 Subject: Finished some remaining work on the port of ComboBox --- muse2/ChangeLog | 4 +++ muse2/muse/mixer/astrip.cpp | 40 +++++++++----------------- muse2/muse/mixer/mstrip.cpp | 23 ++++++--------- muse2/muse/mixer/strip.cpp | 2 +- muse2/muse/mixer/strip.h | 2 +- muse2/muse/widgets/combobox.cpp | 64 ++++++++++++++++++++++++----------------- muse2/muse/widgets/combobox.h | 24 +++++++++------- 7 files changed, 78 insertions(+), 81 deletions(-) (limited to 'muse2') diff --git a/muse2/ChangeLog b/muse2/ChangeLog index 32d65061..d5dd93ce 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,7 @@ +17.08.2011: + - Convert some Qt3 style coding in ComboBox to Qt4 in terms of menu entry handling. (Orcan) + - Add mouse wheel support to ComboBox. (Orcan) + - Fix AutoType indicator coloring. (Orcan) 16.08.2011: - More drawing fixes, improved accuracy (grids, timescales, edges, markers guaranteed to align now). (Tim p4.0.30) Much drawing changed to device (pixel) space instead of virtual space, for accuracy. diff --git a/muse2/muse/mixer/astrip.cpp b/muse2/muse/mixer/astrip.cpp index 5644e6eb..658a4970 100644 --- a/muse2/muse/mixer/astrip.cpp +++ b/muse2/muse/mixer/astrip.cpp @@ -211,16 +211,14 @@ void AudioStrip::songChanged(int val) autoType->setCurrentItem(track->automationType()); if(track->automationType() == AUTO_TOUCH || track->automationType() == AUTO_WRITE) { - //autoType->setPaletteBackgroundColor(Qt::red); QPalette palette; - palette.setColor(autoType->backgroundRole(), QColor(Qt::red)); + palette.setColor(QPalette::Button, QColor(Qt::red)); autoType->setPalette(palette); } else { - //autoType->setPaletteBackgroundColor(qApp->palette().active().background()); QPalette palette; - palette.setColor(autoType->backgroundRole(), qApp->palette().color(QPalette::Active, QPalette::Background)); + palette.setColor(QPalette::Button, qApp->palette().color(QPalette::Active, QPalette::Background)); autoType->setPalette(palette); } @@ -927,41 +925,31 @@ AudioStrip::AudioStrip(QWidget* parent, AudioTrack* at) // automation type //--------------------------------------------------- - autoType = new ComboBox(this); + autoType = new ComboBox(); autoType->setFont(config.fonts[1]); autoType->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); - autoType->setAlignment(Qt::AlignCenter); - autoType->insertItem(tr("Off"), AUTO_OFF); - autoType->insertItem(tr("Read"), AUTO_READ); - autoType->insertItem(tr("Touch"), AUTO_TOUCH); - autoType->insertItem(tr("Write"), AUTO_WRITE); + autoType->addAction(tr("Off"), AUTO_OFF); + autoType->addAction(tr("Read"), AUTO_READ); + autoType->addAction(tr("Touch"), AUTO_TOUCH); + autoType->addAction(tr("Write"), AUTO_WRITE); autoType->setCurrentItem(t->automationType()); - // FIXME: TODO: Convert ComboBox to QT4 - //autoType->insertItem(AUTO_OFF, tr("Off")); - //autoType->insertItem(AUTO_READ, tr("Read")); - //autoType->insertItem(AUTO_TOUCH, tr("Touch")); - //autoType->insertItem(AUTO_WRITE, tr("Write")); - //autoType->setCurrentIndex(t->automationType()); - + if(t->automationType() == AUTO_TOUCH || t->automationType() == AUTO_WRITE) { - // FIXME: - //autoType->setPaletteBackgroundColor(Qt::red); - QPalette palette; - palette.setColor(autoType->backgroundRole(), QColor(Qt::red)); - autoType->setPalette(palette); + QPalette palette; + palette.setColor(QPalette::Button, QColor(Qt::red)); + autoType->setPalette(palette); } else { - // FIXME: - //autoType->setPaletteBackgroundColor(qApp->palette().active().background()); QPalette palette; - palette.setColor(autoType->backgroundRole(), qApp->palette().color(QPalette::Active, QPalette::Background)); + palette.setColor(QPalette::Button, qApp->palette().color(QPalette::Active, QPalette::Background)); autoType->setPalette(palette); } + autoType->setToolTip(tr("automation type")); - connect(autoType, SIGNAL(activated(int,int)), SLOT(setAutomationType(int,int))); + connect(autoType, SIGNAL(activated(int)), SLOT(setAutomationType(int))); grid->addWidget(autoType, _curGridRow++, 0, 1, 2); if (off) { diff --git a/muse2/muse/mixer/mstrip.cpp b/muse2/muse/mixer/mstrip.cpp index d773708a..ad21916d 100644 --- a/muse2/muse/mixer/mstrip.cpp +++ b/muse2/muse/mixer/mstrip.cpp @@ -405,28 +405,21 @@ MidiStrip::MidiStrip(QWidget* parent, MidiTrack* t) // automation mode //--------------------------------------------------- - autoType = new ComboBox(this); + autoType = new ComboBox(); autoType->setFont(config.fonts[1]); autoType->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum)); - autoType->setAlignment(Qt::AlignCenter); autoType->setEnabled(false); // Removed by T356. // Disabled for now. There is no midi automation mechanism yet... - //autoType->insertItem(tr("Off"), AUTO_OFF); - //autoType->insertItem(tr("Read"), AUTO_READ); - //autoType->insertItem(tr("Touch"), AUTO_TOUCH); - //autoType->insertItem(tr("Write"), AUTO_WRITE); + //autoType->addAction(tr("Off"), AUTO_OFF); + //autoType->addAction(tr("Read"), AUTO_READ); + //autoType->addAction(tr("Touch"), AUTO_TOUCH); + //autoType->addAction(tr("Write"), AUTO_WRITE); //autoType->setCurrentItem(t->automationType()); - // TODO: Convert ComboBox to QT4 - //autoType->insertItem(AUTO_OFF, tr("Off")); - //autoType->insertItem(AUTO_READ, tr("Read")); - //autoType->insertItem(AUTO_TOUCH, tr("Touch")); - //autoType->insertItem(AUTO_WRITE, tr("Write")); - //autoType->setCurrentIndex(t->automationType()); - //autoType->setToolTip(tr("automation type")); - - //connect(autoType, SIGNAL(activated(int,int)), SLOT(setAutomationType(int,int))); + //autoType->setToolTip(tr("automation type")); + //connect(autoType, SIGNAL(activated(int)), SLOT(setAutomationType(int))); + grid->addWidget(autoType, _curGridRow++, 0, 1, 2); connect(heartBeatTimer, SIGNAL(timeout()), SLOT(heartBeat())); inHeartBeat = false; diff --git a/muse2/muse/mixer/strip.cpp b/muse2/muse/mixer/strip.cpp index 0c4059d8..3cf9765d 100644 --- a/muse2/muse/mixer/strip.cpp +++ b/muse2/muse/mixer/strip.cpp @@ -257,7 +257,7 @@ Strip::~Strip() // setAutomationType //--------------------------------------------------------- -void Strip::setAutomationType(int t,int) +void Strip::setAutomationType(int t) { track->setAutomationType(AutomationType(t)); song->update(SC_AUTOMATION); diff --git a/muse2/muse/mixer/strip.h b/muse2/muse/mixer/strip.h index b138992e..cf3babe8 100644 --- a/muse2/muse/mixer/strip.h +++ b/muse2/muse/mixer/strip.h @@ -60,7 +60,7 @@ class Strip : public QFrame { protected slots: virtual void heartBeat(); - void setAutomationType(int t,int); + void setAutomationType(int t); public slots: void resetPeaks(); diff --git a/muse2/muse/widgets/combobox.cpp b/muse2/muse/widgets/combobox.cpp index 9e278376..bd78d6f2 100644 --- a/muse2/muse/widgets/combobox.cpp +++ b/muse2/muse/widgets/combobox.cpp @@ -6,6 +6,8 @@ //========================================================= #include +#include +#include #include "combobox.h" @@ -14,67 +16,75 @@ //--------------------------------------------------------- ComboBox::ComboBox(QWidget* parent, const char* name) - : QLabel(parent) + : QToolButton(parent) { setObjectName(name); _currentItem = 0; - _id = -1; - list = new QMenu(0); - connect(list, SIGNAL(triggered(QAction*)), SLOT(activatedIntern(QAction*))); - setFrameStyle(QFrame::Panel | QFrame::Raised); - setLineWidth(2); + + menu = new QMenu(this); + + autoTypeSignalMapper = new QSignalMapper(this); + connect(autoTypeSignalMapper, SIGNAL(mapped(int)), this, SLOT(activatedIntern(int))); } ComboBox::~ComboBox() { - delete list; + delete menu; } //--------------------------------------------------------- // mousePressEvent //--------------------------------------------------------- -void ComboBox::mousePressEvent(QMouseEvent*) +void ComboBox::mousePressEvent(QMouseEvent* /*ev*/) + { + menu->exec(QCursor::pos()); + } + +//--------------------------------------------------------- +// wheelEvent +//--------------------------------------------------------- + +void ComboBox::wheelEvent(QWheelEvent* ev) { - list->exec(QCursor::pos()); + int i = itemlist.indexOf(_currentItem); + int len = itemlist.count(); + if (ev->delta() > 0 && i > 0) + activatedIntern(_currentItem-1); + else if (ev->delta() < 0 && -1 < i && i < len - 1) + activatedIntern(_currentItem+1); } //--------------------------------------------------------- // activated //--------------------------------------------------------- -void ComboBox::activatedIntern(QAction* act) +void ComboBox::activatedIntern(int id) { - _currentItem = act->data().toInt(); - emit activated(_currentItem, _id); - setText(act->text()); + setCurrentItem(id); + emit activated(id); } //--------------------------------------------------------- // setCurrentItem //--------------------------------------------------------- -void ComboBox::setCurrentItem(int i) +void ComboBox::setCurrentItem(int id) { - _currentItem = i; - // ORCAN - CHECK - QList actions = list->actions(); - for (QList::iterator it = actions.begin(); it != actions.end(); ++it) { - QAction* act = *it; - if (act->data().toInt() == i) { - setText(act->text()); - break; - } - } + QAction* act = (QAction*) autoTypeSignalMapper->mapping(id); + _currentItem = id; + setText(act->text()); } //--------------------------------------------------------- // insertItem //--------------------------------------------------------- -void ComboBox::insertItem(const QString& s, int id) +void ComboBox::addAction(const QString& s, int id) { - QAction *act = list->addAction(s); - act->setData(id); + QAction *act = menu->addAction(s); + connect(act, SIGNAL(triggered()), autoTypeSignalMapper, SLOT(map())); + autoTypeSignalMapper->setMapping(act, id); + itemlist << id; } diff --git a/muse2/muse/widgets/combobox.h b/muse2/muse/widgets/combobox.h index 305ad0b3..c099b3ce 100644 --- a/muse2/muse/widgets/combobox.h +++ b/muse2/muse/widgets/combobox.h @@ -8,36 +8,38 @@ #ifndef __COMBOBOX_H__ #define __COMBOBOX_H__ -#include +#include class QMenu; +class QSignalMapper; //--------------------------------------------------------- // ComboBox //--------------------------------------------------------- -class ComboBox : public QLabel { +class ComboBox : public QToolButton { Q_OBJECT - Q_PROPERTY( int id READ id WRITE setId ) - int _id; int _currentItem; - QMenu* list; + QList itemlist; + + QMenu* menu; virtual void mousePressEvent(QMouseEvent*); + virtual void wheelEvent(QWheelEvent*); + + QSignalMapper* autoTypeSignalMapper; private slots: - void activatedIntern(QAction*); + void activatedIntern(int id); signals: - void activated(int val, int id); + void activated(int id); public: - ComboBox(QWidget* parent, const char* name = 0); + ComboBox(QWidget* parent = 0, const char* name = 0); ~ComboBox(); void setCurrentItem(int); - void insertItem(const QString& s, int id = -1); - int id() const { return _id; } - void setId(int i) { _id = i; } + void addAction(const QString& s, int id = -1); }; #endif -- cgit v1.2.3