Vector<IntRect> DocumentMarkerController::renderedRectsForMarkers(DocumentMarker::MarkerType markerType) { Vector<IntRect> result; if (!possiblyHasMarkers(markerType)) return result; ASSERT(!(m_markers.isEmpty())); // outer loop: process each node MarkerMap::iterator end = m_markers.end(); for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) { // inner loop; process each marker in this node MarkerList* list = nodeIterator->value; unsigned markerCount = list->size(); for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { const RenderedDocumentMarker& marker = list->at(markerIndex); // skip marker that is wrong type if (marker.type() != markerType) continue; if (!marker.isRendered()) continue; result.append(marker.renderedRect()); } } return result; }
void DocumentMarkerController::clearDescriptionOnMarkersIntersectingRange(Range* range, DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!m_markers.isEmpty()); Node* startContainer = range->startContainer(); Node* endContainer = range->endContainer(); Node* pastLastNode = range->pastLastNode(); for (Node* node = range->firstNode(); node != pastLastNode; node = NodeTraversal::next(node)) { unsigned startOffset = node == startContainer ? range->startOffset() : 0; unsigned endOffset = node == endContainer ? static_cast<unsigned>(range->endOffset()) : std::numeric_limits<unsigned>::max(); MarkerList* list = m_markers.get(node); if (!list) continue; for (size_t i = 0; i < list->size(); ++i) { DocumentMarker& marker = list->at(i); // markers are returned in order, so stop if we are now past the specified range if (marker.startOffset() >= endOffset) break; // skip marker that is wrong type or before target if (marker.endOffset() <= startOffset || !markerTypes.contains(marker.type())) { i++; continue; } marker.clearDetails(); } } }
DocumentMarker* DocumentMarkerController::markerContainingPoint(const LayoutPoint& point, DocumentMarker::MarkerType markerType) { if (!possiblyHasMarkers(markerType)) return 0; ASSERT(!(m_markers.isEmpty())); // outer loop: process each node that contains any markers MarkerMap::iterator end = m_markers.end(); for (MarkerMap::iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) { // inner loop; process each marker in this node MarkerList* list = nodeIterator->value; unsigned markerCount = list->size(); for (unsigned markerIndex = 0; markerIndex < markerCount; ++markerIndex) { RenderedDocumentMarker& marker = list->at(markerIndex); // skip marker that is wrong type if (marker.type() != markerType) continue; if (marker.contains(point)) return ▮ } } return 0; }
void DocumentMarkerController::shiftMarkers(Node* node, unsigned startOffset, int delta) { if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) return; ASSERT(!m_markers.isEmpty()); MarkerList* list = m_markers.get(node); if (!list) return; bool docDirty = false; for (size_t i = 0; i != list->size(); ++i) { RenderedDocumentMarker& marker = list->at(i); if (marker.startOffset() >= startOffset) { ASSERT((int)marker.startOffset() + delta >= 0); marker.shiftOffsets(delta); docDirty = true; // Marker moved, so previously-computed rendered rectangle is now invalid marker.invalidate(); } } // repaint the affected node if (docDirty && node->renderer()) node->renderer()->repaint(); }
void DocumentMarkerController::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active) { MarkerList* list = m_markers.get(node); if (!list) return; bool docDirty = false; for (size_t i = 0; i != list->size(); ++i) { DocumentMarker& marker = list->at(i); // Markers are returned in order, so stop if we are now past the specified range. if (marker.startOffset() >= endOffset) break; // Skip marker that is wrong type or before target. if (marker.endOffset() < startOffset || marker.type() != DocumentMarker::TextMatch) continue; marker.setActiveMatch(active); docDirty = true; } // repaint the affected node if (docDirty && node->renderer()) node->renderer()->repaint(); }
void DocumentMarkerController::repaintMarkers(DocumentMarker::MarkerTypes markerTypes) { if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!m_markers.isEmpty()); // outer loop: process each markered node in the document MarkerMap::iterator end = m_markers.end(); for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { Node* node = i->key.get(); // inner loop: process each marker in the current node MarkerList* list = i->value.get(); bool nodeNeedsRepaint = false; for (size_t i = 0; i != list->size(); ++i) { DocumentMarker marker = list->at(i); // skip nodes that are not of the specified type if (markerTypes.contains(marker.type())) { nodeNeedsRepaint = true; break; } } if (!nodeNeedsRepaint) continue; // cause the node to be redrawn if (auto renderer = node->renderer()) renderer->repaint(); } }
void MarkerList::ValueTreeWrapper::readFrom (const MarkerList& markerList, UndoManager* undoManager) { state.removeAllChildren (undoManager); for (int i = 0; i < markerList.getNumMarkers(); ++i) setMarker (*markerList.getMarker(i), undoManager); }
void CanvasNavigator::updateMarkers() { MarkerList* markers = song->marker(); for (iMarker m = markers->begin(); m != markers->end(); ++m) { QPointF point(calcSize(m->second.tick()), 0.0); QGraphicsRectItem* marker = m_markers.value(m->second.id()); if(marker) marker->setPos(point); } }
// FIXME: Should be removed after all relevant patches are landed Vector<DocumentMarker> DocumentMarkerController::markersForNode(Node* node) { Vector<DocumentMarker> result; MarkerList* list = m_markers.get(node); if (!list) return result; for (size_t i = 0; i < list->size(); ++i) result.append(list->at(i)); return result; }
void DocumentMarkerController::invalidateRenderedRectsForMarkersInRect(const LayoutRect& r) { // outer loop: process each markered node in the document MarkerMap::iterator end = m_markers.end(); for (MarkerMap::iterator i = m_markers.begin(); i != end; ++i) { // inner loop: process each rect in the current node MarkerList* list = i->value.get(); for (size_t listIndex = 0; listIndex < list->size(); ++listIndex) list->at(listIndex).invalidate(r); } }
Vector<RenderedDocumentMarker*> DocumentMarkerController::markersFor(Node* node, DocumentMarker::MarkerTypes markerTypes) { Vector<RenderedDocumentMarker*> result; MarkerList* list = m_markers.get(node); if (!list) return result; for (size_t i = 0; i < list->size(); ++i) { if (markerTypes.contains(list->at(i).type())) result.append(&(list->at(i))); } return result; }
void MarkerView::prevMarker() { unsigned int curPos = song->cpos(); //prevent compiler warning: comparison of sigend/unsigned unsigned int nextPos = 0; MarkerList* marker = song->marker(); for (iMarker i = marker->begin(); i != marker->end(); ++i) { if (i->second.tick() < curPos && i->second.tick() > nextPos) nextPos = i->second.tick(); } /* if (nextPos == 0) return;*/ Pos p(nextPos, true); song->setPos(0, p, true, true, false); }
void DocumentMarkerController::addMarker(Node* node, const DocumentMarker& newMarker) { ASSERT(newMarker.endOffset() >= newMarker.startOffset()); if (newMarker.endOffset() == newMarker.startOffset()) return; m_possiblyExistingMarkerTypes.add(newMarker.type()); MarkerList* list = m_markers.get(node); if (!list) { list = new MarkerList; list->append(RenderedDocumentMarker(newMarker)); m_markers.set(node, list); } else { RenderedDocumentMarker toInsert(newMarker); size_t numMarkers = list->size(); size_t i; // Iterate over all markers whose start offset is less than or equal to the new marker's. // If one of them is of the same type as the new marker and touches it or intersects with it // (there is at most one), remove it and adjust the new marker's start offset to encompass it. for (i = 0; i < numMarkers; ++i) { DocumentMarker marker = list->at(i); if (marker.startOffset() > toInsert.startOffset()) break; if (marker.type() == toInsert.type() && marker.endOffset() >= toInsert.startOffset()) { toInsert.setStartOffset(marker.startOffset()); list->remove(i); numMarkers--; break; } } size_t j = i; // Iterate over all markers whose end offset is less than or equal to the new marker's, // removing markers of the same type as the new marker which touch it or intersect with it, // adjusting the new marker's end offset to cover them if necessary. while (j < numMarkers) { DocumentMarker marker = list->at(j); if (marker.startOffset() > toInsert.endOffset()) break; if (marker.type() == toInsert.type()) { list->remove(j); if (toInsert.endOffset() <= marker.endOffset()) { toInsert.setEndOffset(marker.endOffset()); break; } numMarkers--; } else j++; } // At this point i points to the node before which we want to insert. list->insert(i, RenderedDocumentMarker(toInsert)); } // repaint the affected node if (node->renderer()) node->renderer()->repaint(); }
void DocumentMarkerController::showMarkers() const { fprintf(stderr, "%d nodes have markers:\n", m_markers.size()); MarkerMap::const_iterator end = m_markers.end(); for (MarkerMap::const_iterator nodeIterator = m_markers.begin(); nodeIterator != end; ++nodeIterator) { Node* node = nodeIterator->first.get(); fprintf(stderr, "%p", node); MarkerList* list = nodeIterator->second; for (unsigned markerIndex = 0; markerIndex < list->size(); ++markerIndex) { const DocumentMarker& marker = list->at(markerIndex); fprintf(stderr, " %d:[%d:%d](%d)", marker.type(), marker.startOffset(), marker.endOffset(), marker.activeMatch()); } fprintf(stderr, "\n"); } }
//============================================================================== void MarkerList::ValueTreeWrapper::applyTo (MarkerList& markerList) { const int numMarkers = getNumMarkers(); StringArray updatedMarkers; for (int i = 0; i < numMarkers; ++i) { const ValueTree marker (state.getChild (i)); const String name (marker [nameProperty].toString()); markerList.setMarker (name, RelativeCoordinate (marker [posProperty].toString())); updatedMarkers.add (name); } for (int i = markerList.getNumMarkers(); --i >= 0;) if (! updatedMarkers.contains (markerList.getMarker (i)->name)) markerList.removeMarker (i); }
void MarkerView::markerChanged(int val) { //if (val != Song::MARKER_CUR) // return; // p3.3.43 switch (val) { // MARKER_CUR, MARKER_ADD, MARKER_REMOVE, MARKER_NAME, // MARKER_TICK, MARKER_LOCK case Song::MARKER_ADD: case Song::MARKER_REMOVE: updateList(); break; // Try falling through and let it try to select something. No, let updateList() do it... case Song::MARKER_CUR: { MarkerList* marker = song->marker(); for (iMarker i = marker->begin(); i != marker->end(); ++i) { if (i->second.current()) { MarkerItem* item = (MarkerItem*) table->topLevelItem(0); while (item) { if (item->marker() == &i->second) { table->setCurrentItem(item); return; } item = (MarkerItem*) table->itemBelow(item); } } } } break; default: break; } }
// copies markers from srcNode to dstNode, applying the specified shift delta to the copies. The shift is // useful if, e.g., the caller has created the dstNode from a non-prefix substring of the srcNode. void DocumentMarkerController::copyMarkers(Node* srcNode, unsigned startOffset, int length, Node* dstNode, int delta) { if (length <= 0) return; if (!possiblyHasMarkers(DocumentMarker::AllMarkers())) return; ASSERT(!m_markers.isEmpty()); MarkerList* list = m_markers.get(srcNode); if (!list) return; bool docDirty = false; unsigned endOffset = startOffset + length - 1; for (size_t i = 0; i != list->size(); ++i) { DocumentMarker marker = list->at(i); // stop if we are now past the specified range if (marker.startOffset() > endOffset) break; // skip marker that is before the specified range or is the wrong type if (marker.endOffset() < startOffset) continue; // pin the marker to the specified range and apply the shift delta docDirty = true; if (marker.startOffset() < startOffset) marker.setStartOffset(startOffset); if (marker.endOffset() > endOffset) marker.setEndOffset(endOffset); marker.shiftOffsets(delta); addMarker(dstNode, marker); } // repaint the affected node if (docDirty && dstNode->renderer()) dstNode->renderer()->repaint(); }
void DocumentMarkerController::removeMarkersFromList(MarkerMap::iterator iterator, DocumentMarker::MarkerTypes markerTypes) { bool needsRepainting = false; bool listCanBeRemoved; if (markerTypes == DocumentMarker::AllMarkers()) { needsRepainting = true; listCanBeRemoved = true; } else { MarkerList* list = iterator->value.get(); for (size_t i = 0; i != list->size(); ) { DocumentMarker marker = list->at(i); // skip nodes that are not of the specified type if (!markerTypes.contains(marker.type())) { ++i; continue; } // pitch the old marker list->remove(i); needsRepainting = true; // i now is the index of the next marker } listCanBeRemoved = list->isEmpty(); } if (needsRepainting) { if (auto renderer = iterator->key->renderer()) renderer->repaint(); } if (listCanBeRemoved) { m_markers.remove(iterator); if (m_markers.isEmpty()) m_possiblyExistingMarkerTypes = 0; } }
void Finish() { if (markers.empty()) return; FlushScreen(); markers.append().Set(NULL); for (unsigned i = 0; markers[i + 1].text != NULL; ++i) { const Marker &start = markers[i]; const Marker &end = markers[i + 1]; LogFormat("StopWatch '%s': clock=%lu cpu=%lu", start.text, (unsigned long)(end.clock - start.clock), (unsigned long)(end.cpu - start.cpu)); } const Marker &start = markers.front(); const Marker &end = markers.back(); LogFormat("StopWatch total: clock=%lu cpu=%lu", (unsigned long)(end.clock - start.clock), (unsigned long)(end.cpu - start.cpu)); markers.clear(); }
bool MarkerList::operator== (const MarkerList& other) const noexcept { if (other.markers.size() != markers.size()) return false; for (int i = markers.size(); --i >= 0;) { const Marker* const m1 = markers.getUnchecked(i); jassert (m1 != nullptr); const Marker* const m2 = other.getMarker (m1->name); if (m2 == nullptr || *m1 != *m2) return false; } return true; }
void MarkerView::updateList() { // Added p3.3.43 Manage selected item, due to clearing of table... MarkerList* marker = song->marker(); MarkerItem* selitem = (MarkerItem*) table->currentItem(); Marker* selm = selitem ? selitem->marker() : 0; // p3.3.44 Look for removed markers before added markers... if (selitem) { MarkerItem* mitem = (MarkerItem*) table->topLevelItem(0); while (mitem) { bool found = false; for (iMarker i = marker->begin(); i != marker->end(); ++i) { Marker* m = &i->second; if (m == mitem->marker()) { found = true; break; } } // Anything removed from the marker list? if (!found) { // If it is the current selected item, it no longer exists. Make the next item be selected. if (mitem == selitem) { MarkerItem* mi = (MarkerItem*) table->itemBelow(selitem); if (mi) { selitem = mi; selm = selitem->marker(); } } } mitem = (MarkerItem*) table->itemBelow(mitem); } } // Look for added markers... for (iMarker i = marker->begin(); i != marker->end(); ++i) { Marker* m = &i->second; bool found = false; MarkerItem* item = (MarkerItem*) table->topLevelItem(0); while (item) { if (item->marker() == m) { found = true; break; } item = (MarkerItem*) table->itemBelow(item); } // Anything new found in the marker list? if (!found) selm = m; } // Block signals added. Triggers itemSelectionChanged() causing crash. Tim. table->blockSignals(true); table->clear(); table->blockSignals(false); //MarkerList* marker = song->marker(); for (iMarker i = marker->begin(); i != marker->end(); ++i) { Marker* m = &i->second; // Changed p3.3.43 //QString tick; //tick.setNum(i->first); //new MarkerItem(table, m); MarkerItem* item = new MarkerItem(table, m); if (m == selm) { m->setCurrent(true); table->setCurrentItem(item); } else { m->setCurrent(false); } } }
void Mark(const char *text) { FlushScreen(); markers.append().Set(text); }
void CanvasNavigator::updateParts()/*{{{*/ { m_editing = true; m_playhead = 0; m_start = 0; m_canvasBox = 0; m_punchIn = 0; m_punchOut = 0; m_parts.clear(); m_markers.clear(); m_scene->clear(); /*foreach(PartItem* i, m_parts) m_scene->removeItem(i); while(m_parts.size()) delete m_parts.takeFirst();*/ m_heightList.clear(); m_scene->setSceneRect(QRectF()); int index = 1; //QList<QGraphicsItem*> group; MidiTrackList* tl = song->visibletracks(); ciMidiTrack ci = tl->begin(); for(; ci != tl->end(); ci++) { m_heightList.append((*ci)->height()); } ci = tl->begin(); if(ci != tl->end()) { int mh = (*ci)->height(); double partHeight = (mh * 8)/100; m_start = m_scene->addRect(0.0, 0.0, calcSize(song->len()), partHeight); m_start->setBrush(QColor(63, 63, 63)); m_start->setPen(QPen(QColor(63, 63, 63))); m_start->setZValue(-50); ci++;//Special case for master } for(; ci != tl->end(); ci++) { MidiTrack* track = *ci; if(track) { QList<int> list = m_heightList.mid(0, index); int ypos = 0; foreach(int i, list) ypos += i; ypos = (ypos * 8)/100; int ih = m_heightList.at(index); double partHeight = (ih * 8)/100; //qDebug("CanvasNavigator::updateParts: partHeight: %2f, ypos: %d", partHeight, ypos); PartList* parts = track->parts(); if(parts && !parts->empty()) { for(iPart p = parts->begin(); p != parts->end(); p++) { Part *part = p->second; int tick, len; if(part) { tick = part->tick(); len = part->lenTick(); } double w = calcSize(len); double pos = calcSize(tick); PartItem* item = new PartItem(pos, ypos, w, partHeight); item->setPart(part); m_parts.append(item); //group.append((QGraphicsItem*)item); int i = part->colorIndex(); QColor partWaveColor(config.partWaveColors[i]); QColor partColor(config.partColors[i]); //partWaveColor.setAlpha(150); partColor.setAlpha(150); item->setBrush(part->selected() ? partWaveColor : partColor); item->setPen(part->selected() ? partColor : partWaveColor); m_scene->addItem(item); } } ++index; } } QColor colTimeLine = QColor(0, 186, 255); int kpos = 0; foreach(int i, m_heightList) kpos += i; //kpos = ((kpos + 400) * 8)/100; kpos = ((kpos + 400) * 8)/100; m_playhead = new QGraphicsRectItem(0, 0, 1, kpos); m_playhead->setBrush(colTimeLine); m_playhead->setPen(Qt::NoPen); m_playhead->setZValue(124001.0f); m_playhead->setFlags(QGraphicsItem::ItemIgnoresTransformations); m_scene->addItem(m_playhead); QColor loopColor(139, 225, 69); QColor markerColor(243,191,124); MarkerList* markers = song->marker(); for (iMarker m = markers->begin(); m != markers->end(); ++m) { //double xp = calcSize(m->second.tick()); QGraphicsRectItem *marker = m_scene->addRect(0, 0, 1, kpos); marker->setData(Qt::UserRole, m->second.id()); m_markers[m->second.id()] = marker; marker->setPen(Qt::NoPen); marker->setBrush(markerColor); marker->setZValue(124002.0f); marker->setFlags(QGraphicsItem::ItemIgnoresTransformations); m_updateMarkers = true; } m_punchIn = new QGraphicsRectItem(0, 0, 1, kpos); m_punchIn->setBrush(loopColor); m_punchIn->setPen(Qt::NoPen); m_punchIn->setZValue(124003.0f); m_punchIn->setFlags(QGraphicsItem::ItemIgnoresTransformations); m_scene->addItem(m_punchIn); m_punchIn->setVisible(song->loop() || song->punchin()); m_punchOut = new QGraphicsRectItem(0, 0, 1, kpos); m_punchOut->setBrush(loopColor); m_punchOut->setPen(Qt::NoPen); m_punchOut->setZValue(124003.0f); m_punchOut->setFlags(QGraphicsItem::ItemIgnoresTransformations); m_scene->addItem(m_punchOut); m_punchOut->setVisible(song->loop() || song->punchout()); createCanvasBox(); //group.append((QGraphicsItem*)m_start); //group.append((QGraphicsItem*)m_playhead); //if(group.size()) //{ // m_partGroup = m_scene->createItemGroup(group); //} //else m_partGroup = 0; updateSpacing(); m_editing = false; }/*}}}*/
void adjustGlobalLists(Undo& operations, int startPos, int diff) { const TempoList* t = &MusEGlobal::tempomap; const AL::SigList* s = &AL::sigmap; const KeyList* k = &MusEGlobal::keymap; criTEvent it = t->rbegin(); AL::criSigEvent is = s->rbegin(); criKeyEvent ik = k->rbegin(); // key for (; ik != k->rend(); ik++) { const KeyEvent &ev = (KeyEvent)ik->second; int tick = ev.tick; int key = ev.key; if (tick < startPos ) break; if (tick > startPos && tick +diff < startPos ) { // remove operations.push_back(UndoOp(UndoOp::DeleteKey, tick, key)); } else { operations.push_back(UndoOp(UndoOp::DeleteKey,tick, key)); operations.push_back(UndoOp(UndoOp::AddKey,tick+diff, key)); } } // tempo for (; it != t->rend(); it++) { const TEvent* ev = (TEvent*)it->second; int tick = ev->tick; int tempo = ev->tempo; if (tick < startPos ) break; if (tick > startPos && tick +diff < startPos ) { // remove operations.push_back(UndoOp(UndoOp::DeleteTempo,tick, tempo)); } else { operations.push_back(UndoOp(UndoOp::DeleteTempo,tick, tempo)); operations.push_back(UndoOp(UndoOp::AddTempo,tick+diff, tempo)); } } // sig for (; is != s->rend(); is++) { const AL::SigEvent* ev = (AL::SigEvent*)is->second; int tick = ev->tick; if (tick < startPos ) break; int z = ev->sig.z; int n = ev->sig.n; if (tick > startPos && tick +diff < startPos ) { // remove operations.push_back(UndoOp(UndoOp::DeleteSig,tick, z, n)); } else { operations.push_back(UndoOp(UndoOp::DeleteSig,tick, z, n)); operations.push_back(UndoOp(UndoOp::AddSig,tick+diff, z, n)); } } MarkerList *markerlist = MusEGlobal::song->marker(); for(iMarker i = markerlist->begin(); i != markerlist->end(); ++i) { Marker* m = &i->second; int tick = m->tick(); if (tick > startPos) { if (tick + diff < startPos ) { // these ticks should be removed operations.push_back(UndoOp(UndoOp::ModifyMarker, 0, m)); } else { Marker *newMarker = new Marker(); *newMarker = *m; newMarker->setTick(tick + diff); operations.push_back(UndoOp(UndoOp::ModifyMarker, newMarker, m)); } } } }
void DocumentMarkerController::removeMarkers(Node* node, unsigned startOffset, int length, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker) { if (length <= 0) return; if (!possiblyHasMarkers(markerTypes)) return; ASSERT(!(m_markers.isEmpty())); MarkerList* list = m_markers.get(node); if (!list) return; bool docDirty = false; unsigned endOffset = startOffset + length; for (size_t i = 0; i < list->size();) { DocumentMarker marker = list->at(i); // markers are returned in order, so stop if we are now past the specified range if (marker.startOffset() >= endOffset) break; // skip marker that is wrong type or before target if (marker.endOffset() <= startOffset || !markerTypes.contains(marker.type())) { i++; continue; } // at this point we know that marker and target intersect in some way docDirty = true; // pitch the old marker list->remove(i); if (shouldRemovePartiallyOverlappingMarker) // Stop here. Don't add resulting slices back. continue; // add either of the resulting slices that are left after removing target if (startOffset > marker.startOffset()) { DocumentMarker newLeft = marker; newLeft.setEndOffset(startOffset); list->insert(i, RenderedDocumentMarker(newLeft)); // i now points to the newly-inserted node, but we want to skip that one i++; } if (marker.endOffset() > endOffset) { DocumentMarker newRight = marker; newRight.setStartOffset(endOffset); list->insert(i, RenderedDocumentMarker(newRight)); // i now points to the newly-inserted node, but we want to skip that one i++; } } if (list->isEmpty()) { m_markers.remove(node); if (m_markers.isEmpty()) m_possiblyExistingMarkerTypes = 0; } // repaint the affected node if (docDirty && node->renderer()) node->renderer()->repaint(); }
void MTScale::pdraw(QPainter& p, const QRect& r) { QColor colTimeLine = QColor(172,181,176); int x = r.x(); int w = r.width(); //printf("MTScale::pdraw x:%d w:%d\n", x, w); x -= 20; w += 40; // wg. Text //--------------------------------------------------- // draw Marker //--------------------------------------------------- int y = 12; p.setPen(colTimeLine); p.setFont(QFont("fixed-width", 9, QFont::Bold)); p.drawLine(r.x(), y + 1, r.x() + r.width(), y + 1); QRect tr(r); tr.setHeight(12); MarkerList* marker = song->marker(); for (iMarker m = marker->begin(); m != marker->end(); ++m) { int xp; if (waveMode) xp = mapx(m->second.frame()); else xp = mapx(m->second.tick()); if (xp > x + w) break; int xe = r.x() + r.width(); iMarker mm = m; ++mm; if (mm != marker->end()) { if (waveMode) xe = mapx(tempomap.tick2frame(mm->first)); else xe = mapx(mm->first); } QRect tr(xp, 0, xe - xp, 13); QRect wr = r.intersect(tr); if (!wr.isEmpty()) { if (m->second.current()) { p.fillRect(wr, QColor(89, 89, 102)); } int x2; if (mm != marker->end()) { if (waveMode) x2 = mapx(tempomap.tick2frame(mm->first)); else x2 = mapx(mm->first); } else x2 = xp + 200; //printf("MTScale::pdraw marker %s xp:%d y:%d h:%d r.x:%d r.w:%d\n", m->second.name().toLatin1(), xp, height(), y, r.x(), r.width()); // Must be reasonable about very low negative x values! With long songs > 15min // and with high horizontal magnification, 'ghost' drawings appeared, // apparently the result of truncation later (xp = -65006 caused ghosting // at bar 245 with magnification at max.), even with correct clipping region // applied to painter in View::paint(). Tim. Apr 5 2009 // Quote: "Warning: Note that QPainter does not attempt to work around // coordinate limitations in the underlying window system. Some platforms may // behave incorrectly with coordinates as small as +/-4000." if (xp >= -32) p.drawPixmap(xp, 0, *flagIconS); if (xp >= -1023) { QRect r = QRect(xp + 10, 0, x2 - xp, 12); p.setPen(colTimeLine); p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter, m->second.name()); } if (xp >= 0) { p.setPen(colTimeLine); p.drawLine(xp, y, xp, height()); } } } unsigned ctick; int bar1, bar2, beat; unsigned tick; if (waveMode) { ctick = tempomap.frame2tick(mapxDev(x)); AL::sigmap.tickValues(ctick, &bar1, &beat, &tick); AL::sigmap.tickValues(tempomap.frame2tick(mapxDev(x + w)), &bar2, &beat, &tick); } else { ctick = mapxDev(x); AL::sigmap.tickValues(ctick, &bar1, &beat, &tick); AL::sigmap.tickValues(mapxDev(x + w), &bar2, &beat, &tick); } //printf("bar %d %d-%d=%d\n", bar, ntick, stick, ntick-stick); int h = height() - 12; int stick = AL::sigmap.bar2tick(bar1, 0, 0); int ntick; for (int bar = bar1; bar <= bar2; bar++, stick = ntick) { ntick = AL::sigmap.bar2tick(bar + 1, 0, 0); int tpix, a, b = 0; if (waveMode) { a = tempomap.tick2frame(ntick); b = tempomap.tick2frame(stick); tpix = rmapx(a - b); } else { tpix = rmapx(ntick - stick); } if (tpix < 64) { // don�t show beats if measure is this small int n = 1; if (tpix < 32) n = 2; if (tpix <= 16) n = 4; if (tpix < 8) n = 8; if (tpix <= 4) n = 16; if (tpix <= 2) n = 32; if (bar % n) continue; int x = mapx(waveMode ? b : stick); QString s; s.setNum(bar + 1); p.drawLine(x, y + 1, x, y + 1 + h); QRect r = QRect(x + 2, y, 1000, h); p.setFont(QFont("fixed-width", 9, QFont::Bold)); p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, s); } else { int z, n; AL::sigmap.timesig(stick, z, n); for (int beat = 0; beat < z; beat++) { int xx = AL::sigmap.bar2tick(bar, beat, 0); if (waveMode) xx = tempomap.tick2frame(xx); int xp = mapx(xx); QString s; QRect r(xp + 2, y, 1000, h); int y1; int num; if (beat == 0) { num = bar + 1; y1 = y + 1; p.setFont(QFont("fixed-width", 9, QFont::Bold)); } else { num = beat + 1; y1 = y + 7; p.setFont(QFont("fixed-width", 7, QFont::Normal)); r.setY(y + 3); } s.setNum(num); p.drawLine(xp, y1, xp, y + 1 + h); p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, s); } } } //--------------------------------------------------- // draw location marker //--------------------------------------------------- //Christopher here is your color p.setPen(QColor(156,75,219)); if (pos[3] != MAXINT) { int xp = mapx(pos[3]); if (xp >= x && xp < x + w) p.drawLine(xp, 0, xp, height()); } p.setPen(colTimeLine); if (barLocator) { p.setPen(QColor(0, 186, 255)); int xp = mapx(pos[0]); if (xp >= x && xp < x + w) p.drawLine(xp, 0, xp, height()); p.setPen(QColor(139, 225, 69)); xp = mapx(pos[1]); if (xp >= x && xp < x + w) p.drawLine(xp, 0, xp, height()); xp = mapx(pos[2]); if (xp >= x && xp < x + w) p.drawLine(xp, 0, xp, height()); } else { for (int i = 0; i < 3; ++i) { int xp = mapx(pos[i]); if (xp >= x && xp < x + w) { QPixmap* pm = markIcon[i]; p.drawPixmap(xp - pm->width() / 2, y - 1, *pm); } } } }