diff options
| author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 18:37:05 +0000 | 
|---|---|---|
| committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 18:37:05 +0000 | 
| commit | 145364a8af6a1fec06556221e66d4b724a62fc9a (patch) | |
| tree | 53bd71a544008c518034f208d64c932dc2883f50 /src/gui/rulers/RawNoteRuler.cpp | |
| download | rosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.tar.gz rosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.zip | |
Added old abandoned KDE3 version of the RoseGarden MIDI tool
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/rosegarden@1097595 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/gui/rulers/RawNoteRuler.cpp')
| -rw-r--r-- | src/gui/rulers/RawNoteRuler.cpp | 573 | 
1 files changed, 573 insertions, 0 deletions
| diff --git a/src/gui/rulers/RawNoteRuler.cpp b/src/gui/rulers/RawNoteRuler.cpp new file mode 100644 index 0000000..cc7d6e4 --- /dev/null +++ b/src/gui/rulers/RawNoteRuler.cpp @@ -0,0 +1,573 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* +    Rosegarden +    A MIDI and audio sequencer and musical notation editor. +  +    This program is Copyright 2000-2008 +        Guillaume Laurent   <glaurent@telegraph-road.org>, +        Chris Cannam        <cannam@all-day-breakfast.com>, +        Richard Bown        <richard.bown@ferventsoftware.com> +  +    The moral rights of Guillaume Laurent, Chris Cannam, and Richard +    Bown to claim authorship of this work have been asserted. +  +    Other copyrights also apply to some parts of this work.  Please +    see the AUTHORS file and individual file headers for details. +  +    This program is free software; you can redistribute it and/or +    modify it under the terms of the GNU General Public License as +    published by the Free Software Foundation; either version 2 of the +    License, or (at your option) any later version.  See the file +    COPYING included with this distribution for more information. +*/ + + +#include "RawNoteRuler.h" + +#include "misc/Debug.h" +#include "base/BaseProperties.h" +#include "base/Composition.h" +#include "base/NotationTypes.h" +#include "base/NotationQuantizer.h" +#include "base/RulerScale.h" +#include "base/Segment.h" +#include "DefaultVelocityColour.h" +#include "gui/general/GUIPalette.h" +#include <klocale.h> +#include <qcolor.h> +#include <qpainter.h> +#include <qrect.h> +#include <qsize.h> +#include <qtooltip.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +RawNoteRuler::RawNoteRuler(RulerScale *rulerScale, +                           Segment *segment, +                           double xorigin, +                           int height, +                           QWidget *parent, +                           const char *name) : +        QWidget(parent, name), +        m_xorigin(xorigin), +        m_height(height), +        m_currentXOffset(0), +        m_width( -1), +        m_segment(segment), +        m_rulerScale(rulerScale) +{ +    setBackgroundColor(GUIPalette::getColour(GUIPalette::RawNoteRulerBackground)); +    QToolTip::add(this,""); +} + +RawNoteRuler::~RawNoteRuler() +{ +    QToolTip::remove(this); +    // nothing else +} + +void +RawNoteRuler::slotScrollHoriz(int x) +{ +    int w = width(), h = height(); +    int dx = x - ( -m_currentXOffset); +    if (dx == 0) +        return ; +    m_currentXOffset = -x; + +    if (dx > w*3 / 4 || dx < -w*3 / 4) { +        update(); +        return ; +    } + +    if (dx > 0) { // moving right, so the existing stuff moves left +        bitBlt(this, 0, 0, this, dx, 0, w - dx, h); +        repaint(w - dx, 0, dx, h); +    } else {      // moving left, so the existing stuff moves right +        bitBlt(this, -dx, 0, this, 0, 0, w + dx, h); +        repaint(0, 0, -dx, h); +    } +} + +QSize +RawNoteRuler::sizeHint() const +{ +    double width = +        m_rulerScale->getBarPosition(m_rulerScale->getLastVisibleBar()) + +        m_rulerScale->getBarWidth(m_rulerScale->getLastVisibleBar()) + +        m_xorigin; + +    QSize res(std::max(int(width), m_width), m_height); + +    return res; +} + +QSize +RawNoteRuler::minimumSizeHint() const +{ +    double firstBarWidth = m_rulerScale->getBarWidth(0) + m_xorigin; +    QSize res = QSize(int(firstBarWidth), m_height); +    return res; +} + +std::pair<timeT, timeT> +RawNoteRuler::getExtents(Segment::iterator i) +{ +    const Quantizer *q = +        m_segment->getComposition()->getNotationQuantizer(); + +    timeT u0 = (*i)->getAbsoluteTime(); +    timeT u1 = u0 + (*i)->getDuration(); + +    timeT q0 = q->getQuantizedAbsoluteTime(*i); +    timeT q1 = q0 + q->getQuantizedDuration(*i); + +    timeT t0 = std::min(u0, q0); +    timeT t1 = std::max(u1, q1); + +    return std::pair<timeT, timeT>(t0, t1); +} + +Segment::iterator +RawNoteRuler::addChildren(Segment *s, +                          Segment::iterator to, +                          timeT rightBound, +                          EventTreeNode *node) +{ +    Segment::iterator i = node->node; + +    std::pair<timeT, timeT> iex = getExtents(i); +    Segment::iterator j = i; +    Segment::iterator rightmost = to; + +#ifdef DEBUG_RAW_NOTE_RULER + +    RG_DEBUG << "addChildren called for extents " << iex.first << "->" << iex.second << ", rightBound " << rightBound << endl; +#endif + +    for (++j; j != to && s->isBeforeEndMarker(j); ) { + +        if (!(*j)->isa(Note::EventType)) { +            ++j; +            continue; +        } +        std::pair<timeT, timeT> jex = getExtents(j); + +#ifdef DEBUG_RAW_NOTE_RULER + +        RG_DEBUG << "addChildren: event at " << (*j)->getAbsoluteTime() << ", extents " << jex.first << "->" << jex.second << endl; +#endif + +        if (jex.first == jex.second) { +            ++j; +            continue; +        } +        if (jex.first >= iex.second || jex.first >= rightBound) +            break; + +#ifdef DEBUG_RAW_NOTE_RULER + +        RG_DEBUG << "addChildren: adding" << endl; +#endif + +        EventTreeNode *subnode = new EventTreeNode(j); + +        Segment::iterator subRightmost = addChildren(s, to, rightBound, subnode); +        if (subRightmost != to) +            rightmost = subRightmost; +        else +            rightmost = j; + +        node->children.push_back(subnode); +        j = s->findTime(jex.second); +    } + +    return rightmost; +} + +void +RawNoteRuler::buildForest(Segment *s, +                          Segment::iterator from, +                          Segment::iterator to) +{ +    for (EventTreeNode::NodeList::iterator i = m_forest.begin(); +            i != m_forest.end(); ++i) { +        delete *i; +    } +    m_forest.clear(); + +    timeT endTime = (s->isBeforeEndMarker(to) ? (*to)->getAbsoluteTime() : +                     s->getEndMarkerTime()); + +    for (Segment::iterator i = from; i != to && s->isBeforeEndMarker(i); ) { + +        if (!(*i)->isa(Note::EventType)) { +            ++i; +            continue; +        } + +        std::pair<timeT, timeT> iex = getExtents(i); + +#ifdef DEBUG_RAW_NOTE_RULER + +        RG_DEBUG << "buildForest: event at " << (*i)->getAbsoluteTime() << ", extents " << iex.first << "->" << iex.second << endl; +#endif + +        if (iex.first == iex.second) { +            ++i; +            continue; +        } +        if (iex.first >= endTime) +            break; + +        EventTreeNode *node = new EventTreeNode(i); +        Segment::iterator rightmost = addChildren(s, to, iex.second, node); +        m_forest.push_back(node); + +        if (rightmost != to) { +            i = rightmost; +            ++i; +        } else { +            i = s->findTime(iex.second); +        } + +#ifdef DEBUG_RAW_NOTE_RULER +        RG_DEBUG << "findTime " << iex.second << " returned iterator at " << (i == s->end() ? -1 : (*i)->getAbsoluteTime()) << endl; +#endif + +    } +} + +void +RawNoteRuler::dumpSubtree(EventTreeNode *node, int depth) +{ +    if (!node) +        return ; +#ifdef DEBUG_RAW_NOTE_RULER + +    for (int i = 0; i < depth; ++i) +        std::cerr << "  "; +    if (depth > 0) +        std::cerr << "->"; +    std::cerr << (*node->node)->getAbsoluteTime() << "," +    << (*node->node)->getDuration() << " ["; +    long pitch = 0; +    if ((*node->node)->get +            <Int>(PITCH, pitch)) { +        std::cerr << pitch << "]" << std::endl; +    } +    else { +        std::cerr << "no-pitch]" << std::endl; +    } +    for (EventTreeNode::NodeList::iterator i = node->children.begin(); +            i != node->children.end(); ++i) { +        dumpSubtree(*i, depth + 1); +    } +#endif +    (void)depth; // avoid warnings +} + +void +RawNoteRuler::dumpForest(EventTreeNode::NodeList *forest) +{ +#ifdef DEBUG_RAW_NOTE_RULER +    std::cerr << "\nFOREST:\n" << std::endl; + +    for (unsigned int i = 0; i < forest->size(); ++i) { + +        std::cerr << "\nTREE " << i << ":\n" << std::endl; +        dumpSubtree((*forest)[i], 0); +    } + +    std::cerr << std::endl; +#endif + +    (void)forest; // avoid warnings +} + +int +RawNoteRuler::EventTreeNode::getDepth() +{ +    int subchildrenDepth = 0; +    for (NodeList::iterator i = children.begin(); +            i != children.end(); ++i) { +        int subchildDepth = (*i)->getDepth(); +        if (subchildDepth > subchildrenDepth) +            subchildrenDepth = subchildDepth; +    } +    return subchildrenDepth + 1; +} + +int +RawNoteRuler::EventTreeNode::getChildrenAboveOrBelow(bool below, int p) +{ +    long pitch(p); +    if (pitch < 0) +        (*node)->get +        <Int>(BaseProperties::PITCH, pitch); + +    int max = 0; + +    for (NodeList::iterator i = children.begin(); +            i != children.end(); ++i) { +        int forThisChild = (*i)->getChildrenAboveOrBelow(below, pitch); +        long thisChildPitch = pitch; +        (*(*i)->node)->get +        <Int>(BaseProperties::PITCH, thisChildPitch); +        if (below ? (thisChildPitch < pitch) : (thisChildPitch > pitch)) { +            ++forThisChild; +        } +        if (forThisChild > max) +            max = forThisChild; +    } + +    return max; +} + +void +RawNoteRuler::drawNode(QPainter &paint, DefaultVelocityColour &vc, +                       EventTreeNode *node, double height, double yorigin) +{ +    int depth = node->getDepth(); +    int above = node->getChildrenAboveOrBelow(false); + +#ifdef DEBUG_RAW_NOTE_RULER + +    int below = node->getChildrenAboveOrBelow(true); + +    NOTATION_DEBUG << "RawNoteRuler::drawNode: children above: " +    << above << ", below: " << below << endl; +#endif + +    int toFit = depth; + +    double heightPer = double(height) / toFit; +    if (heightPer > m_height / 4) +        heightPer = m_height / 4; +    if (heightPer < 2) +        heightPer = 2; + +    double myOrigin = yorigin + (heightPer * above); +    long myPitch = 60; +    (*node->node)->get +    <Int>(BaseProperties::PITCH, myPitch); + +    long velocity = 100; +    (*node->node)->get +    <Int>(BaseProperties::VELOCITY, velocity); +    QColor colour = vc.getColour(velocity); + +    timeT start = (*node->node)->getAbsoluteTime(); +    timeT end = (*node->node)->getDuration() + start; + +    double u0 = m_rulerScale->getXForTime(start); +    double u1 = m_rulerScale->getXForTime(end); + +    u0 += m_currentXOffset + m_xorigin; +    u1 += m_currentXOffset + m_xorigin; + +    start = m_segment->getComposition()->getNotationQuantizer()-> +            getQuantizedAbsoluteTime(*node->node); +    end = start + m_segment->getComposition()->getNotationQuantizer()-> +          getQuantizedDuration(*node->node); + +    double q0 = m_rulerScale->getXForTime(start); +    double q1 = m_rulerScale->getXForTime(end); + +    q0 += m_currentXOffset + m_xorigin; +    q1 += m_currentXOffset + m_xorigin; + +#ifdef DEBUG_RAW_NOTE_RULER + +    NOTATION_DEBUG << "RawNoteRuler: (" << int(start) << "," << myOrigin +    << ") -> (" << int(end) << "," << myOrigin << ")" << endl; +#endif + +    int qi0 = int(q0); +    int ui0 = int(u0); +    int qi1 = int(q1); +    int ui1 = int(u1); +    //    int qiw = int(q1-q0) - 1; +    int uiw = int(u1 - u0) - 1; +    //    int iy = int(myOrigin + (height - heightPer) / 2); +    int iy = int(myOrigin); +    int ih = int(heightPer); + +#ifdef DEBUG_RAW_NOTE_RULER + +    NOTATION_DEBUG << "RawNoteRuler: height " << height << ", heightPer " +    << heightPer << ", iy " << iy << endl; +#endif + +    paint.setPen(colour); +    paint.setBrush(colour); +    paint.drawRect(ui0 + 1, iy + 1, uiw, ih - 1); + +    paint.setPen(GUIPalette::getColour(GUIPalette::RawNoteRulerForeground)); +    paint.setBrush(GUIPalette::getColour(GUIPalette::RawNoteRulerForeground)); +    paint.drawLine(qi0, iy, qi1 - 1, iy); +    paint.drawLine(qi0, iy + ih, qi1 - 1, iy + ih); +    paint.drawLine(ui0, iy + 1, ui0, iy + ih - 1); +    paint.drawLine(ui1 - 1, iy + 1, ui1 - 1, iy + ih - 1); + +    for (EventTreeNode::NodeList::iterator i = node->children.begin(); +            i != node->children.end(); ++i) { + +        long nodePitch = myPitch; +        (*(*i)->node)->get +        <Int>(BaseProperties::PITCH, nodePitch); + +        if (nodePitch < myPitch) { + +            drawNode(paint, vc, *i, +                     height - heightPer - myOrigin, myOrigin + heightPer); + +        } else { + +            drawNode(paint, vc, *i, +                     myOrigin - yorigin, yorigin); +        } +    } +} + +void +RawNoteRuler::paintEvent(QPaintEvent* e) +{ +    if (!m_segment || !m_segment->getComposition()) +        return ; + +    // Tooltips +    { +	QToolTip::remove(this); +	TrackId trackId = m_segment->getTrack(); +	Track *track = +	    m_segment->getComposition()->getTrackById(trackId); +        int trackPosition = -1; +        if (track) +            trackPosition = track->getPosition(); + +	QToolTip::add(this,i18n("Track #%1, Segment \"%2\" (runtime id %3)") +		           .arg(trackPosition + 1) +		           .arg(m_segment->getLabel()) +		           .arg(m_segment->getRuntimeId())); +    } + +    //    START_TIMING; + +    QPainter paint(this); +    paint.setClipRegion(e->region()); +    paint.setClipRect(e->rect().normalize()); + +    QRect clipRect = paint.clipRegion().boundingRect(); + +    timeT from = m_rulerScale->getTimeForX +                 (clipRect.x() - m_currentXOffset - 100 - m_xorigin); +    timeT to = m_rulerScale->getTimeForX +               (clipRect.x() + clipRect.width() - m_currentXOffset + 100 - m_xorigin); + +    paint.setPen(GUIPalette::getColour(GUIPalette::RawNoteRulerForeground)); +    paint.setBrush(GUIPalette::getColour(GUIPalette::RawNoteRulerForeground)); +    paint.drawLine(0, 0, width(), 0); + +    // draw the extent of the segment using its color + +    QColor brushColor = GUIPalette::convertColour(m_segment->getComposition()-> +                        getSegmentColourMap().getColourByIndex(m_segment->getColourIndex())); +    paint.setPen(brushColor); +    paint.setBrush(brushColor); +    int x0 = int(m_rulerScale->getXForTime(m_segment->getStartTime()) +  +		 m_currentXOffset + m_xorigin); +    int x1 = int(m_rulerScale->getXForTime(m_segment->getEndTime()) +  +		 m_currentXOffset + m_xorigin); +    paint.drawRect(x0, 1, x1-x0+1, height()-1); + +    // draw the bar divisions + +    int firstBar = m_segment->getComposition()->getBarNumber(from); +    int lastBar = m_segment->getComposition()->getBarNumber(to); +    std::vector<int> divisions; + +    for (int barNo = firstBar; barNo <= lastBar; ++barNo) { + +        bool isNew = false; +        TimeSignature timeSig = +            m_segment->getComposition()->getTimeSignatureInBar(barNo, isNew); +        if (isNew || barNo == firstBar) { +            timeSig.getDivisions(3, divisions); +            if (timeSig == TimeSignature()) // special case for 4/4 +                divisions[0] = 2; +        } + +        timeT barStart = m_segment->getComposition()->getBarStart(barNo); +        timeT base = timeSig.getBarDuration(); +        timeT barEnd = barStart + base; + +        paint.setPen(GUIPalette::getColour(GUIPalette::RawNoteRulerForeground)); +        paint.setBrush(GUIPalette::getColour(GUIPalette::RawNoteRulerForeground)); + +        int x = int(m_rulerScale->getXForTime(barStart) + +                    m_currentXOffset + m_xorigin); +        paint.drawLine(x, 1, x, m_height); + +        for (int depth = 0; depth < 3; ++depth) { + +            int grey = depth * 60 + 60; +            paint.setPen(QColor(grey, grey, grey)); +            paint.setBrush(QColor(grey, grey, grey)); + +            base /= divisions[depth]; +            timeT t(barStart + base); +            while (t < barEnd) { +                if ((t - barStart) % (base * divisions[depth]) != 0) { +                    int x = int(m_rulerScale->getXForTime(t) + +                                m_currentXOffset + m_xorigin); +                    paint.drawLine(x, 1, x, m_height); +                } +                t += base; +            } +        } +    } + +    //    PRINT_ELAPSED("RawNoteRuler::paintEvent: drawing bar lines and divisions"); + +#ifdef DEBUG_RAW_NOTE_RULER +    NOTATION_DEBUG << "RawNoteRuler: from is " << from << ", to is " << to << endl; +#endif + +    Segment::iterator i = m_segment->findNearestTime(from); +    if (i == m_segment->end()) +        i = m_segment->begin(); + +    // somewhat experimental, as is this whole class +    Segment::iterator j = m_segment->findTime(to); +    buildForest(m_segment, i, j); + +    //    PRINT_ELAPSED("RawNoteRuler::paintEvent: buildForest"); + +    dumpForest(&m_forest); + +    //    PRINT_ELAPSED("RawNoteRuler::paintEvent: dumpForest"); + +    for (EventTreeNode::NodeList::iterator fi = m_forest.begin(); +            fi != m_forest.end(); ++fi) { + +        // Each tree in the forest should represent a note that starts +        // at a time when no other notes are playing (at least of +        // those that started no earlier than the paint start time). +        // Each node in that tree represents a note that starts +        // playing during its parent node's note, or at the same time +        // as it. + +        drawNode(paint, *DefaultVelocityColour::getInstance(), *fi, m_height - 3, 2); + +    } + +    //    PRINT_ELAPSED("RawNoteRuler::paintEvent: complete"); +} + +} +#include "RawNoteRuler.moc" | 
