summaryrefslogtreecommitdiff
path: root/attic/muse2-oom/muse2/awl/posedit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'attic/muse2-oom/muse2/awl/posedit.cpp')
-rw-r--r--attic/muse2-oom/muse2/awl/posedit.cpp697
1 files changed, 697 insertions, 0 deletions
diff --git a/attic/muse2-oom/muse2/awl/posedit.cpp b/attic/muse2-oom/muse2/awl/posedit.cpp
new file mode 100644
index 00000000..3d4abaab
--- /dev/null
+++ b/attic/muse2-oom/muse2/awl/posedit.cpp
@@ -0,0 +1,697 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "al/al.h"
+#include "awl.h"
+#include "posedit.h"
+#include "al/sig.h"
+//#include "sig.h"
+//#include "sync.h" // Tim.
+
+#include <QApplication>
+#include <QKeyEvent>
+#include <QLineEdit>
+#include <QStyle>
+
+extern int mtcType;
+
+namespace Awl {
+
+ ///using AL::mtcType;
+ using AL::sigmap;
+
+//---------------------------------------------------------
+// PosEdit
+//---------------------------------------------------------
+
+PosEdit::PosEdit(QWidget* parent)
+ : QAbstractSpinBox(parent)
+ {
+ validator = new QIntValidator(this);
+
+ initialized = false;
+ setReadOnly(false);
+ setSmpte(false);
+
+ //connect(this, SIGNAL(editingFinished()), SLOT(finishEdit()));
+ //connect(this, SIGNAL(returnPressed()), SLOT(enterPressed()));
+ }
+
+// What was this for? Tim.
+/*
+void* PosEdit::operator new(size_t n)
+ {
+ void* p = new char[n];
+ memset(p, 0, n);
+ return p;
+ }
+*/
+
+PosEdit::~PosEdit()
+ {
+ }
+
+QSize PosEdit::sizeHint() const
+ {
+ QFontMetrics fm(font());
+ int fw = style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth);
+ int h = fm.height() + fw * 2;
+ int w = fw * 4 + 10; // HACK: 10 = spinbox up/down arrows
+ if (_smpte)
+ w += 2 + fm.width('9') * 9 + fm.width(':') * 3 + fw * 4;
+ else
+ w += 2 + fm.width('9') * 9 + fm.width('.') * 2 + fw * 4;
+ return QSize(w, h).expandedTo(QApplication::globalStrut());
+ }
+
+//---------------------------------------------------------
+// event
+// filter Tab and Backtab key events
+//---------------------------------------------------------
+
+bool PosEdit::event(QEvent* event)
+{
+ if (event->type() == QEvent::KeyPress)
+ {
+ QKeyEvent* ke = static_cast<QKeyEvent*>(event);
+ if (ke->key() == Qt::Key_Return)
+ {
+ //printf("key press event Return\n"); // REMOVE Tim.
+ //enterPressed();
+ finishEdit();
+ emit returnPressed();
+ emit editingFinished();
+ return true;
+ }
+
+ if (ke->key() == Qt::Key_Escape)
+ {
+ //printf("key press event Escape\n"); // REMOVE Tim.
+ if(lineEdit())
+ lineEdit()->undo();
+ // "By default, isAccepted() is set to true, but don't rely on this as subclasses may
+ // choose to clear it in their constructor."
+ // Just to be sure. Otherwise escape will close a midi editor for example, which is annoying.
+ ke->setAccepted(true);
+ return true;
+ }
+
+ int segment = curSegment();
+ if (ke->key() == Qt::Key_Backtab)
+ {
+ if (_smpte) {
+ if (segment == 3) {
+ lineEdit()->setSelection(7, 2);
+ return true;
+ }
+ else if (segment == 2) {
+ lineEdit()->setSelection(4, 2);
+ return true;
+ }
+ else if (segment == 1) {
+ lineEdit()->setSelection(0, 3);
+ return true;
+ }
+ }
+ else {
+ if (segment == 2) {
+ lineEdit()->setSelection(5, 2);
+ return true;
+ }
+ if (segment == 1) {
+ lineEdit()->setSelection(0, 4);
+ return true;
+ }
+ }
+ }
+ if (ke->key() == Qt::Key_Tab)
+ {
+ if (_smpte) {
+ if (segment == 0) {
+ lineEdit()->setSelection(4, 2);
+ return true;
+ }
+ else if (segment == 1) {
+ lineEdit()->setSelection(7, 2);
+ return true;
+ }
+ else if (segment == 2) {
+ lineEdit()->setSelection(10, 2);
+ return true;
+ }
+ }
+ else {
+ if (segment == 0) {
+ lineEdit()->setSelection(5, 2);
+ return true;
+ }
+ if (segment == 1) {
+ lineEdit()->setSelection(8, 3);
+ return true;
+ }
+ }
+ }
+ }
+ else if (event->type() == QEvent::FocusIn)
+ {
+ QFocusEvent* fe = static_cast<QFocusEvent*>(event);
+ QAbstractSpinBox::focusInEvent(fe);
+ int segment = curSegment();
+ switch(segment) {
+ case 0: lineEdit()->setSelection(0,4); break;
+ case 1: lineEdit()->setSelection(5,2); break;
+ case 2: lineEdit()->setSelection(8,3); break;
+ }
+ return true;
+ }
+ else if (event->type() == QEvent::FocusOut)
+ {
+ QFocusEvent* fe = static_cast<QFocusEvent*>(event);
+ QAbstractSpinBox::focusOutEvent(fe);
+ finishEdit();
+ emit lostFocus();
+ emit editingFinished();
+ return true;
+ }
+
+ return QAbstractSpinBox::event(event);
+}
+
+//---------------------------------------------------------
+// setSmpte
+//---------------------------------------------------------
+
+void PosEdit::setSmpte(bool f)
+ {
+ _smpte = f;
+ if (_smpte)
+ //lineEdit()->setInputMask("999:99:99:99");
+ lineEdit()->setInputMask("999:99:99:99;0");
+ else
+ //lineEdit()->setInputMask("9999.99.999");
+ lineEdit()->setInputMask("9999.99.999;0");
+ updateValue();
+ }
+
+//---------------------------------------------------------
+// setValue
+//---------------------------------------------------------
+
+void PosEdit::setValue(const Pos& time)
+ {
+ if(_pos == time)
+ return;
+ _pos = time;
+ updateValue();
+ }
+
+void PosEdit::setValue(const QString& s)
+ {
+ Pos time(s);
+ setValue(time);
+ }
+
+void PosEdit::setValue(int t)
+ {
+ Pos time(t);
+ setValue(time);
+ }
+
+//---------------------------------------------------------
+// updateValue
+//---------------------------------------------------------
+
+void PosEdit::updateValue()
+ {
+ char buffer[64];
+ if (_smpte) {
+ int minute, sec, frame, subframe;
+ _pos.msf(&minute, &sec, &frame, &subframe);
+ sprintf(buffer, "%03d:%02d:%02d:%02d", minute, sec, frame, subframe);
+ }
+ else {
+ int bar, beat;
+ int tick;
+ _pos.mbt(&bar, &beat, &tick);
+ sprintf(buffer, "%04d.%02d.%03d", bar+1, beat+1, tick);
+ }
+ lineEdit()->setText(buffer);
+ }
+
+//---------------------------------------------------------
+// stepEnables
+//---------------------------------------------------------
+
+QAbstractSpinBox::StepEnabled PosEdit::stepEnabled() const
+ {
+ int segment = curSegment();
+ QAbstractSpinBox::StepEnabled en = QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled;
+
+ if (_smpte) {
+ int minute, sec, frame, subframe;
+ _pos.msf(&minute, &sec, &frame, &subframe);
+ switch(segment) {
+ case 0:
+ if (minute == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ break;
+ case 1:
+ if (sec == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ else if (sec == 59)
+ en &= ~QAbstractSpinBox::StepUpEnabled;
+ break;
+ case 2:
+ if (frame == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ else
+ {
+ int nf = 23; // 24 frames sec
+ switch(mtcType) {
+ //case 0: // 24 frames sec
+ // nf = 23;
+ // break;
+ case 1:
+ nf = 24; // 25 frames sec
+ break;
+ case 2: // 30 drop frame
+ case 3: // 30 non drop frame
+ nf = 29;
+ break;
+ default:
+ break;
+ }
+ //if (frame == 23)
+ if (frame >= nf)
+ en &= ~QAbstractSpinBox::StepUpEnabled;
+ }
+ break;
+ case 3:
+ if (subframe == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ else if (subframe == 99)
+ en &= ~QAbstractSpinBox::StepUpEnabled;
+ break;
+ }
+ }
+ else {
+ int bar, beat;
+ unsigned tick;
+ AL::sigmap.tickValues(_pos.tick(), &bar, &beat, &tick);
+ //sigmap.tickValues(_pos.tick(), &bar, &beat, &tick);
+ unsigned tb = AL::sigmap.ticksBeat(_pos.tick());
+ //unsigned tb = sigmap.ticksBeat(_pos.tick());
+ unsigned tm = AL::sigmap.ticksMeasure(_pos.tick());
+ //unsigned tm = sigmap.ticksMeasure(_pos.tick());
+ int bm = tm / tb;
+
+ switch (segment) {
+ case 0:
+ if (bar == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ break;
+ case 1:
+ if (beat == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ else {
+ if (beat >= (bm-1))
+ en &= ~QAbstractSpinBox::StepUpEnabled;
+ }
+ break;
+ case 2:
+ if (tick == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ else {
+ if (tick >= (tb-1))
+ en &= ~QAbstractSpinBox::StepUpEnabled;
+ }
+ break;
+ }
+ }
+ return en;
+ }
+
+//---------------------------------------------------------
+// fixup
+//---------------------------------------------------------
+
+void PosEdit::fixup(QString& input) const
+ {
+ printf("fixup <%s>\n", input.toLatin1().constData()); // REMOVE Tim.
+ }
+
+//---------------------------------------------------------
+// validate
+//---------------------------------------------------------
+
+QValidator::State PosEdit::validate(QString& s,int& /*i*/) const
+{
+ //printf("validate string:%s int:%d\n", s.toLatin1().data(), i); // REMOVE Tim.
+ //printf("validate string:%s\n", s.toLatin1().data()); // REMOVE Tim.
+
+ QStringList sl = s.split(_smpte ? ':' : '.');
+ QValidator::State state;
+ QValidator::State rv = QValidator::Acceptable;
+ // "By default, the pos parameter is not used by this [QIntValidator] validator."
+ int dpos = 0;
+
+ if (_smpte)
+ {
+ if(sl.size() != 4)
+ {
+ printf("validate smpte string:%s sections:%d != 4\n", s.toLatin1().data(), sl.size());
+ return QValidator::Invalid;
+ }
+
+ validator->setRange(0, 999);
+ state = validator->validate(sl[0], dpos);
+ if(state == QValidator::Invalid)
+ return state;
+ if(state == QValidator::Intermediate)
+ rv = state;
+
+ validator->setRange(0, 59);
+ state = validator->validate(sl[1], dpos);
+ if(state == QValidator::Invalid)
+ return state;
+ if(state == QValidator::Intermediate)
+ rv = state;
+
+ int nf = 23; // 24 frames sec
+ switch(mtcType) {
+ //case 0: // 24 frames sec
+ // nf = 23;
+ // break;
+ case 1:
+ nf = 24; // 25 frames sec
+ break;
+ case 2: // 30 drop frame
+ case 3: // 30 non drop frame
+ nf = 29;
+ break;
+ default:
+ break;
+ }
+ validator->setRange(0, nf);
+ state = validator->validate(sl[2], dpos);
+ if(state == QValidator::Invalid)
+ return state;
+ if(state == QValidator::Intermediate)
+ rv = state;
+
+ validator->setRange(0, 99);
+ state = validator->validate(sl[3], dpos);
+ if(state == QValidator::Invalid)
+ return state;
+ if(state == QValidator::Intermediate)
+ rv = state;
+ }
+ else
+ {
+ if(sl.size() != 3)
+ {
+ printf("validate bbt string:%s sections:%d != 3\n", s.toLatin1().data(), sl.size());
+ return QValidator::Invalid;
+ }
+
+ int tb = AL::sigmap.ticksBeat(_pos.tick());
+ unsigned tm = AL::sigmap.ticksMeasure(_pos.tick());
+ int bm = tm / tb;
+
+ validator->setRange(1, 9999);
+ //printf("validate substring 0:%s\n", sl[0].toLatin1().data()); // REMOVE Tim.
+ // Special hack because validator says 0000 is intermediate.
+ if(sl[0] == "0000")
+ return QValidator::Invalid;
+ state = validator->validate(sl[0], dpos);
+ if(state == QValidator::Invalid)
+ return state;
+ if(state == QValidator::Intermediate)
+ rv = state;
+
+ validator->setRange(1, bm);
+ //printf("validate substring 1:%s\n", sl[1].toLatin1().data()); // REMOVE Tim.
+ // Special hack because validator says 00 is intermediate.
+ if(sl[1] == "00")
+ return QValidator::Invalid;
+ state = validator->validate(sl[1], dpos);
+ if(state == QValidator::Invalid)
+ return state;
+ if(state == QValidator::Intermediate)
+ rv = state;
+
+ validator->setRange(0, tb-1);
+ //printf("validate substring 2:%s\n", sl[2].toLatin1().data()); // REMOVE Tim.
+ state = validator->validate(sl[2], dpos);
+ if(state == QValidator::Invalid)
+ return state;
+ if(state == QValidator::Intermediate)
+ rv = state;
+ }
+ return rv;
+}
+
+//---------------------------------------------------------
+// curSegment
+//---------------------------------------------------------
+
+int PosEdit::curSegment() const
+ {
+ QLineEdit* le = lineEdit();
+ int pos = le->cursorPosition();
+ int segment = -1;
+
+ if (_smpte) {
+ if (pos >= 0 && pos <= 3)
+ segment = 0;
+ else if (pos >= 4 && pos <= 6)
+ segment = 1;
+ else if (pos >= 7 && pos <= 9)
+ segment = 2;
+ else if (pos >= 10)
+ segment = 3;
+ }
+ else {
+ if (pos >= 0 && pos <= 4)
+ segment = 0;
+ else if (pos >= 5 && pos <= 7)
+ segment = 1;
+ else if (pos >= 8)
+ segment = 2;
+ else
+ printf("curSegment = -1, pos %d\n", pos);
+ }
+ return segment;
+ }
+
+//---------------------------------------------------------
+// stepBy
+//---------------------------------------------------------
+
+void PosEdit::stepBy(int steps)
+ {
+ int segment = curSegment();
+ int selPos;
+ int selLen;
+
+ bool changed = false;
+
+ if (_smpte) {
+ int minute, sec, frame, subframe;
+ _pos.msf(&minute, &sec, &frame, &subframe);
+ switch(segment) {
+ case 0:
+ minute += steps;
+ if (minute < 0)
+ minute = 0;
+ selPos = 0;
+ selLen = 3;
+ break;
+ case 1:
+ sec += steps;
+ if (sec < 0)
+ sec = 0;
+ if (sec > 59)
+ sec = 59;
+ selPos = 4;
+ selLen = 2;
+ break;
+ case 2:
+ {
+ int nf = 23; // 24 frames sec
+ switch(mtcType) {
+ //case 0: // 24 frames sec
+ // nf = 23;
+ // break;
+ case 1:
+ nf = 24; // 25 frames sec
+ break;
+ case 2: // 30 drop frame
+ case 3: // 30 non drop frame
+ nf = 29;
+ break;
+ default:
+ break;
+ }
+ frame += steps;
+ if (frame < 0)
+ frame = 0;
+ //if (frame > 24) //TD frame type?
+ // frame = 24;
+ if (frame > nf)
+ frame = nf;
+ selPos = 7;
+ selLen = 2;
+ }
+ break;
+ case 3:
+ subframe += steps;
+ if (subframe < 0)
+ subframe = 0;
+ if (subframe > 99)
+ subframe = 99;
+ selPos = 10;
+ selLen = 2;
+ break;
+ default:
+ return;
+ }
+ Pos newPos(minute, sec, frame, subframe);
+ if (!(newPos == _pos)) {
+ changed = true;
+ _pos = newPos;
+ }
+ }
+ else {
+ int bar, beat, tick;
+ _pos.mbt(&bar, &beat, &tick);
+
+ int tb = AL::sigmap.ticksBeat(_pos.tick());
+ //int tb = sigmap.ticksBeat(_pos.tick());
+ unsigned tm = AL::sigmap.ticksMeasure(_pos.tick());
+ //unsigned tm = sigmap.ticksMeasure(_pos.tick());
+ int bm = tm / tb;
+
+ switch(segment) {
+ case 0:
+ bar += steps;
+ if (bar < 0)
+ bar = 0;
+ selPos = 0;
+ selLen = 4;
+ break;
+ case 1:
+ beat += steps;
+ if (beat < 0)
+ beat = 0;
+ else if (beat >= bm)
+ beat = bm - 1;
+ selPos = 5;
+ selLen = 2;
+ break;
+ case 2:
+ tick += steps;
+ if (tick < 0)
+ tick = 0;
+ else if (tick >= tb)
+ tick = tb -1;
+ selPos = 8;
+ selLen = 3;
+ break;
+ default:
+ return;
+ }
+ Pos newPos(bar, beat, tick);
+ if (!(newPos == _pos)) {
+ changed = true;
+ _pos = newPos;
+ }
+ }
+ if (changed) {
+ updateValue();
+ emit valueChanged(_pos);
+ }
+ lineEdit()->setSelection(selPos, selLen);
+ }
+
+//---------------------------------------------------------
+// paintEvent
+//---------------------------------------------------------
+
+void PosEdit::paintEvent(QPaintEvent* event)
+{
+ if (!initialized)
+ updateValue();
+ initialized = true;
+ QAbstractSpinBox::paintEvent(event);
+}
+
+//---------------------------------------------------------
+// finishEdit
+//---------------------------------------------------------
+
+void PosEdit::finishEdit()
+{
+ // If our validator did its job correctly, the entire line edit text should be valid now...
+
+ bool changed = false;
+ QStringList sl = text().split(_smpte ? ':' : '.');
+ if (_smpte)
+ {
+ if(sl.size() != 4)
+ {
+ printf("finishEdit smpte string:%s sections:%d != 4\n", text().toLatin1().data(), sl.size());
+ return;
+ }
+
+ Pos newPos(sl[0].toInt(), sl[1].toInt(), sl[2].toInt(), sl[3].toInt());
+ if (!(newPos == _pos))
+ {
+ changed = true;
+ _pos = newPos;
+ }
+ }
+ else
+ {
+ if(sl.size() != 3)
+ {
+ printf("finishEdit bbt string:%s sections:%d != 3\n", text().toLatin1().data(), sl.size());
+ return;
+ }
+
+ Pos newPos(sl[0].toInt() - 1, sl[1].toInt() - 1, sl[2].toInt());
+ if (!(newPos == _pos))
+ {
+ changed = true;
+ _pos = newPos;
+ }
+ }
+
+ if (changed)
+ {
+ //updateValue();
+ emit valueChanged(_pos);
+ }
+}
+
+
+} // namespace Awl
+
+