#include "TimingLine.hh" #include "TimingUtils.hh" using namespace Vivy; #define CONNECT_SEP(sep) \ connect(sep, &TimingSeparator::positionChanged, this, &TimingLine::timingSeparatorHasChanged); \ connect(sep, &TimingSeparator::enterPress, this, &TimingLine::sepEnterPress); \ connect(sep, &TimingSeparator::exitPress, this, &TimingLine::sepExitPress); TimingLine::TimingLine(Ass::Line& _line, int index, QGraphicsItem *parent) : QGraphicsObject(parent) , line(_line) , lineIndex(index) { setPos(TimingUtils::posFromMs(int(line.getStart()) * 10), TimingUtils::axisHeight()); int currentTime = 0; int endSyl = 0; int i; setZValue(Z_LINE_BACKGROUND); TimingSeparator *timingSeparatorStart = new TimingSeparator(currentTime, 0, TimingSeparator::SeparatorStyle::Start, this); seps.append(timingSeparatorStart); CONNECT_SEP(timingSeparatorStart); QVector<Ass::Syl> syls = line.getContent(); for (i = 0; i < syls.size(); ++i) { endSyl = currentTime + 10 * int(syls.at(i).getDuration()); TimingSyl *timingSyl = new TimingSyl(syls.at(i), currentTime, this); timingSyls.append(timingSyl); if (i != 0) { TimingSeparator *timingSeparator = new TimingSeparator(currentTime, i, TimingSeparator::SeparatorStyle::Middle, this); seps.append(timingSeparator); CONNECT_SEP(timingSeparator); } currentTime = endSyl; } TimingSeparator *timingSeparatorEnd = new TimingSeparator(currentTime, i, TimingSeparator::SeparatorStyle::End, this); seps.append(timingSeparatorEnd); CONNECT_SEP(timingSeparatorEnd); } #undef CONNECT_SEP QRectF TimingLine::boundingRect() const { return QRectF(tempOffset, 0, TimingUtils::posFromMs(int(10 * (line.getEnd() - line.getStart()))), TimingUtils::audioHeight()); } void TimingLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->fillRect(QRectF(tempOffset, 0, TimingUtils::posFromMs(int(10 * (line.getEnd() - line.getStart()))), TimingUtils::audioHeight()), QColor(0, 255, 255, 50)); } void TimingLine::timingSeparatorHasChanged(int sylIndex, qreal x) { } void TimingLine::sepEnterPress(int sepIndex) { } void TimingLine::sepExitPress(int sepIndex) { if (tempOffset) { prepareGeometryChange(); if (sepIndex == 0) { moveBy(tempOffset, 0); timingSyls[sepIndex]->setPos(0, 0); seps[sepIndex]->silentlySetPos(0, 0); for (int i = 1; i < timingSyls.size(); i++) { timingSyls[i]->moveBy(-tempOffset, 0); } for (int i = 1; i < seps.size(); i++) { seps[i]->silentlyMoveBy(-tempOffset, 0); } line.setStart(quint64(TimingUtils::msFromPos(mapToScene(0, 0).x()) / 10)); } } tempOffset = 0; } qreal TimingLine::requestMove(int sepIndex, qreal x) { QRectF sceneRect = mapRectFromScene(scene()->sceneRect()); QVector<Ass::Syl> syls = line.getContent(); qreal given = x; qreal mini, maxi; if (sepIndex <= 0) { prepareGeometryChange(); mini = sceneRect.left(); maxi = sepIndex < syls.size() - 1 ? timingSyls[sepIndex + 1]->pos().x() : TimingUtils::posFromMs(int(line.getDuration()) * 10); given = qBound(mini, given, maxi); tempOffset = given; quint64 dur1 = quint64(TimingUtils::msFromPos(int(seps[1]->pos().x() - given)) / 10); syls[0].setDuration(dur1); timingSyls[0]->setLen(dur1); timingSyls[0]->setPos(given, 0); line.setStart(quint64(TimingUtils::msFromPos(mapToScene(seps[0]->pos().x(), 0).x()) / 10)); } else if (sepIndex >= syls.size()) { prepareGeometryChange(); mini = timingSyls[sepIndex - 1]->pos().x(); maxi = sceneRect.right(); given = qBound(mini, given, maxi); quint64 dur2 = quint64(TimingUtils::msFromPos(int(given - timingSyls[sepIndex - 1]->pos().x())) / 10); syls[sepIndex - 1].setDuration(dur2); timingSyls[sepIndex - 1]->setLen(dur2); line.setEnd(line.getStart() + quint64(TimingUtils::msFromPos(int(given)) / 10)); } else { mini = timingSyls[sepIndex - 1]->pos().x(); maxi = sepIndex < syls.size() - 1 ? timingSyls[sepIndex + 1]->pos().x() : TimingUtils::posFromMs(int(line.getDuration() * 10)); given = qBound(mini, given, maxi); quint64 sumDur = syls[sepIndex].getDuration() + syls[sepIndex - 1].getDuration(); quint64 dur1 = quint64( TimingUtils::msFromPos(int(given) - int(timingSyls[sepIndex - 1]->pos().x())) / 10); dur1 = qMin(dur1, sumDur); quint64 dur2 = sumDur - dur1; syls[sepIndex - 1].setDuration(dur1); syls[sepIndex].setDuration(dur2); timingSyls[sepIndex - 1]->setLen(dur1); timingSyls[sepIndex]->setPos(given, 0); timingSyls[sepIndex]->setLen(dur2); } line.setContent(syls); if (given) { emit lineChanged(lineIndex, std::make_shared<Ass::Line>(line)); } return given; }