lbajardsilogic@18: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ lbajardsilogic@18: lbajardsilogic@18: /* lbajardsilogic@18: Sound Access lbajardsilogic@18: EASAIER client application. lbajardsilogic@18: Silogic 2007. Luc Barthélémy. lbajardsilogic@18: lbajardsilogic@18: This program is free software; you can redistribute it and/or lbajardsilogic@18: modify it under the terms of the GNU General Public License as lbajardsilogic@18: published by the Free Software Foundation; either version 2 of the lbajardsilogic@18: License, or (at your option) any later version. See the file lbajardsilogic@18: COPYING included with this distribution for more information. lbajardsilogic@18: */ lbajardsilogic@18: lbajardsilogic@18: #include lbajardsilogic@18: #include lbajardsilogic@18: #include lbajardsilogic@18: #include lbajardsilogic@18: #include lbajardsilogic@18: lbajardsilogic@18: #include "layer/IntervalLayer.h" lbajardsilogic@18: #include "view/View.h" lbajardsilogic@18: #include "system/System.h" lbajardsilogic@18: #include "widgets/ItemEditDialog.h" lbajardsilogic@18: lbajardsilogic@18: lbajardsilogic@18: const int gIntervalHeight = 30; lbajardsilogic@18: lbajardsilogic@18: //**************************************************************** lbajardsilogic@18: //* Function: Constructor lbajardsilogic@18: //* Description: declaration and initialisation of all private parameters lbajardsilogic@18: //**************************************************************** lbajardsilogic@18: IntervalLayer::IntervalLayer(): lbajardsilogic@18: Layer(), lbajardsilogic@18: m_model(0), lbajardsilogic@18: m_editing(false), lbajardsilogic@18: m_colour(Qt::darkRed), lbajardsilogic@18: m_editingCommand(0) lbajardsilogic@18: { lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: IntervalLayer::~IntervalLayer() lbajardsilogic@18: {} lbajardsilogic@18: lbajardsilogic@18: void IntervalLayer::setModel(IntervalModel* model) lbajardsilogic@18: { lbajardsilogic@18: if (m_model == model) return; lbajardsilogic@18: m_model = model; lbajardsilogic@18: lbajardsilogic@18: connect(m_model, SIGNAL(modelChanged()), this, SIGNAL(modelChanged())); lbajardsilogic@18: connect(m_model, SIGNAL(modelChanged(size_t, size_t)), lbajardsilogic@18: this, SIGNAL(modelChanged(size_t, size_t))); lbajardsilogic@18: lbajardsilogic@18: connect(m_model, SIGNAL(completionChanged()), lbajardsilogic@18: this, SIGNAL(modelCompletionChanged())); lbajardsilogic@18: lbajardsilogic@18: emit modelReplaced(); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: Layer::PropertyList lbajardsilogic@18: IntervalLayer::getProperties() const lbajardsilogic@18: { lbajardsilogic@18: PropertyList list; lbajardsilogic@18: list.push_back("Colour"); lbajardsilogic@18: return list; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: Layer::PropertyType lbajardsilogic@18: IntervalLayer::getPropertyType(const PropertyName &name) const lbajardsilogic@18: { lbajardsilogic@18: return ValueProperty; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: int lbajardsilogic@18: IntervalLayer::getPropertyRangeAndValue(const PropertyName &name, lbajardsilogic@18: int *min, int *max, int *deflt) const lbajardsilogic@18: { lbajardsilogic@18: //!!! factor this colour handling stuff out into a colour manager class lbajardsilogic@18: int val = 0; lbajardsilogic@18: lbajardsilogic@18: if (name == "Colour") { lbajardsilogic@18: lbajardsilogic@18: if (min) *min = 0; lbajardsilogic@18: if (max) *max = 5; lbajardsilogic@18: if (deflt) *deflt = 0; lbajardsilogic@18: lbajardsilogic@18: if (m_colour == Qt::black) val = 0; lbajardsilogic@18: else if (m_colour == Qt::darkRed) val = 1; lbajardsilogic@18: else if (m_colour == Qt::darkBlue) val = 2; lbajardsilogic@18: else if (m_colour == Qt::darkGreen) val = 3; lbajardsilogic@18: else if (m_colour == QColor(200, 50, 255)) val = 4; lbajardsilogic@18: else if (m_colour == QColor(255, 150, 50)) val = 5; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: return val; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: QString lbajardsilogic@18: IntervalLayer::getPropertyValueLabel(const PropertyName &name, lbajardsilogic@18: int value) const lbajardsilogic@18: { lbajardsilogic@18: if (name == "Colour") { lbajardsilogic@18: switch (value) { lbajardsilogic@18: default: lbajardsilogic@18: case 0: return tr("Black"); lbajardsilogic@18: case 1: return tr("Red"); lbajardsilogic@18: case 2: return tr("Blue"); lbajardsilogic@18: case 3: return tr("Green"); lbajardsilogic@18: case 4: return tr("Purple"); lbajardsilogic@18: case 5: return tr("Orange"); lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: return tr(""); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: lbajardsilogic@18: void IntervalLayer::setProperties(const QXmlAttributes &attributes) lbajardsilogic@18: { lbajardsilogic@18: QString colourSpec = attributes.value("colour"); lbajardsilogic@18: if (colourSpec != "") { lbajardsilogic@18: QColor colour(colourSpec); lbajardsilogic@18: if (colour.isValid()) { lbajardsilogic@18: setBaseColour(QColor(colourSpec)); lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::setProperty(const PropertyName &name, int value) lbajardsilogic@18: { lbajardsilogic@18: if (name == "Colour") { lbajardsilogic@18: switch (value) { lbajardsilogic@18: default: lbajardsilogic@18: case 0: setBaseColour(Qt::black); break; lbajardsilogic@18: case 1: setBaseColour(Qt::darkRed); break; lbajardsilogic@18: case 2: setBaseColour(Qt::darkBlue); break; lbajardsilogic@18: case 3: setBaseColour(Qt::darkGreen); break; lbajardsilogic@18: case 4: setBaseColour(QColor(200, 50, 255)); break; lbajardsilogic@18: case 5: setBaseColour(QColor(255, 150, 50)); break; lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::setBaseColour(QColor colour) lbajardsilogic@18: { lbajardsilogic@18: if (m_colour == colour) return; lbajardsilogic@18: m_colour = colour; lbajardsilogic@18: emit layerParametersChanged(); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: QString lbajardsilogic@18: IntervalLayer::toXmlString(QString indent, QString extraAttributes) const lbajardsilogic@18: { lbajardsilogic@18: return Layer::toXmlString(indent, extraAttributes + lbajardsilogic@18: QString(" colour=\"%1\"") lbajardsilogic@18: .arg(encodeColour(m_colour))); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: QString lbajardsilogic@18: IntervalLayer::toEasaierXmlString(QString indent, QString extraAttributes) const lbajardsilogic@18: { lbajardsilogic@18: return Layer::toEasaierXmlString(indent, extraAttributes + lbajardsilogic@18: QString(" colour=\"%1\"") lbajardsilogic@18: .arg(encodeColour(m_colour))); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: QString lbajardsilogic@18: IntervalLayer::getPropertyLabel(const PropertyName &name) const lbajardsilogic@18: { lbajardsilogic@18: if (name == "Colour") return tr("Colour"); lbajardsilogic@18: return ""; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: int lbajardsilogic@18: IntervalLayer::getYForHeight(View *v, float height) const lbajardsilogic@18: { lbajardsilogic@18: int h = v->height(); lbajardsilogic@18: return h - int(height * h); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: float lbajardsilogic@18: IntervalLayer::getHeightForY(View *v, int y) const lbajardsilogic@18: { lbajardsilogic@18: int h = v->height(); lbajardsilogic@18: return float(h - y) / h; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::paint(View *v, QPainter &paint, QRect rect) const lbajardsilogic@18: { lbajardsilogic@18: if (!m_model || !m_model->isOK()) return; lbajardsilogic@18: lbajardsilogic@18: int sampleRate = m_model->getSampleRate(); lbajardsilogic@18: if (!sampleRate) return; lbajardsilogic@18: lbajardsilogic@18: int x0 = rect.left(), x1 = rect.right(); lbajardsilogic@18: long frame0 = v->getFrameForX(x0); lbajardsilogic@18: long frame1 = v->getFrameForX(x1); lbajardsilogic@18: lbajardsilogic@18: paint.save(); lbajardsilogic@18: lbajardsilogic@18: QColor brushColour(m_colour); lbajardsilogic@18: brushColour.setAlpha(100); lbajardsilogic@18: QColor penColour = Qt::black; lbajardsilogic@18: lbajardsilogic@18: paint.setPen(m_colour); lbajardsilogic@18: lbajardsilogic@18: IntervalList& intervals = m_model->intervals(); lbajardsilogic@18: lbajardsilogic@18: int xS,xE,y; lbajardsilogic@18: bool draw, drawText, drawStart, drawEnd; lbajardsilogic@18: lbajardsilogic@18: QPoint localPos; lbajardsilogic@18: long illuminateX = -1; lbajardsilogic@18: lbajardsilogic@18: if (v->shouldIlluminateLocalFeatures(this, localPos)) { lbajardsilogic@18: // should highlight one endpoint ? lbajardsilogic@18: illuminateX = localPos.x(); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i) lbajardsilogic@18: { lbajardsilogic@18: draw = drawText = drawStart = drawEnd = false; lbajardsilogic@18: lbajardsilogic@18: TimeIntervalPtr ti = (*i); lbajardsilogic@18: lbajardsilogic@18: if (ti->start() >= frame0 && ti->start() < frame1) lbajardsilogic@18: { lbajardsilogic@18: xS = v->getXForFrame(ti->start()); lbajardsilogic@18: xE = v->getXForFrame(ti->end()); lbajardsilogic@18: if (xE <= x1) lbajardsilogic@18: drawEnd = true; lbajardsilogic@18: else lbajardsilogic@18: xE = x1; lbajardsilogic@18: draw = drawText = drawStart = true; lbajardsilogic@18: } ivand_qmul@125: else if (ti->end() > frame0 && ti->end() <= frame1) lbajardsilogic@18: { lbajardsilogic@18: xS = v->getXForFrame(ti->start()); lbajardsilogic@18: if (xS < x0) lbajardsilogic@18: xS = x0; lbajardsilogic@18: xE = v->getXForFrame(ti->end()); lbajardsilogic@18: draw = drawEnd = true; lbajardsilogic@18: } ivand_qmul@125: else if (ti->start() <= frame0 && ti->end() >= frame1) lbajardsilogic@18: { lbajardsilogic@18: xS = x0; lbajardsilogic@18: xE = x1; lbajardsilogic@18: draw = true; lbajardsilogic@18: } lbajardsilogic@18: if (draw) lbajardsilogic@18: { lbajardsilogic@18: y = getYForHeight(v, ti->value()); lbajardsilogic@18: paint.setBrush(brushColour); lbajardsilogic@18: paint.fillRect(xS, y-gIntervalHeight/2, (xE-xS+1), gIntervalHeight, brushColour); lbajardsilogic@18: } lbajardsilogic@18: if (drawStart) lbajardsilogic@18: { lbajardsilogic@18: if (abs(illuminateX - xS) < 3) lbajardsilogic@18: paint.setPen(Qt::black); lbajardsilogic@18: else lbajardsilogic@18: paint.setPen(brushColour); lbajardsilogic@18: paint.drawLine(xS, 0, xS, v->height() - 1); lbajardsilogic@18: } lbajardsilogic@18: if (drawEnd) lbajardsilogic@18: { lbajardsilogic@18: if (abs (illuminateX - xE) < 3) lbajardsilogic@18: paint.setPen(Qt::black); lbajardsilogic@18: else lbajardsilogic@18: paint.setPen(brushColour); lbajardsilogic@18: paint.drawLine(xE, 0, xE, v->height() - 1); lbajardsilogic@18: } lbajardsilogic@18: if (drawText) lbajardsilogic@18: { lbajardsilogic@18: paint.setPen(penColour); lbajardsilogic@18: paint.drawText(xS+10, y, ti->label()); lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: paint.restore(); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: lbajardsilogic@18: bool lbajardsilogic@18: IntervalLayer::getValueExtents(float &min, float &max, lbajardsilogic@18: bool &logarithmic, QString &unit) const lbajardsilogic@18: { lbajardsilogic@18: return false; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: IntervalList lbajardsilogic@18: IntervalLayer::getIntervalAt(View *v, int x, int y) // y < 0 means you don't make any test on it lbajardsilogic@18: { lbajardsilogic@18: IntervalList result; lbajardsilogic@18: IntervalList& intervals = m_model->intervals(); lbajardsilogic@18: lbajardsilogic@18: for (IntervalListIterator i = intervals.begin(); i != intervals.end(); ++i) lbajardsilogic@18: { lbajardsilogic@18: TimeIntervalPtr ti = (*i); lbajardsilogic@18: lbajardsilogic@18: int yT = getYForHeight(v, ti->value()); lbajardsilogic@18: int xS = v->getXForFrame(ti->start()); lbajardsilogic@18: int xE = v->getXForFrame(ti->end()); lbajardsilogic@18: if ((x >= xS) && (x <= xE)) lbajardsilogic@18: { lbajardsilogic@18: if ((y < 0) || (abs(y - yT) <= gIntervalHeight/2)) lbajardsilogic@18: result.push_back(ti); lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: return result; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: IntervalList lbajardsilogic@18: IntervalLayer::getInterval(long start, long end) lbajardsilogic@18: { lbajardsilogic@18: IntervalList result; lbajardsilogic@18: IntervalList& intervals = m_model->intervals(); lbajardsilogic@18: lbajardsilogic@18: for (IntervalListIterator i = intervals.begin(); i != intervals.end(); ++i) lbajardsilogic@18: { lbajardsilogic@18: TimeIntervalPtr ti = (*i); lbajardsilogic@18: lbajardsilogic@18: if ( (start <= ti->start()) && (ti->start() <= end) && lbajardsilogic@18: (start <= ti->end()) && (ti->end() <= end) ) lbajardsilogic@18: { lbajardsilogic@18: result.push_back(ti); lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: return result; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: QString lbajardsilogic@18: IntervalLayer::getFeatureDescription(View *v, QPoint& pos) const lbajardsilogic@18: { lbajardsilogic@18: if (!m_model || !m_model->getSampleRate()) return ""; lbajardsilogic@18: lbajardsilogic@18: QString description; lbajardsilogic@18: lbajardsilogic@18: int x = pos.x(); lbajardsilogic@18: int y = pos.y(); lbajardsilogic@18: lbajardsilogic@18: long frame = v->getFrameForX(x); lbajardsilogic@18: lbajardsilogic@18: IntervalList& intervals = m_model->intervals(); lbajardsilogic@18: for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i) lbajardsilogic@18: { lbajardsilogic@18: TimeIntervalPtr ti = (*i); lbajardsilogic@18: lbajardsilogic@18: if (ti->start() <= frame && ti->end() >= frame) lbajardsilogic@18: { lbajardsilogic@18: int y = getYForHeight(v, ti->value()); lbajardsilogic@18: lbajardsilogic@18: if (abs(y - pos.y()) <= gIntervalHeight/2) lbajardsilogic@18: { lbajardsilogic@18: RealTime rtStart = RealTime::frame2RealTime(ti->start(), m_model->getSampleRate()); lbajardsilogic@18: RealTime rtEnd = RealTime::frame2RealTime(ti->end(), m_model->getSampleRate()); lbajardsilogic@18: RealTime rtDuration = rtEnd - rtStart; lbajardsilogic@18: lbajardsilogic@18: description = QString(tr("Interval:\t%1\nStart:\t%2 End:\t%3\tDuration:\t%4")) lbajardsilogic@18: .arg(ti->label()) lbajardsilogic@18: .arg(rtStart.toText(true).c_str()) lbajardsilogic@18: .arg(rtEnd.toText(true).c_str()) lbajardsilogic@18: .arg(rtDuration.toText(true).c_str()); lbajardsilogic@18: break; lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: return description; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::drawStart(View *v, QMouseEvent *e) lbajardsilogic@18: { lbajardsilogic@18: if (!m_model) { lbajardsilogic@18: std::cerr << "IntervalLayer::drawStart: no model" << std::endl; lbajardsilogic@18: return; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: long frame = v->getFrameForX(e->x()); lbajardsilogic@18: lbajardsilogic@18: if (frame < 0) lbajardsilogic@18: frame = 0; lbajardsilogic@18: lbajardsilogic@18: frame = frame / m_model->getResolution() * m_model->getResolution(); lbajardsilogic@18: lbajardsilogic@18: int height = (int) (getHeightForY(v, e->y())*100+0.5); lbajardsilogic@18: float value = ((float) height)/100; lbajardsilogic@18: lbajardsilogic@18: m_editingInterval = new TimeInterval(frame, frame, "", value); lbajardsilogic@18: lbajardsilogic@18: m_model->addInterval(m_editingInterval); lbajardsilogic@18: lbajardsilogic@18: if (m_editingCommand) lbajardsilogic@18: { lbajardsilogic@18: CommandHistory::getInstance()->addCommand(m_editingCommand, false); lbajardsilogic@18: m_editingCommand = 0; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: m_editingCommand = new IntervalModel::IntervalCommand(m_model, m_editingInterval, lbajardsilogic@18: IntervalModel::IntervalCommand::Creation , lbajardsilogic@18: frame, frame, value, ""); lbajardsilogic@18: lbajardsilogic@18: m_editing = 1; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::drawDrag(View *v, QMouseEvent *e) lbajardsilogic@18: { lbajardsilogic@18: if (!m_model || !m_editing) return; lbajardsilogic@18: lbajardsilogic@18: long frame = v->getFrameForX(e->x()); lbajardsilogic@18: lbajardsilogic@18: if (frame < 0) lbajardsilogic@18: frame = 0; lbajardsilogic@18: lbajardsilogic@18: frame = frame / m_model->getResolution() * m_model->getResolution(); lbajardsilogic@18: lbajardsilogic@18: long start = m_editingInterval->start(); lbajardsilogic@18: long end = frame; lbajardsilogic@18: lbajardsilogic@18: if (start < end) lbajardsilogic@18: { lbajardsilogic@18: m_editing = 2; lbajardsilogic@18: m_editingInterval->end(frame); lbajardsilogic@18: m_editingCommand->newEnd(frame); lbajardsilogic@18: } else { lbajardsilogic@18: m_editing = 1; lbajardsilogic@18: m_editingInterval->start(frame); lbajardsilogic@18: m_editingCommand->newStart(frame); lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::drawEnd(View *v, QMouseEvent *e) lbajardsilogic@18: { lbajardsilogic@18: if (!m_model || !m_editing) lbajardsilogic@18: return; lbajardsilogic@18: lbajardsilogic@18: bool ok = false; lbajardsilogic@18: QString label = QInputDialog::getText(v, tr("Enter label"), lbajardsilogic@18: tr("Please enter a new label:"), lbajardsilogic@18: QLineEdit::Normal, "", &ok); lbajardsilogic@18: lbajardsilogic@18: if (ok) { lbajardsilogic@18: m_editingInterval->label(label); lbajardsilogic@18: m_editingCommand->newLabel(label); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: if (m_editingCommand) lbajardsilogic@18: { lbajardsilogic@18: CommandHistory::getInstance()->addCommand(m_editingCommand, false); lbajardsilogic@18: m_editingCommand = 0; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: m_editing = false; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::editStart(View *view, QMouseEvent *evt) lbajardsilogic@18: { lbajardsilogic@18: if (!m_model) lbajardsilogic@18: return; lbajardsilogic@18: lbajardsilogic@18: IntervalList intervals = getIntervalAt(view, evt->x(), evt->y()); lbajardsilogic@18: lbajardsilogic@18: for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i) lbajardsilogic@18: { lbajardsilogic@18: TimeIntervalPtr ti = (*i); lbajardsilogic@18: lbajardsilogic@18: int xS = view->getXForFrame(ti->start()); lbajardsilogic@18: int xE = view->getXForFrame(ti->end()); lbajardsilogic@18: lbajardsilogic@18: if (abs(xS - evt->x()) < 5) lbajardsilogic@18: { lbajardsilogic@18: m_editing = 1; // editing start lbajardsilogic@18: m_editingInterval = ti; lbajardsilogic@18: break; lbajardsilogic@18: } lbajardsilogic@18: else if (abs(xE - evt->x()) < 5) lbajardsilogic@18: { lbajardsilogic@18: m_editing = 2; // editing end lbajardsilogic@18: m_editingInterval = ti; lbajardsilogic@18: break; lbajardsilogic@18: } lbajardsilogic@18: else lbajardsilogic@18: { lbajardsilogic@18: m_editing = 0; lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: if (m_editing) lbajardsilogic@18: view->setCursor(Qt::SizeHorCursor); lbajardsilogic@18: lbajardsilogic@18: if (m_editingCommand) lbajardsilogic@18: { lbajardsilogic@18: CommandHistory::getInstance()->addCommand(m_editingCommand, false); lbajardsilogic@18: m_editingCommand = 0; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::editDrag(View *view, QMouseEvent *evt) lbajardsilogic@18: { lbajardsilogic@18: if (!m_model || !m_editing) lbajardsilogic@18: return; lbajardsilogic@18: lbajardsilogic@18: long frame = view->getFrameForX(evt->x()); lbajardsilogic@18: lbajardsilogic@18: if (!m_editingCommand) lbajardsilogic@18: { lbajardsilogic@18: m_editingCommand = new IntervalModel::IntervalCommand(m_model, m_editingInterval, IntervalModel::IntervalCommand::Edition, lbajardsilogic@18: m_editingInterval->start(), lbajardsilogic@18: m_editingInterval->end(), lbajardsilogic@18: m_editingInterval->value(), lbajardsilogic@18: m_editingInterval->label()); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: if (m_editing == 1) // start lbajardsilogic@18: { lbajardsilogic@18: if (frame < m_editingInterval->end()) lbajardsilogic@18: m_editingCommand->newStart(frame); lbajardsilogic@18: } lbajardsilogic@18: else if (m_editing == 2) // end lbajardsilogic@18: { lbajardsilogic@18: if (frame > m_editingInterval->start()) lbajardsilogic@18: m_editingCommand->newEnd(frame); lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::editEnd(View *view, QMouseEvent *evt) lbajardsilogic@18: { lbajardsilogic@18: if (!m_model || !m_editing) lbajardsilogic@18: return; lbajardsilogic@18: lbajardsilogic@18: view->setCursor(Qt::UpArrowCursor); lbajardsilogic@18: lbajardsilogic@18: if (m_editingCommand) lbajardsilogic@18: { lbajardsilogic@18: CommandHistory::getInstance()->addCommand(m_editingCommand, false); lbajardsilogic@18: m_editingCommand = 0; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: lbajardsilogic@18: m_editing = false; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::editOpen(View *view, QMouseEvent *evt) // on double-click lbajardsilogic@18: { lbajardsilogic@18: if (!m_model) return; lbajardsilogic@18: lbajardsilogic@18: IntervalList intervals = getIntervalAt(view, evt->x(), evt->y()); lbajardsilogic@18: if (! intervals.empty()) lbajardsilogic@18: { lbajardsilogic@18: TimeIntervalPtr ti = intervals.front(); lbajardsilogic@18: lbajardsilogic@18: bool ok = false; lbajardsilogic@18: ItemEditDialog *dialog = new ItemEditDialog lbajardsilogic@18: (m_model->getSampleRate(), lbajardsilogic@18: ItemEditDialog::ShowTime | lbajardsilogic@18: ItemEditDialog::ShowDuration | lbajardsilogic@18: ItemEditDialog::ShowText | lbajardsilogic@18: ItemEditDialog::ShowValue); lbajardsilogic@18: lbajardsilogic@18: dialog->setFrameTime(ti->start()); lbajardsilogic@18: dialog->setFrameDuration(ti->end() - ti->start()); lbajardsilogic@18: dialog->setText(ti->label()); lbajardsilogic@18: dialog->setValue((int)(ti->value()*100+0.5)); lbajardsilogic@18: lbajardsilogic@18: if (dialog->exec() == QDialog::Accepted) lbajardsilogic@18: { lbajardsilogic@18: lbajardsilogic@18: IntervalModel::IntervalCommand *command = lbajardsilogic@18: new IntervalModel::IntervalCommand(m_model, ti, IntervalModel::IntervalCommand::Edition, lbajardsilogic@18: dialog->getFrameTime(), lbajardsilogic@18: dialog->getFrameTime() + dialog->getFrameDuration(), lbajardsilogic@18: dialog->getValue()/100, lbajardsilogic@18: dialog->getText()); lbajardsilogic@18: lbajardsilogic@18: CommandHistory::getInstance()->addCommand(command); lbajardsilogic@18: lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::moveSelection(Selection s, size_t newStartFrame) lbajardsilogic@18: { lbajardsilogic@18: if (!m_model) return; lbajardsilogic@18: lbajardsilogic@18: IntervalList intervals = getInterval(s.getStartFrame(), s.getEndFrame()); lbajardsilogic@18: lbajardsilogic@18: MacroCommand * command = new MacroCommand("Drag Selection"); lbajardsilogic@18: lbajardsilogic@18: long newStart = 0; lbajardsilogic@18: long newEnd = 0; lbajardsilogic@18: lbajardsilogic@18: for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i) lbajardsilogic@18: { lbajardsilogic@18: TimeIntervalPtr ti = (*i); lbajardsilogic@18: lbajardsilogic@18: newStart = ti->start() + ((long) (newStartFrame - s.getStartFrame())); lbajardsilogic@18: newEnd = ti->end() + ((long) (newStartFrame - s.getStartFrame())); lbajardsilogic@18: lbajardsilogic@18: IntervalModel::IntervalCommand *intervalCommand = lbajardsilogic@18: new IntervalModel::IntervalCommand(m_model, ti, IntervalModel::IntervalCommand::Edition, lbajardsilogic@18: newStart, lbajardsilogic@18: newEnd, lbajardsilogic@18: ti->value(), lbajardsilogic@18: ti->label()); lbajardsilogic@18: lbajardsilogic@18: m_model->changeInterval(ti, newStart, newEnd, ti->value(), ti->label() ); lbajardsilogic@18: lbajardsilogic@18: command->addCommand(intervalCommand); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: CommandHistory::getInstance()->addCommand(command, false); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::resizeSelection(Selection s, Selection newSize) lbajardsilogic@18: { lbajardsilogic@18: if (!m_model) return; lbajardsilogic@18: lbajardsilogic@18: IntervalList intervals = getInterval(s.getStartFrame(), s.getEndFrame()); lbajardsilogic@18: lbajardsilogic@18: MacroCommand * command = new MacroCommand("Resize Selection"); lbajardsilogic@18: lbajardsilogic@18: long newStart = 0; lbajardsilogic@18: long newEnd = 0; lbajardsilogic@18: lbajardsilogic@18: double ratio = ((double) (newSize.getEndFrame() - newSize.getStartFrame())) / lbajardsilogic@18: ((double) (s.getEndFrame() - s.getStartFrame())); lbajardsilogic@18: lbajardsilogic@18: for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i) lbajardsilogic@18: { lbajardsilogic@18: TimeIntervalPtr ti = (*i); lbajardsilogic@18: lbajardsilogic@18: newStart = (long) newSize.getStartFrame() + (long) ( ((double) ti->start() - (double) s.getStartFrame()) * ratio ); lbajardsilogic@18: newEnd = (long) newSize.getStartFrame() + (long) ( ((double) ti->end() - (double) s.getStartFrame()) * ratio ); lbajardsilogic@18: lbajardsilogic@18: IntervalModel::IntervalCommand *intervalCommand = lbajardsilogic@18: new IntervalModel::IntervalCommand(m_model, ti, IntervalModel::IntervalCommand::Edition, lbajardsilogic@18: newStart, lbajardsilogic@18: newEnd, lbajardsilogic@18: ti->value(), lbajardsilogic@18: ti->label()); lbajardsilogic@18: lbajardsilogic@18: m_model->changeInterval(ti, newStart, newEnd, ti->value(), ti->label() ); lbajardsilogic@18: lbajardsilogic@18: command->addCommand(intervalCommand); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: CommandHistory::getInstance()->addCommand(command, false); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::deleteSelection(Selection s) lbajardsilogic@18: { lbajardsilogic@18: if (!m_model) return; lbajardsilogic@18: lbajardsilogic@18: IntervalList intervals = getInterval(s.getStartFrame(), s.getEndFrame()); lbajardsilogic@18: lbajardsilogic@18: MacroCommand * command = new MacroCommand("Delete Selected Intervals"); lbajardsilogic@18: lbajardsilogic@18: for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i) lbajardsilogic@18: { lbajardsilogic@18: TimeIntervalPtr ti = (*i); lbajardsilogic@18: lbajardsilogic@18: m_model->removeInterval(ti); lbajardsilogic@18: lbajardsilogic@18: IntervalModel::IntervalCommand *intervalCommand = lbajardsilogic@18: new IntervalModel::IntervalCommand(m_model, ti, IntervalModel::IntervalCommand::Deletion, lbajardsilogic@18: ti->start(), lbajardsilogic@18: ti->end(), lbajardsilogic@18: ti->value(), lbajardsilogic@18: ti->label()); lbajardsilogic@18: lbajardsilogic@18: command->addCommand(intervalCommand); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: CommandHistory::getInstance()->addCommand(command, false); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::paste(const Clipboard &from, int frameOffset) lbajardsilogic@18: { lbajardsilogic@18: if (!m_model) return; lbajardsilogic@18: lbajardsilogic@18: const Clipboard::PointList &points = from.getPoints(); lbajardsilogic@18: lbajardsilogic@18: MacroCommand * command = new MacroCommand("Paste"); lbajardsilogic@18: lbajardsilogic@18: for (Clipboard::PointList::const_iterator i = points.begin(); i != points.end(); ++i) lbajardsilogic@18: { lbajardsilogic@18: if (!i->haveFrame()) lbajardsilogic@18: continue; lbajardsilogic@18: lbajardsilogic@18: size_t frame = 0; lbajardsilogic@18: lbajardsilogic@18: if (frameOffset > 0 || -frameOffset < i->getFrame()) { lbajardsilogic@18: frame = i->getFrame() + frameOffset; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: TimeIntervalPtr ti = new TimeInterval((long) frame, (long) (frame+i->getDuration()), i->getLabel(), i->getValue()); lbajardsilogic@18: lbajardsilogic@18: m_model->addInterval(ti); lbajardsilogic@18: lbajardsilogic@18: IntervalModel::IntervalCommand *intervalCommand = lbajardsilogic@18: new IntervalModel::IntervalCommand(m_model, ti, IntervalModel::IntervalCommand::Creation, lbajardsilogic@18: ti->start(), lbajardsilogic@18: ti->end(), lbajardsilogic@18: ti->value(), lbajardsilogic@18: ti->label()); lbajardsilogic@18: lbajardsilogic@18: command->addCommand(intervalCommand); lbajardsilogic@18: lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: CommandHistory::getInstance()->addCommand(command, false); lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: void lbajardsilogic@18: IntervalLayer::copy(Selection s, Clipboard &to) lbajardsilogic@18: { lbajardsilogic@18: if (!m_model) return; lbajardsilogic@18: lbajardsilogic@18: IntervalList intervals = getInterval(s.getStartFrame(), s.getEndFrame()); lbajardsilogic@18: lbajardsilogic@18: for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i) lbajardsilogic@18: { lbajardsilogic@18: TimeIntervalPtr ti = (*i); lbajardsilogic@18: lbajardsilogic@18: Clipboard::Point point(ti->start(), ti->value(), ti->end()-ti->start(), ti->label()); lbajardsilogic@18: to.addPoint(point); lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: bool lbajardsilogic@18: IntervalLayer::snapToFeatureFrame(View *v, int &frame, lbajardsilogic@18: size_t &resolution, lbajardsilogic@18: SnapType snap) const lbajardsilogic@18: { lbajardsilogic@18: if (!m_model) lbajardsilogic@18: return Layer::snapToFeatureFrame(v, frame, resolution, snap); lbajardsilogic@18: lbajardsilogic@18: resolution = m_model->getResolution(); lbajardsilogic@18: lbajardsilogic@18: IntervalList& intervals = m_model->intervals(); lbajardsilogic@18: lbajardsilogic@18: int snapped, best = frame; lbajardsilogic@18: bool found = false; lbajardsilogic@18: lbajardsilogic@18: unsigned int dist, distMin; lbajardsilogic@18: lbajardsilogic@18: dist = distMin = m_model->getEndFrame(); lbajardsilogic@18: lbajardsilogic@18: for (IntervalListConstIterator i = intervals.begin(); i != intervals.end(); ++i) lbajardsilogic@18: { lbajardsilogic@18: TimeIntervalPtr ti = (*i); lbajardsilogic@18: switch (snap) lbajardsilogic@18: { lbajardsilogic@18: case SnapRight: lbajardsilogic@18: if (ti->start() >= frame) lbajardsilogic@18: { lbajardsilogic@18: dist = ti->start() - frame; lbajardsilogic@18: snapped = ti->start(); lbajardsilogic@18: } lbajardsilogic@18: else if (ti->end() >= frame) lbajardsilogic@18: { lbajardsilogic@18: dist = ti->end() - frame; lbajardsilogic@18: snapped = ti->end(); lbajardsilogic@18: } lbajardsilogic@18: break; lbajardsilogic@18: lbajardsilogic@18: case SnapLeft: lbajardsilogic@18: if (ti->end() <= frame) lbajardsilogic@18: { lbajardsilogic@18: dist = frame - ti->end(); lbajardsilogic@18: snapped = ti->end(); lbajardsilogic@18: } lbajardsilogic@18: else if (ti->start() <= frame) lbajardsilogic@18: { lbajardsilogic@18: dist = frame - ti->start(); lbajardsilogic@18: snapped = ti->start(); lbajardsilogic@18: } lbajardsilogic@18: break; lbajardsilogic@18: lbajardsilogic@18: case SnapNearest: lbajardsilogic@18: { lbajardsilogic@18: int distS = abs(ti->start() - frame); lbajardsilogic@18: int distE = abs(ti->end() - frame); lbajardsilogic@18: if (distS < distE) lbajardsilogic@18: { lbajardsilogic@18: dist = distS; lbajardsilogic@18: snapped = ti->start(); lbajardsilogic@18: } else lbajardsilogic@18: { lbajardsilogic@18: dist = distE; lbajardsilogic@18: snapped = ti->end(); lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: break; lbajardsilogic@18: lbajardsilogic@18: case SnapNeighbouring: lbajardsilogic@18: { lbajardsilogic@18: int distS = abs(ti->start() - frame); lbajardsilogic@18: int distE = abs(ti->end() - frame); lbajardsilogic@18: if (distS < 5) lbajardsilogic@18: { lbajardsilogic@18: dist = distS; lbajardsilogic@18: snapped = ti->start(); lbajardsilogic@18: } else if (distE < 5) lbajardsilogic@18: { lbajardsilogic@18: dist = distE; lbajardsilogic@18: snapped = ti->end(); lbajardsilogic@18: } lbajardsilogic@18: } lbajardsilogic@18: break; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: if (dist < distMin) lbajardsilogic@18: { lbajardsilogic@18: found = true; lbajardsilogic@18: distMin = dist; lbajardsilogic@18: best = snapped; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: lbajardsilogic@18: if (found) lbajardsilogic@18: { lbajardsilogic@18: frame = best; lbajardsilogic@18: } lbajardsilogic@18: lbajardsilogic@18: return found; lbajardsilogic@18: }