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/editors/notation/TrackHeader.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/editors/notation/TrackHeader.cpp')
-rw-r--r-- | src/gui/editors/notation/TrackHeader.cpp | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/src/gui/editors/notation/TrackHeader.cpp b/src/gui/editors/notation/TrackHeader.cpp new file mode 100644 index 0000000..32fab2f --- /dev/null +++ b/src/gui/editors/notation/TrackHeader.cpp @@ -0,0 +1,450 @@ +/* -*- 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 <[email protected]>, + Chris Cannam <[email protected]>, + Richard Bown <[email protected]> + + This file is Copyright 2007-2008 + Yves Guillemot <[email protected]> + + 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 "TrackHeader.h" +#include "HeadersGroup.h" +#include "base/Composition.h" +#include "base/NotationTypes.h" +#include "base/StaffExportTypes.h" +#include "base/Colour.h" +#include "base/ColourMap.h" +#include "base/Track.h" +#include "gui/general/GUIPalette.h" +#include "gui/general/LinedStaff.h" +#include "document/RosegardenGUIDoc.h" +#include "misc/Strings.h" +#include "NotePixmapFactory.h" +#include "NotationView.h" +#include "NotationStaff.h" + +#include <map> +#include <set> +#include <string> +#include <utility> + +#include <kapplication.h> +#include <klocale.h> +#include <qsize.h> +#include <qwidget.h> +#include <qhbox.h> +#include <qvbox.h> +#include <qpushbutton.h> +#include <qlabel.h> +#include <qframe.h> +#include <qstring.h> +#include <qtooltip.h> + + +namespace Rosegarden +{ + + +// Status bits +const int TrackHeader::SEGMENT_HERE = 1 << 0; +const int TrackHeader::SUPERIMPOSED_SEGMENTS = 1 << 1; +const int TrackHeader::INCONSISTENT_CLEFS = 1 << 2; +const int TrackHeader::INCONSISTENT_KEYS = 1 << 3; +const int TrackHeader::INCONSISTENT_LABELS = 1 << 4; +const int TrackHeader::INCONSISTENT_TRANSPOSITIONS = 1 << 5; +const int TrackHeader::BEFORE_FIRST_SEGMENT = 1 << 6; + + +TrackHeader::TrackHeader(QWidget *parent, TrackId trackId, int height, int ypos) : + QLabel(parent), + m_track(trackId), + m_height(height), + m_ypos(ypos), + m_lastClef(Clef()), + m_lastKey(Rosegarden::Key()), + m_lastLabel(QString("")), + m_lastTranspose(0), + m_lastUpperText(QString("")), + m_neverUpdated(true), + m_isCurrent(true), + m_lastStatusPart(0), + m_lastWidth(0), + m_key(Rosegarden::Key()), + m_label(QString("")), + m_transpose(0), + m_status(0), + m_current(false) +{ + + m_notationView = static_cast<HeadersGroup *>(parent)->getNotationView(); + + setFrameStyle(QFrame::Box | QFrame::Plain); + setCurrent(false); + + + // + // Tooltip text creation + + Composition *comp = + static_cast<HeadersGroup *>(parent)->getComposition(); + Track *track = comp->getTrackById(m_track); + int trackPos = comp->getTrackPositionById(m_track); + + QString toolTipText = QString(i18n("Track %1 : \"%2\"") + .arg(trackPos + 1) + .arg(strtoqstr(track->getLabel()))); + + QString preset = track->getPresetLabel(); + if (preset != QString("")) + toolTipText += QString(i18n("\nNotate for: %1").arg(preset)); + + QString notationSize = i18n("normal"); + switch (track->getStaffSize()) { + case StaffTypes::Small: + notationSize = i18n("small"); + break; + case StaffTypes::Tiny: + notationSize = i18n("tiny"); + break; + } + + QString bracketText = i18n("--"); + switch (track->getStaffBracket()) { + case Brackets::SquareOn: + bracketText = "[-"; + break; + case Brackets::SquareOff: + bracketText = "-]"; + break; + case Brackets::SquareOnOff: + bracketText = "[-]"; + break; + case Brackets::CurlyOn: + bracketText = "{-"; + break; + case Brackets::CurlyOff: + bracketText = "-}"; + break; + case Brackets::CurlySquareOn: + bracketText = "{[-"; + break; + case Brackets::CurlySquareOff: + bracketText = "-]}"; + break; + } + + toolTipText += QString(i18n("\nSize: %1, Bracket: %2 ")) + .arg(notationSize) + .arg(bracketText); + + // Sort segments by position on the track + SortedSegments segments; + for (int i=0; i<m_notationView->getStaffCount(); i++) { + + NotationStaff * notationStaff = m_notationView->getNotationStaff(i); + Segment &segment = notationStaff->getSegment(); + TrackId trackId = segment.getTrack(); + + if (trackId == m_track) { + segments.insert(&segment); + } + } + + for (SortedSegments::iterator i=segments.begin(); i!=segments.end(); ++i) { + timeT segStart = (*i)->getStartTime(); + timeT segEnd = (*i)->getEndMarkerTime(); + int barStart = comp->getBarNumber(segStart) + 1; + int barEnd = comp->getBarNumber(segEnd) + 1; + + int transpose = (*i)->getTranspose(); + if (transpose) { + QString transposeName; + transposeValueToName(transpose, transposeName); + toolTipText += QString(i18n("\nbars [%1-%2] in %3 (tr=%4) : \"%5\"")) + .arg(barStart) + .arg(barEnd) + .arg(transposeName) + .arg(transpose) + .arg(strtoqstr((*i)->getLabel())); + } else { + toolTipText += QString(i18n("\nbars [%1-%2] (tr=%3) : \"%4\"")) + .arg(barStart) + .arg(barEnd) + .arg(transpose) + .arg(strtoqstr((*i)->getLabel())); + } + } + + QToolTip::add(this, toolTipText); + + m_firstSeg = *segments.begin(); + m_firstSegStartTime = m_firstSeg->getStartTime(); + + /// This may not work if two segments are superimposed + /// at the beginning of the track (inconsistencies are + /// not detected). + /// TODO : Look for the first segment(s) in + /// lookAtStaff() and not here. +} + +void +TrackHeader::setCurrent(bool current) +{ + /// TODO : use colours from GUIPalette + + if (current != m_isCurrent) { + m_isCurrent = current; + if (current) { + setLineWidth(2); + setMargin(0); + setPaletteForegroundColor(QColor(0, 0, 255)); + } else { + setLineWidth(1); + setMargin(1); + setPaletteForegroundColor(QColor(0, 0, 0)); + } + } +} + +void +TrackHeader::transposeValueToName(int transpose, QString &transposeName) +{ + + /// TODO : Should be rewrited using methods from Pitch class + + int noteIndex = transpose % 12; + if (noteIndex < 0) noteIndex += 12; + + switch(noteIndex) { + case 0 : transposeName = i18n("C"); break; + case 1 : transposeName = i18n("C#"); break; + case 2 : transposeName = i18n("D"); break; + case 3 : transposeName = i18n("Eb"); break; + case 4 : transposeName = i18n("E"); break; + case 5 : transposeName = i18n("F"); break; + case 6 : transposeName = i18n("F#"); break; + case 7 : transposeName = i18n("G"); break; + case 8 : transposeName = i18n("G#"); break; + case 9 : transposeName = i18n("A"); break; + case 10 : transposeName = i18n("Bb"); break; + case 11 : transposeName = i18n("B"); break; + } +} + +int +TrackHeader::lookAtStaff(double x, int maxWidth) +{ + // Read Clef and Key on canvas at (x, m_ypos + m_height / 2) + // then guess the header needed width and return it + + // When walking through the segments : + // clef, key, label and transpose are current values + // clef0, key0, label0 and transpose0 are preceding values used to look + // for inconsistencies + // key1, label1 and transpose1 are "visible" (opposed at invisible as are + // key=<C major>, label="" or transpose=0) + // preceding or current values which may be + // displayed with a red colour if some + // inconsistency occurs. + Clef clef, clef0; + Rosegarden::Key key, key0, key1 = Rosegarden::Key("C major"); + QString label = QString(""), label0, label1 = QString(""); + int transpose = 0, transpose0, transpose1 = 0; + + int staff; + + Composition *comp = + static_cast<HeadersGroup *>(parent())->getComposition(); + Track *track = comp->getTrackById(m_track); + int trackPos = comp->getTrackPositionById(m_track); + + int status = 0; + bool current = false; + for (int i=0; i<m_notationView->getStaffCount(); i++) { + NotationStaff * notationStaff = m_notationView->getNotationStaff(i); + Segment &segment = notationStaff->getSegment(); + TrackId trackId = segment.getTrack(); + if (trackId == m_track) { + + /// TODO : What if a segment has been moved ??? + timeT xTime = notationStaff->getTimeAtCanvasCoords(x, m_ypos); + if (xTime < m_firstSegStartTime) { + status |= BEFORE_FIRST_SEGMENT; + /// TODO : What if superimposed segments ??? + m_firstSeg->getFirstClefAndKey(clef, key); + label = strtoqstr(m_firstSeg->getLabel()); + transpose = m_firstSeg->getTranspose(); + current = current || m_notationView->isCurrentStaff(i); + break; + } + timeT segStart = segment.getStartTime(); + timeT segEnd = segment.getEndMarkerTime(); + current = current || m_notationView->isCurrentStaff(i); + + if ((xTime >= segStart) && (xTime < segEnd)) { + + notationStaff->getClefAndKeyAtCanvasCoords(x, + m_ypos + m_height / 2, clef, key); + label = strtoqstr(segment.getLabel()); + transpose = segment.getTranspose(); + + if (status & SEGMENT_HERE) { + status |= SUPERIMPOSED_SEGMENTS; + if (clef != clef0) + status |= INCONSISTENT_CLEFS; + if (key != key0) + status |= INCONSISTENT_KEYS; + if (label != label0) + status |= INCONSISTENT_LABELS; + if (transpose != transpose0) + status |= INCONSISTENT_TRANSPOSITIONS; + } else { + status |= SEGMENT_HERE; + } + + staff = i; + + // If current value is visible, remember it + if (key.getAccidentalCount()) key1 = key; + if (label.stripWhiteSpace().length()) label1 = label; + if (transpose) transpose1 = transpose; + + // Current values become last values + clef0 = clef; + key0 = key; + label0 = label; + transpose0 = transpose; + } // if(xTime...) + } // if(trackId...) + } + + // Remember current data (but only visible data if inconsistency) + m_clef = clef; + m_key = (status & INCONSISTENT_KEYS) ? key1 : key; + m_label = (status & INCONSISTENT_LABELS) ? label1 : label; + m_transpose = (status & INCONSISTENT_TRANSPOSITIONS) ? transpose1 : transpose; + m_current = current; + m_status = status; + + QString noteName; + transposeValueToName(m_transpose, noteName); + + m_upperText = QString(i18n("%1: %2") + .arg(trackPos + 1) + .arg(strtoqstr(track->getLabel()))); + if (m_transpose) m_transposeText = i18n(" in %1").arg(noteName); + else m_transposeText = QString(""); + + NotePixmapFactory * npf = m_notationView->getNotePixmapFactory(); + int clefAndKeyWidth = npf->getClefAndKeyWidth(m_key, m_clef); + + // How many text lines may be written above or under the clef + // in track header ? + m_numberOfTextLines = npf->getTrackHeaderNTL(m_height); + + int trackLabelWidth = + npf->getTrackHeaderTextWidth(m_upperText + m_transposeText) + / m_numberOfTextLines; + int segmentNameWidth = + npf->getTrackHeaderTextWidth(m_label) / m_numberOfTextLines; + + // Get the max. width from upper text and lower text + int width = (segmentNameWidth > trackLabelWidth) + ? segmentNameWidth : trackLabelWidth; + + // Text width is limited by max header Width + if (width > maxWidth) width = maxWidth; + + // But clef and key width may override max header width + if (width < clefAndKeyWidth) width = clefAndKeyWidth; + + return width; +} + + + +void +TrackHeader::updateHeader(int width) +{ + + // Update the header (using given width) if necessary + + // Filter out bits whose display doesn't depend from + int statusPart = m_status & ~(SUPERIMPOSED_SEGMENTS); + + // Header should be updated only if necessary + if ( m_neverUpdated + || (width != m_lastWidth) + || (statusPart != m_lastStatusPart) + || (m_key != m_lastKey) + || (m_clef != m_lastClef) + || (m_label != m_lastLabel) + || (m_upperText != m_lastUpperText) + || (m_transpose != m_lastTranspose)) { + + m_neverUpdated = false; + m_lastStatusPart = statusPart; + m_lastKey = m_key; + m_lastClef = m_clef; + m_lastLabel = m_label; + m_lastTranspose = m_transpose; + m_lastUpperText = m_upperText; + + bool drawClef = true; + QColor clefColour; + if (m_status & (SEGMENT_HERE | BEFORE_FIRST_SEGMENT)) { + if (m_status & (INCONSISTENT_CLEFS | INCONSISTENT_KEYS)) + clefColour = Qt::red; + else + clefColour = Qt::black; + } else { + drawClef = false; + } + + NotePixmapFactory * npf = m_notationView->getNotePixmapFactory(); + QPixmap pmap = NotePixmapFactory::toQPixmap( + npf->makeTrackHeaderPixmap(width, m_height, this)); + + setPixmap(pmap); + setFixedWidth(width); + + // Forced width may differ from localy computed width + m_lastWidth = width; + } + + // Highlight header if track is the current one + setCurrent(m_current); +} + +bool +TrackHeader::SegmentCmp::operator()(const Segment * s1, const Segment * s2) const +{ + // Sort segments by start time, then by end time + if (s1->getStartTime() < s2->getStartTime()) return true; + if (s1->getStartTime() > s2->getStartTime()) return false; + if (s1->getEndMarkerTime() < s2->getEndMarkerTime()) return true; + return false; +} + +} +#include "TrackHeader.moc" |