diff options
| author | Florian Jung <flo@windfisch.org> | 2011-08-18 16:45:06 +0000 | 
|---|---|---|
| committer | Florian Jung <flo@windfisch.org> | 2011-08-18 16:45:06 +0000 | 
| commit | 0002e57359fb002a70cc9559308619ff611718c9 (patch) | |
| tree | 4d430468df5c1a38895ae9f56a61127240e5ea2b /muse2/muse | |
| parent | 3513555193d44fe99bc30dd3bf04701278a797a1 (diff) | |
| parent | 35c95c10cca9938210818c0b809b1ff4f9c4ad3d (diff) | |
merged with trunk, except:
 - not applied the "masteredit saves toolbar state" change, as this
   is done by TopWin here in experimental
 - fixed some indentation error in scoreedit.cpp
Diffstat (limited to 'muse2/muse')
35 files changed, 2008 insertions, 459 deletions
| diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index e48425d7..8f059c73 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -1422,7 +1422,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                    { @@ -2601,7 +2601,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 d223321b..cf376042 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -3,6 +3,7 @@  //  Linux Music Editor  //    $Id: pcanvas.cpp,v 1.48.2.26 2009/11/22 11:08:33 spamatica Exp $  //  (C) Copyright 1999 Werner Schweer (ws@seh.de) +//  Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)  //=========================================================  #include <stdio.h> @@ -45,7 +46,6 @@  #include "midictrl.h"  #include "utils.h" -  //---------------------------------------------------------  //   colorRect  //   paints a rectangular icon with a given color @@ -69,17 +69,12 @@ QIcon colorRect(const QColor& color, int width, int height) {  NPart::NPart(Part* e) : CItem(Event(), e)        { -      int th = track()->height(); -      int y  = track()->y(); +      leftBorderTouches = false; +      rightBorderTouches = false; -      ///setPos(QPoint(e->tick(), y + 1)); +      int y  = track()->y();        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()));        }  //--------------------------------------------------------- @@ -418,17 +413,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();        } @@ -1275,6 +1284,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(); @@ -1298,84 +1308,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); +            brush = QBrush(gradient); -            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())); -             -            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(); @@ -1393,40 +1534,640 @@ void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect)            drawMidiPart(p, rect, mp->events(), (MidiTrack*)part->track(), mp, r, mp->tick(), from, to);          } +  #if 0 +        // +        // Now draw the borders... +        // Works great but requires clones be drawn with the highest priority on top of all other parts, in Canvas::draw. +        // +         +        QPen pen(part->selected() ? config.partColors[i] : Qt::black, 2.0, clone ? Qt::DotLine : Qt::SolidLine); +        pen.setCosmetic(true); +        p.setPen(pen);  +        p.setBrush(Qt::NoBrush); +        p.drawRect(r); +         +  #else  +        // +        // Now draw the borders, using custom segments... +        // +         +        // FIXME NOTE: For 1-pixel wide lines, setting pen style to anything other than solid didn't work out well.  +        // Much too screwy - the single-width lines kept getting shifted one pixel over intermittently.  +        // I tried EVERYTHING to make sure x is proper but the painter keeps shifting them over. +        // Meanwhile the fills are correct. Seems painter doesn't like line patterns, whether stock or custom. +        // Therefore I was forced to manually draw the left and right segments.  +        // It works. Which seems to be more proof that painter is handling line patterns and pen widths badly...  +        // DO NOT ERASE COMMENTED CODE BELOW for now, in case it can be fixed. Tim. p4.0.29 +         +        p.setBrush(Qt::NoBrush); +         +        QColor pc((part->mute() || item->isMoving())? Qt::white : config.partColors[cidx]); +        QPen penSelect1H(pc); +        QPen penSelect2H(pc, 2.0); +        QPen penSelect1V(pc); +        QPen penSelect2V(pc, 2.0); +        penSelect1H.setCosmetic(true); +        penSelect2H.setCosmetic(true); +        penSelect1V.setCosmetic(true); +        penSelect2V.setCosmetic(true); +         +        pc = Qt::black; +        QPen penNormal1H(pc); +        QPen penNormal2H(pc, 2.0); +        QPen penNormal1V(pc); +        QPen penNormal2V(pc, 2.0); +        penNormal1H.setCosmetic(true); +        penNormal2H.setCosmetic(true); +        penNormal1V.setCosmetic(true); +        penNormal2V.setCosmetic(true); +         +        QVector<qreal> customDashPattern; +        if(clone) +        { +          customDashPattern << 4.0 << 8.0; +          penSelect1H.setDashPattern(customDashPattern); +          penNormal1H.setDashPattern(customDashPattern); +          //penSelect1V.setDashPattern(customDashPattern); +          //penNormal1V.setDashPattern(customDashPattern); +          customDashPattern.clear(); +          customDashPattern << 2.0 << 4.0; +          penSelect2H.setDashPattern(customDashPattern); +          penNormal2H.setDashPattern(customDashPattern); +          //penSelect2V.setDashPattern(customDashPattern); +          //penNormal2V.setDashPattern(customDashPattern); +        }   +         +        pc = Qt::white; +        QPen penHidden1(pc); +        QPen penHidden2(pc, 2.0); +        penHidden2.setCosmetic(true); +        //customDashPattern.clear(); +        //customDashPattern << 2.0 << 10.0; +        //penHidden1.setDashPattern(customDashPattern); +        //customDashPattern.clear(); +        //customDashPattern << 1.0 << 5.0; +        //penHidden2.setDashPattern(customDashPattern); +         +        bool lbt = ((NPart*)item)->leftBorderTouches; +        bool rbt = ((NPart*)item)->rightBorderTouches; +         +        QLineF l1( lbt?xs_1:xs_0, ys_0,   rbt?xe_1:xe_0, ys_0);                     // Top  +        //QLineF l2(rbt?xe_1:xe_0,  r.y() + (rbt?y_1:y_2) - 1,       rbt?xe_1:xe_0, r.y() + r.height() - 1);        // Right  +        QLineF l3( lbt?xs_1:xs_0, ye_0,   rbt?xe_1:xe_0, ye_0);  // Bottom +        //QLineF l4(r.x(), r.y() + (lbt?y_1:y_2),            r.x(), r.y() + r.height() - (lbt?y_1:y_2));       // Left +         +        if(het & Part::RightEventsHidden) +          p.setPen(((NPart*)item)->rightBorderTouches ? penHidden1 : penHidden2);  +        else   +        { +          if(((NPart*)item)->rightBorderTouches)               +            p.setPen(part->selected() ? penSelect1V : penNormal1V);  +          else   +            p.setPen(part->selected() ? penSelect2V : penNormal2V);  +        }   +        //p.drawLine(l2);        // Right line +         +        double xx = rbt?xe_1:xe_0;  +        if(clone) +        { +          double yinc = 7.0 * y_1; +          for(double yy = (rbt?ys_1:ys_2); yy < ye_2; yy += yinc) +          { +            double yi = (rbt?3.0:2.0) * y_1; +            if(yy + yi > ye_2) +              yi = ye_2 - yy; +            p.drawLine(QPointF(xx, yy), QPointF(xx, yy + yi));      // Right dashed line +          }    +        } +        else   +          p.drawLine(QPointF(xx, rbt?ys_1:ys_2), QPointF(xx, rbt?ye_1:ye_2));      // Right line +         +        if(het & Part::LeftEventsHidden) +          p.setPen(((NPart*)item)->leftBorderTouches ? penHidden1 : penHidden2);  +        else   +        { +          if(((NPart*)item)->leftBorderTouches)               +            p.setPen(part->selected() ? penSelect1V : penNormal1V);  +          else   +            p.setPen(part->selected() ? penSelect2V : penNormal2V);  +        }   +        //p.drawLine(l4);        //  Left line +         +        xx = xs_0; +        if(clone) +        { +          double yinc = 7.0 * y_1; +          for(double yy = (lbt?ys_1:ys_2); yy < ye_2; yy += yinc) +          { +            double yi = (lbt?3.0:2.0) * y_1; +            if(yy + yi > ye_2) +              yi = ye_2 - yy; +            p.drawLine(QPointF(xx, yy), QPointF(xx, yy + yi));      // Left dashed line +          }    +        } +        else   +          p.drawLine(QPointF(xx, lbt?ys_1:ys_2), QPointF(xx, lbt?ye_1:ye_2));      // Left line +         +        p.setPen(part->selected() ? penSelect2H : penNormal2H);  +        p.drawLine(l1);  // Top line +        p.drawLine(l3);  // Bottom line +         +  #endif +  +      //p.restore(); +              if (config.canvasShowPartType & 1) {     // show names              // draw name              // FN: Set text color depending on part color (black / white)              int part_r, part_g, part_b, brightness; -            //config.partColors[i].getRgb(&part_r, &part_g, &part_b);              // Since we'll draw the text on the bottom (to accommodate drum 'slivers'),              //  get the lowest colour in the gradient used to draw the part.              QRect rr = map(r);              rr.setX(rr.x() + 3); -            gGradientFromQColor(config.partColors[i], rr.topLeft(), rr.bottomLeft()).stops().last().second.getRgb(&part_r, &part_g, &part_b); +            gGradientFromQColor(config.partColors[cidx], rr.topLeft(), rr.bottomLeft()).stops().last().second.getRgb(&part_r, &part_g, &part_b);              brightness =  part_r*29 + part_g*59 + part_b*12; -            //if (brightness < 12000 || part->selected()) -            //  p.setPen(Qt::white);   /* too dark: use white for text color */ -            //else -            //  p.setPen(Qt::black);  /* otherwise use black */ -            bool rev = brightness < 12000 || part->selected(); -            //QRect rr = map(r); -            //rr.setX(rr.x() + 3); +            //bool rev = (brightness < 12000 || part->selected()) && !part->mute() && !item->isMoving(); +            bool rev = brightness >= 12000 && !part->selected();              p.save();              p.setFont(config.fonts[1]);              p.setWorldMatrixEnabled(false);              if (rev) -              p.setPen(Qt::black);    -            else                p.setPen(Qt::white);  +            else +              p.setPen(Qt::black);                 p.drawText(rr.translated(1, 1), Qt::AlignBottom|Qt::AlignLeft, part->name());              if (rev) -              p.setPen(Qt::white);    -            else                p.setPen(Qt::black);   +            else +              p.setPen(Qt::white);                 p.drawText(rr, Qt::AlignBottom|Qt::AlignLeft, part->name());              p.restore();              }        } +#endif + +void PartCanvas::drawItem(QPainter& p, const CItem* item, const QRect& rect) +      { +      int from   = rect.x(); +      int to     = from + rect.width(); + +      //printf("from %d to %d\n", from,to); +      Part* part = ((NPart*)item)->part(); +      int pTick  = part->tick(); +      from      -= pTick; +      to        -= pTick; +      if(from < 0) +        from = 0; +      if((unsigned int)to > part->lenTick()) +        to = part->lenTick();   + +      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() & rect).isNull()) +      if((rr & map(rect)).isNull()) +      { +        //printf("PartCanvas::drawItem rectangle is null\n"); +        return; +      } +       +      //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_j = xs_0 + 8; +      if(xs_j > xe_0) +        xs_j = 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_j = xe_0 - 8; +      if(xe_j < xs_0) +        xe_j = 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 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) +        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 = ys_0; +      //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[12];    +      QPoint points[8];    +      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_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_j, y2); +          points[pts++] = QPoint(xe_0, y4); +          points[pts++] = QPoint(xs_0, y4); +          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_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_j, y2); +          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=96; //0;    // too light: use dark color  +        else +          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_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_j, y2); +          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... +        // +         +        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); +         +        //pc = Qt::white; +        //pc = Qt::darkGray; +        //QPen penHidden1(pc); +        //QPen penHidden2(pc, 2.0); +        //penHidden2.setCosmetic(true); +         +        QVector<qreal> customDashPattern; +         +        if(clone) +        { +          customDashPattern << 4.0 << 6.0; +          penSelect1H.setDashPattern(customDashPattern); +          penNormal1H.setDashPattern(customDashPattern); +          penSelect1V.setDashPattern(customDashPattern);   +          penNormal1V.setDashPattern(customDashPattern);   +          penSelect1V.setDashOffset(2.0);   +          penNormal1V.setDashOffset(2.0); +          //penHidden1.setDashPattern(customDashPattern);   +          customDashPattern.clear(); +          customDashPattern << 2.0 << 3.0; +          penSelect2H.setDashPattern(customDashPattern); +          penNormal2H.setDashPattern(customDashPattern); +          penSelect2V.setDashPattern(customDashPattern);   +          penNormal2V.setDashPattern(customDashPattern);   +          penSelect2V.setDashOffset(1.0);   +          penNormal2V.setDashOffset(1.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, 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(((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 @@ -1436,19 +2177,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());        } @@ -1468,10 +2201,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; // 96;    // too bright: use dark color       else -      color_brightness=64;  // otherwise use dark color  +      color_brightness=190; //160;   // too dark: use lighter color     }    else      color_brightness=80; @@ -1656,9 +2393,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(); @@ -1685,8 +2424,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(); @@ -2359,9 +3100,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 // @@ -2379,13 +3133,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; @@ -2411,20 +3169,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(); @@ -2433,22 +3199,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);  }  //--------------------------------------------------------- @@ -2456,36 +3246,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(); @@ -2493,38 +3302,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; @@ -2568,53 +3386,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  ... +       +      //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 -//      p.fillRect(r, cc); +      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; @@ -2625,7 +3461,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()) { @@ -2651,6 +3488,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; @@ -2671,6 +3509,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, @@ -2683,20 +3522,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 a0c25f6e..71a0129c 100644 --- a/muse2/muse/arranger/pcanvas.h +++ b/muse2/muse/arranger/pcanvas.h @@ -3,11 +3,14 @@  //  Linux Music Editor  //    $Id: pcanvas.h,v 1.11.2.4 2009/05/24 21:43:44 terminator356 Exp $  //  (C) Copyright 1999 Werner Schweer (ws@seh.de) +//  Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)  //=========================================================  #ifndef __PCANVAS_H__  #define __PCANVAS_H__ +#include <QVector> +  #include "song.h"  #include "canvas.h"  #include "trackautomationview.h" @@ -33,6 +36,9 @@ class NPart : public CItem {        const QString name() const     { return part()->name(); }        void setName(const QString& s) { part()->setName(s); }        Track* track() const           { return part()->track(); } +       +      bool leftBorderTouches;  // Whether the borders touch other part borders.  +      bool rightBorderTouches;        };  enum ControllerVals { doNothing, movingController, addNewController }; @@ -109,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/driver/jack.cpp b/muse2/muse/driver/jack.cpp index 4857ede5..529e8a60 100644 --- a/muse2/muse/driver/jack.cpp +++ b/muse2/muse/driver/jack.cpp @@ -977,7 +977,8 @@ void JackAudioDevice::graphChanged()                          // p3.3.37                          //delete ports; -                        free(ports); +                        //free(ports); +                        jack_free(ports);  // p4.0.29                          ports = NULL;                          } @@ -1063,7 +1064,8 @@ void JackAudioDevice::graphChanged()                          // p3.3.37                          //delete ports; -                        free(ports); +                        //free(ports); +                        jack_free(ports);  // p4.0.29                          ports = NULL;                          } @@ -1182,7 +1184,8 @@ void JackAudioDevice::graphChanged()                              // p3.3.55                              // Done with ports. Free them. -                            free(ports); +                            //free(ports); +                            jack_free(ports);  // p4.0.29                        }                      }                      }   @@ -1279,7 +1282,8 @@ void JackAudioDevice::graphChanged()                                    }                              // p3.3.55                              // Done with ports. Free them. -                            free(ports); +                            //free(ports); +                            jack_free(ports);  // p4.0.29                        }                      }                      }   @@ -1662,7 +1666,8 @@ std::list<QString> JackAudioDevice::outputPorts(bool midi, int aliases)        // p3.3.37        if(ports) -        free(ports);       +        //free(ports);       +        jack_free(ports);  // p4.0.29        return clientList;        } @@ -1734,7 +1739,8 @@ std::list<QString> JackAudioDevice::inputPorts(bool midi, int aliases)        // p3.3.37        if(ports) -        free(ports);       +        //free(ports);       +        jack_free(ports);  // p4.0.29        return clientList;        } diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp index 7d5eecc0..5861ca9e 100644 --- a/muse2/muse/functions.cpp +++ b/muse2/muse/functions.cpp @@ -319,7 +319,7 @@ bool modify_notelen(const set<Part*>& parts, int range, int rate, int offset)  			if (len <= 0)  				len = 1; -			if ((event.tick()+len > part->lenTick()) && (!part->hasHiddenNotes())) +			if ((event.tick()+len > part->lenTick()) && (!part->hasHiddenEvents()))  				partlen[part]=event.tick()+len; // schedule auto-expanding  			if (event.lenTick() != len) @@ -522,7 +522,7 @@ bool move_notes(const set<Part*>& parts, int range, signed int ticks)  			if (newEvent.endTick() > part->lenTick()) //if exceeding the part's end:  			{ -				if (part->hasHiddenNotes()) // auto-expanding is forbidden, clip +				if (part->hasHiddenEvents()) // auto-expanding is forbidden, clip  				{  					if (part->lenTick() > newEvent.tick())  						newEvent.setLenTick(part->lenTick() - newEvent.tick()); @@ -776,7 +776,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/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/master/masteredit.cpp b/muse2/muse/master/masteredit.cpp index 68e8a3b2..777e6066 100644 --- a/muse2/muse/master/masteredit.cpp +++ b/muse2/muse/master/masteredit.cpp @@ -112,6 +112,7 @@ MasterEdit::MasterEdit()        addToolBar(tools2);        QToolBar* enableMaster = addToolBar(tr("Enable master")); +      enableMaster->setObjectName("Enable master");        enableButton = new QToolButton();        enableButton->setCheckable(true);        enableButton->setText(tr("Enable")); @@ -121,6 +122,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); 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              }        } diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp index 921e59f6..615653b3 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; -    if (opart->hasHiddenNotes()) +    if (opart->hasHiddenEvents())      {  			forbidden=true;  			break; @@ -350,7 +350,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)); @@ -463,8 +463,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 5477752d..f8061c06 100644 --- a/muse2/muse/midiedit/drumedit.cpp +++ b/muse2/muse/midiedit/drumedit.cpp @@ -228,7 +228,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 d8fdc34d..c98657ea 100644 --- a/muse2/muse/midiedit/pianoroll.cpp +++ b/muse2/muse/midiedit/pianoroll.cpp @@ -178,7 +178,7 @@ PianoRoll::PianoRoll(PartList* pl, QWidget* parent, const char* name, unsigned i -      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 d06274b4..82a6a215 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; -    if (opart->hasHiddenNotes()) +    if (opart->hasHiddenEvents())      {  			forbidden=true;  			break; @@ -468,7 +523,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)); @@ -513,7 +568,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)); @@ -680,48 +735,6 @@ void PianoCanvas::pianoReleased(int pitch, bool)        }  //--------------------------------------------------------- -//   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  //--------------------------------------------------------- @@ -732,31 +745,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 2f077365..157a6845 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -422,7 +422,7 @@ ScoreEdit::ScoreEdit(QWidget* parent, const char* name, unsigned initPos) -  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())); @@ -3908,7 +3908,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; @@ -4461,7 +4461,7 @@ void staff_t::update_part_indices()   *    *   o maybe remove "insert empty measure"?   *   o add "move other notes" or "overwrite notes" or "mix with notes" to paste - *   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/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/part.cpp b/muse2/muse/part.cpp index 67cf441e..239d53d5 100644 --- a/muse2/muse/part.cpp +++ b/muse2/muse/part.cpp @@ -4,6 +4,7 @@  //  $Id: part.cpp,v 1.12.2.17 2009/06/25 05:13:02 terminator356 Exp $  //  //  (C) Copyright 1999/2000 Werner Schweer (ws@seh.de) +//  Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)  //=========================================================  #include <stdio.h> @@ -655,6 +656,7 @@ Part* PartList::find(int idx)  Part::Part(Track* t)        { +      _hiddenEvents = NoEventsHidden;        _prevClone = this;        _nextClone = this;        setSn(newSn()); @@ -673,6 +675,7 @@ Part::Part(Track* t)  Part::Part(Track* t, EventList* ev)        { +      _hiddenEvents = NoEventsHidden;        _prevClone = this;        _nextClone = this;        setSn(newSn()); @@ -849,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));                                      }                                } @@ -889,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);                          } @@ -1169,15 +1170,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..c7186a2d 100644 --- a/muse2/muse/widgets/canvas.cpp +++ b/muse2/muse/widgets/canvas.cpp @@ -3,6 +3,7 @@  //  Linux Music Editor  //    $Id: canvas.cpp,v 1.10.2.17 2009/05/03 04:14:01 terminator356 Exp $  //  (C) Copyright 1999 Werner Schweer (ws@seh.de) +//  Additions, modifications (C) Copyright 2011 Tim E. Real (terminator356 on users DOT sourceforge DOT net)  //=========================================================  #include <stdio.h> @@ -18,6 +19,8 @@  #include <QMouseEvent>  #include <QWheelEvent> +#include <vector> +  #include "song.h"  #include "event.h"  #include "citem.h" @@ -148,6 +151,11 @@ void Canvas::draw(QPainter& p, const QRect& rect)        int h = rect.height();        int x2 = x + w; +      std::vector<CItem*> list1; +      std::vector<CItem*> list2; +      //std::vector<CItem*> list3; +      std::vector<CItem*> list4; +        if (virt()) {              drawCanvas(p, rect); @@ -157,22 +165,24 @@ void Canvas::draw(QPainter& p, const QRect& rect)              iCItem to(items.lower_bound(x2)); +            /*              // Draw items from other parts behind all others.              // Only for items with events (not arranger parts).              for(iCItem i = items.begin(); i != to; ++i)              {                 CItem* ci = i->second; +              // NOTE Optimization: For each item call this once now, then use cached results later via cachedHasHiddenEvents(). +              ci->part()->hasHiddenEvents();                if(!ci->event().empty() && ci->part() != curPart) -              {                  drawItem(p, ci, rect); -              }              } -             +                 +            // Draw unselected parts behind selected.              for (iCItem i = items.begin(); i != to; ++i)               {                    CItem* ci = i->second; -                  // Draw unselected parts behind selected. -                  if(!ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart)) +                  if((!ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart)) +                     && !(ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents())))  // p4.0.29                     {                          drawItem(p, ci, rect);                    }       @@ -181,12 +191,57 @@ void Canvas::draw(QPainter& p, const QRect& rect)              // Draw selected parts in front of unselected.              for (iCItem i = items.begin(); i != to; ++i)               { -                  CItem* ci = i->second; -                  if(ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart)) -                  { -                        drawItem(p, ci, rect); -                  }       +                CItem* ci = i->second; +                if(ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart)) +                //if((ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))  +                //   || (ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents()))) +                { +                      drawItem(p, ci, rect); +                }       +            }   +            */ +             +            // p4.0.29 +            for(iCItem i = items.begin(); i != to; ++i) +            {  +              CItem* ci = i->second; +              // NOTE Optimization: For each item call this once now, then use cached results later via cachedHasHiddenEvents(). +              // Not required for now. +              //ci->part()->hasHiddenEvents(); +               +              // Draw items from other parts behind all others. +              // Only for items with events (not arranger parts). +              if(!ci->event().empty() && ci->part() != curPart) +                list1.push_back(ci);     +              else if(!ci->isMoving() && (ci->event().empty() || ci->part() == curPart)) +              { +                // Draw selected parts in front of all others. +                if(ci->isSelected())  +                  list4.push_back(ci); +                // Draw clone parts, and parts with hidden events, in front of others all except selected. +                //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents())) +                // Draw clone parts in front of others all except selected. +                //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1)) +                //  list3.push_back(ci); +                else   +                  // Draw unselected parts. +                  list2.push_back(ci); +              }                } +            int i; +            int sz = list1.size(); +            for(i = 0; i != sz; ++i)  +              drawItem(p, list1[i], rect); +            sz = list2.size(); +            for(i = 0; i != sz; ++i)  +              drawItem(p, list2[i], rect); +            //sz = list3.size(); +            //for(i = 0; i != sz; ++i)  +            //  drawItem(p, list3[i], rect); +            sz = list4.size(); +            for(i = 0; i != sz; ++i)  +              drawItem(p, list4[i], rect); +                          to = moving.lower_bound(x2);              for (iCItem i = moving.begin(); i != to; ++i)               { @@ -237,21 +292,22 @@ void Canvas::draw(QPainter& p, const QRect& rect)              //---------------------------------------------------              // draw Canvas Items              //--------------------------------------------------- -            +             +            /*              // Draw items from other parts behind all others.              // Only for items with events (not arranger parts).              for(iCItem i = items.begin(); i != items.end(); ++i)              {                 CItem* ci = i->second; +              // NOTE Optimization: For each item call this once now, then use cached results later via cachedHasHiddenEvents(). +              ci->part()->hasHiddenEvents();                if(!ci->event().empty() && ci->part() != curPart) -              {                  drawItem(p, ci, rect); -              } -            }   -               +            } +                 +            // Draw unselected parts behind selected.              for (iCItem i = items.begin(); i != items.end(); ++i) {                    CItem* ci = i->second; -                  // Draw unselected parts behind selected.                    if(!ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))                      {                          drawItem(p, ci, rect); @@ -262,10 +318,55 @@ void Canvas::draw(QPainter& p, const QRect& rect)              for (iCItem i = items.begin(); i != items.end(); ++i) {                    CItem* ci = i->second;                    if(ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart)) -                    {     -                        drawItem(p, ci, rect); -                    }     -                  }  +                  //if((ci->isSelected() && !ci->isMoving() && (ci->event().empty() || ci->part() == curPart))  +                  //   || (ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents()))) +                  {     +                      drawItem(p, ci, rect); +                  }     +                }  +            */ +             +            // p4.0.29 +            for(iCItem i = items.begin(); i != items.end(); ++i) +            {  +              CItem* ci = i->second; +              // NOTE Optimization: For each item call this once now, then use cached results later via cachedHasHiddenEvents(). +              // Not required for now. +              //ci->part()->hasHiddenEvents(); +               +              // Draw items from other parts behind all others. +              // Only for items with events (not arranger parts). +              if(!ci->event().empty() && ci->part() != curPart) +                list1.push_back(ci);     +              else if(!ci->isMoving() && (ci->event().empty() || ci->part() == curPart)) +              { +                // Draw selected parts in front of all others. +                if(ci->isSelected())  +                  list4.push_back(ci); +                // Draw clone parts, and parts with hidden events, in front of others all except selected. +                //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1 || ci->part()->cachedHasHiddenEvents())) +                // Draw clone parts in front of others all except selected. +                //else if(ci->event().empty() && (ci->part()->events()->arefCount() > 1)) +                //  list3.push_back(ci); +                else   +                  // Draw unselected parts. +                  list2.push_back(ci); +              }   +            }   +            int i; +            int sz = list1.size(); +            for(i = 0; i != sz; ++i)  +              drawItem(p, list1[i], rect); +            sz = list2.size(); +            for(i = 0; i != sz; ++i)  +              drawItem(p, list2[i], rect); +            //sz = list3.size(); +            //for(i = 0; i != sz; ++i)  +            //  drawItem(p, list3[i], rect); +            sz = list4.size(); +            for(i = 0; i != sz; ++i)  +              drawItem(p, list4[i], rect); +                          for (iCItem i = moving.begin(); i != moving.end(); ++i)                     {                          drawItem(p, i->second, rect); @@ -273,19 +374,26 @@ void Canvas::draw(QPainter& p, const QRect& rect)              drawTopItem(p, QRect(x,y,w,h));              p.save();              setPainter(p); -            } +      }        //---------------------------------------------------        //    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);                    }              } @@ -294,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/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/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 <QMenu> +#include <QSignalMapper> +#include <QWheelEvent>  #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<QAction *> actions = list->actions(); -      for (QList<QAction *>::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 <QLabel> +#include <QToolButton>  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<int> 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 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);        } @@ -94,6 +97,31 @@ void Knob::setTotalAngle (double angle)        }  //------------------------------------------------------------ +// 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); 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 <stdio.h>  #include <cmath>  #include <QMouseEvent> @@ -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 <stdio.h>  #include <cmath>  #include <QMouseEvent> @@ -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 <QFrame>  #include "meter.h" +class QPaintEvent;  class QResizeEvent;  class QMouseEvent;  class QPainter; diff --git a/muse2/muse/widgets/view.cpp b/muse2/muse/widgets/view.cpp index fb480527..57955c19 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,10 @@  #include <QKeyEvent>  #include <QPaintEvent> +#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  @@ -491,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;                    } @@ -535,19 +547,116 @@ 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  //--------------------------------------------------------- +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 +694,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 +762,166 @@ 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; +      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;   +            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 { +            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; +            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 { +            yy = r.y()*ymag - ypos - lrint(rmapy_f(yorg)); +            hh = r.height() * ymag; +            } +      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;   +            } +      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); +      */ +      return QPoint(mapx(p.x()), mapy(p.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..a932f173 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__ @@ -49,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&); @@ -77,6 +79,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); | 
