Mercurial > hg > svgui
diff widgets/Pane.cpp @ 0:2a4f26e85b4c
initial import
author | Chris Cannam |
---|---|
date | Tue, 10 Jan 2006 16:33:16 +0000 |
parents | |
children | 37b110168acf |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/widgets/Pane.cpp Tue Jan 10 16:33:16 2006 +0000 @@ -0,0 +1,397 @@ +/* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ + +/* + A waveform viewer and audio annotation editor. + Chris Cannam, Queen Mary University of London, 2005 + + This is experimental software. Not for distribution. +*/ + +#include "widgets/Pane.h" +#include "base/Layer.h" +#include "base/Model.h" +#include "base/ZoomConstraint.h" +#include "base/RealTime.h" +#include "base/Profiler.h" + +#include <QPaintEvent> +#include <QPainter> +#include <iostream> +#include <cmath> + +using std::cerr; +using std::endl; + +Pane::Pane(QWidget *w) : + View(w, true), + m_identifyFeatures(false), + m_clickedInRange(false), + m_shiftPressed(false), + m_centreLineVisible(true) +{ + setObjectName("Pane"); + setMouseTracking(true); +} + +bool +Pane::shouldIlluminateLocalFeatures(const Layer *layer, QPoint &pos) +{ + for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) { + --vi; + if (layer != *vi) return false; + pos = m_identifyPoint; + return m_identifyFeatures; + } + + return false; +} + +void +Pane::setCentreLineVisible(bool visible) +{ + m_centreLineVisible = visible; + update(); +} + +void +Pane::paintEvent(QPaintEvent *e) +{ + QPainter paint; + + QRect r(rect()); + + if (e) { + r = e->rect(); + } +/* + paint.begin(this); + paint.setClipRect(r); + + if (hasLightBackground()) { + paint.setPen(Qt::white); + paint.setBrush(Qt::white); + } else { + paint.setPen(Qt::black); + paint.setBrush(Qt::black); + } + paint.drawRect(r); + + paint.end(); +*/ + View::paintEvent(e); + + paint.begin(this); + + if (e) { + paint.setClipRect(r); + } + + for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) { + --vi; + + int sw = (*vi)->getVerticalScaleWidth(paint); + + if (sw > 0 && r.left() < sw) { + +// Profiler profiler("Pane::paintEvent - painting vertical scale", true); + +// std::cerr << "Pane::paintEvent: calling paint.save() in vertical scale block" << std::endl; + paint.save(); + + paint.setPen(Qt::black); + paint.setBrush(Qt::white); + paint.drawRect(0, 0, sw, height()); + + paint.setBrush(Qt::NoBrush); + (*vi)->paintVerticalScale(paint, QRect(0, 0, sw, height())); + + paint.restore(); + } + + if (m_identifyFeatures) { + QRect descRect = (*vi)->getFeatureDescriptionRect(paint, + m_identifyPoint); + if (descRect.width() > 0 && descRect.height() > 0 && + r.left() + r.width() >= width() - descRect.width() && + r.top() < descRect.height()) { + +// Profiler profiler("Pane::paintEvent - painting local feature description", true); + +// std::cerr << "Pane::paintEvent: calling paint.save() in feature description block" << std::endl; + paint.save(); + + paint.setPen(Qt::black); + paint.setBrush(Qt::white); + + QRect rect(width() - descRect.width() - 1, 0, + descRect.width(), descRect.height()); + + paint.drawRect(rect); + + paint.setBrush(Qt::NoBrush); + (*vi)->paintLocalFeatureDescription(paint, rect, m_identifyPoint); + + paint.restore(); + } + } + + break; + } + + if (m_centreLineVisible) { + + if (hasLightBackground()) { + paint.setPen(QColor(50, 50, 50)); + } else { + paint.setPen(QColor(200, 200, 200)); + } + paint.setBrush(Qt::NoBrush); + paint.drawLine(width() / 2, 0, width() / 2, height() - 1); + +// QFont font(paint.font()); +// font.setBold(true); +// paint.setFont(font); + + int sampleRate = getModelsSampleRate(); + int y = height() - paint.fontMetrics().height() + + paint.fontMetrics().ascent() - 6; + + LayerList::iterator vi = m_layers.end(); + + if (vi != m_layers.begin()) { + + switch ((*--vi)->getPreferredFrameCountPosition()) { + + case Layer::PositionTop: + y = paint.fontMetrics().ascent() + 6; + break; + + case Layer::PositionMiddle: + y = (height() - paint.fontMetrics().height()) / 2 + + paint.fontMetrics().ascent(); + break; + + case Layer::PositionBottom: + // y already set correctly + break; + } + } + + if (sampleRate) { + + QString text(QString::fromStdString + (RealTime::frame2RealTime + (m_centreFrame, sampleRate).toText(true))); + + int tw = paint.fontMetrics().width(text); + int x = width()/2 - 4 - tw; + + if (hasLightBackground()) { + paint.setPen(palette().background().color()); + for (int dx = -1; dx <= 1; ++dx) { + for (int dy = -1; dy <= 1; ++dy) { + if ((dx && dy) || !(dx || dy)) continue; + paint.drawText(x + dx, y + dy, text); + } + } + paint.setPen(QColor(50, 50, 50)); + } else { + paint.setPen(QColor(200, 200, 200)); + } + + paint.drawText(x, y, text); + } + + QString text = QString("%1").arg(m_centreFrame); + + int tw = paint.fontMetrics().width(text); + int x = width()/2 + 4; + + if (hasLightBackground()) { + paint.setPen(palette().background().color()); + for (int dx = -1; dx <= 1; ++dx) { + for (int dy = -1; dy <= 1; ++dy) { + if ((dx && dy) || !(dx || dy)) continue; + paint.drawText(x + dx, y + dy, text); + } + } + paint.setPen(QColor(50, 50, 50)); + } else { + paint.setPen(QColor(200, 200, 200)); + } + paint.drawText(x, y, text); + } + + if (m_clickedInRange && m_shiftPressed) { + paint.setPen(Qt::blue); + paint.drawRect(m_clickPos.x(), m_clickPos.y(), + m_mousePos.x() - m_clickPos.x(), + m_mousePos.y() - m_clickPos.y()); + } + + paint.end(); +} + +void +Pane::mousePressEvent(QMouseEvent *e) +{ + m_clickPos = e->pos(); + m_clickedInRange = true; + m_shiftPressed = (e->modifiers() & Qt::ShiftModifier); + m_dragCentreFrame = m_centreFrame; + + emit paneInteractedWith(); +} + +void +Pane::mouseReleaseEvent(QMouseEvent *e) +{ + if (m_clickedInRange) { + mouseMoveEvent(e); + } + if (m_shiftPressed) { + + int x0 = std::min(m_clickPos.x(), m_mousePos.x()); + int x1 = std::max(m_clickPos.x(), m_mousePos.x()); + int w = x1 - x0; + + long newStartFrame = getStartFrame() + m_zoomLevel * x0; + + if (newStartFrame <= -long(width() * m_zoomLevel)) { + newStartFrame = -long(width() * m_zoomLevel) + 1; + } + + if (newStartFrame >= long(getModelsEndFrame())) { + newStartFrame = getModelsEndFrame() - 1; + } + + float ratio = float(w) / float(width()); +// std::cerr << "ratio: " << ratio << std::endl; + size_t newZoomLevel = (size_t)nearbyint(m_zoomLevel * ratio); + if (newZoomLevel < 1) newZoomLevel = 1; + +// std::cerr << "start: " << m_startFrame << ", level " << m_zoomLevel << std::endl; + setZoomLevel(getZoomConstraintBlockSize(newZoomLevel)); + setStartFrame(newStartFrame); + + //cerr << "mouseReleaseEvent: start frame now " << m_startFrame << endl; +// update(); + } + m_clickedInRange = false; + + emit paneInteractedWith(); +} + +void +Pane::mouseMoveEvent(QMouseEvent *e) +{ + if (!m_clickedInRange) { + +// std::cerr << "Pane: calling identifyLocalFeatures" << std::endl; + +//!!! identifyLocalFeatures(true, e->x(), e->y()); + + bool previouslyIdentifying = m_identifyFeatures; + QPoint prevPoint = m_identifyPoint; + + m_identifyFeatures = true; + m_identifyPoint = e->pos(); + + if (m_identifyFeatures != previouslyIdentifying || + m_identifyPoint != prevPoint) { + update(); + } + + } else if (m_shiftPressed) { + + m_mousePos = e->pos(); + update(); + + } else { + + long xoff = int(e->x()) - int(m_clickPos.x()); + long frameOff = xoff * m_zoomLevel; + + size_t newCentreFrame = m_dragCentreFrame; + + if (frameOff < 0) { + newCentreFrame -= frameOff; + } else if (newCentreFrame >= size_t(frameOff)) { + newCentreFrame -= frameOff; + } else { + newCentreFrame = 0; + } + + if (newCentreFrame >= getModelsEndFrame()) { + newCentreFrame = getModelsEndFrame(); + if (newCentreFrame > 0) --newCentreFrame; + } + + if (std::max(m_centreFrame, newCentreFrame) - + std::min(m_centreFrame, newCentreFrame) > size_t(m_zoomLevel)) { + setCentreFrame(newCentreFrame); + } + } +} + +void +Pane::mouseDoubleClickEvent(QMouseEvent *e) +{ + std::cerr << "mouseDoubleClickEvent" << std::endl; +} + +void +Pane::leaveEvent(QEvent *) +{ + bool previouslyIdentifying = m_identifyFeatures; + m_identifyFeatures = false; + if (previouslyIdentifying) update(); +} + +void +Pane::wheelEvent(QWheelEvent *e) +{ + //std::cerr << "wheelEvent, delta " << e->delta() << std::endl; + + int newZoomLevel = m_zoomLevel; + + int count = e->delta(); + + if (count > 0) { + if (count >= 120) count /= 120; + else count = 1; + } + + if (count < 0) { + if (count <= -120) count /= 120; + else count = -1; + } + + while (count > 0) { + if (newZoomLevel <= 2) { + newZoomLevel = 1; + break; + } + newZoomLevel = getZoomConstraintBlockSize(newZoomLevel - 1, + ZoomConstraint::RoundDown); + --count; + } + + while (count < 0) { + newZoomLevel = getZoomConstraintBlockSize(newZoomLevel + 1, + ZoomConstraint::RoundUp); + ++count; + } + + if (newZoomLevel != m_zoomLevel) { + setZoomLevel(newZoomLevel); + } + + emit paneInteractedWith(); +} + + +#ifdef INCLUDE_MOCFILES +#include "Pane.moc.cpp" +#endif +