Chris@70: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@70: 
Chris@70: /*
Chris@70:     Sonic Visualiser
Chris@70:     An audio file viewer and annotation editor.
Chris@70:     Centre for Digital Music, Queen Mary, University of London.
Chris@70:     This file copyright 2006 Chris Cannam.
Chris@70:     
Chris@70:     This program is free software; you can redistribute it and/or
Chris@70:     modify it under the terms of the GNU General Public License as
Chris@70:     published by the Free Software Foundation; either version 2 of the
Chris@70:     License, or (at your option) any later version.  See the file
Chris@70:     COPYING included with this distribution for more information.
Chris@70: */
Chris@70: 
Chris@70: #include "ItemEditDialog.h"
Chris@70: 
Chris@70: #include <QLineEdit>
Chris@70: #include <QDoubleSpinBox>
Chris@73: #include <QSpinBox>
Chris@70: #include <QGridLayout>
Chris@70: #include <QHBoxLayout>
Chris@70: #include <QLabel>
Chris@70: #include <QPushButton>
Chris@73: #include <QGroupBox>
Chris@282: #include <QDialogButtonBox>
Chris@70: 
Chris@73: #include <float.h> // for FLT_MIN/MAX
Chris@70: 
Chris@73: 
Chris@904: ItemEditDialog::ItemEditDialog(sv_samplerate_t sampleRate, int options,
Chris@73:                                QString valueUnits, QWidget *parent) :
Chris@70:     QDialog(parent),
Chris@70:     m_sampleRate(sampleRate),
Chris@857:     m_defaultFrame(0),
Chris@857:     m_defaultDuration(0),
Chris@857:     m_defaultValue(0),
Chris@73:     m_frameTimeSpinBox(0),
Chris@73:     m_realTimeSecsSpinBox(0),
Chris@73:     m_realTimeUSecsSpinBox(0),
Chris@73:     m_frameDurationSpinBox(0),
Chris@73:     m_realDurationSecsSpinBox(0),
Chris@73:     m_realDurationUSecsSpinBox(0),
Chris@73:     m_valueSpinBox(0),
Chris@73:     m_textField(0)
Chris@70: {
Chris@70:     QGridLayout *grid = new QGridLayout;
Chris@70:     setLayout(grid);
Chris@70: 
Chris@73:     QGroupBox *timeBox = 0;
Chris@73:     QGroupBox *valueBox = 0;
Chris@73:     QGridLayout *subgrid = 0;
Chris@70: 
Chris@73:     int row = 0, subrow = 0;
Chris@70: 
Chris@807:     int singleStep = RealTime::frame2RealTime(2, sampleRate).usec() - 1;
Chris@70: 
Chris@73:     if ((options & ShowTime) || (options & ShowDuration)) {
Chris@70: 
Chris@73:         timeBox = new QGroupBox;
Chris@73:         timeBox->setTitle(tr("Timing"));
Chris@73:         grid->addWidget(timeBox, row, 0);
Chris@70: 
Chris@73:         subgrid = new QGridLayout;
Chris@73:         timeBox->setLayout(subgrid);
Chris@70: 
Chris@70:         ++row;
Chris@70:     }
Chris@70: 
Chris@73:     if (options & ShowTime) {
Chris@73: 
Chris@73:         subgrid->addWidget(new QLabel(tr("Time:")), subrow, 0);
Chris@73: 
Chris@73:         m_frameTimeSpinBox = new QSpinBox;
Chris@73:         m_frameTimeSpinBox->setMaximum(INT_MAX);
Chris@73:         m_frameTimeSpinBox->setSuffix(tr(" frames"));
Chris@73:         subgrid->addWidget(m_frameTimeSpinBox, subrow, 1, 1, 2);
Chris@73:         connect(m_frameTimeSpinBox, SIGNAL(valueChanged(int)),
Chris@938:                 this, SLOT(frameTimeChanged(int)));
Chris@73: 
Chris@73:         ++subrow;
Chris@73: 
Chris@73:         m_realTimeSecsSpinBox = new QSpinBox;
Chris@73:         m_realTimeSecsSpinBox->setMaximum(999999);
Chris@73:         m_realTimeSecsSpinBox->setSuffix(tr(" sec"));
Chris@73:         subgrid->addWidget(m_realTimeSecsSpinBox, subrow, 1);
Chris@73:         connect(m_realTimeSecsSpinBox, SIGNAL(valueChanged(int)),
Chris@73:                 this, SLOT(realTimeSecsChanged(int)));
Chris@73: 
Chris@73:         m_realTimeUSecsSpinBox = new QSpinBox;
Chris@73:         m_realTimeUSecsSpinBox->setMaximum(999999);
Chris@73:         m_realTimeUSecsSpinBox->setSuffix(tr(" usec"));
Chris@73:         m_realTimeUSecsSpinBox->setSingleStep(singleStep);
Chris@73:         subgrid->addWidget(m_realTimeUSecsSpinBox, subrow, 2);
Chris@73:         connect(m_realTimeUSecsSpinBox, SIGNAL(valueChanged(int)),
Chris@73:                 this, SLOT(realTimeUSecsChanged(int)));
Chris@73: 
Chris@73:         ++subrow;
Chris@73:     }
Chris@73: 
Chris@70:     if (options & ShowDuration) {
Chris@70: 
Chris@73:         subgrid->addWidget(new QLabel(tr("Duration:")), subrow, 0);
Chris@70: 
Chris@73:         m_frameDurationSpinBox = new QSpinBox;
Chris@73:         m_frameDurationSpinBox->setMaximum(INT_MAX);
Chris@73:         m_frameDurationSpinBox->setSuffix(tr(" frames"));
Chris@73:         subgrid->addWidget(m_frameDurationSpinBox, subrow, 1, 1, 2);
Chris@73:         connect(m_frameDurationSpinBox, SIGNAL(valueChanged(int)),
Chris@938:                 this, SLOT(frameDurationChanged(int)));
Chris@70: 
Chris@73:         ++subrow;
Chris@70: 
Chris@73:         m_realDurationSecsSpinBox = new QSpinBox;
Chris@73:         m_realDurationSecsSpinBox->setMaximum(999999);
Chris@73:         m_realDurationSecsSpinBox->setSuffix(tr(" sec"));
Chris@73:         subgrid->addWidget(m_realDurationSecsSpinBox, subrow, 1);
Chris@73:         connect(m_realDurationSecsSpinBox, SIGNAL(valueChanged(int)),
Chris@73:                 this, SLOT(realDurationSecsChanged(int)));
Chris@70: 
Chris@73:         m_realDurationUSecsSpinBox = new QSpinBox;
Chris@73:         m_realDurationUSecsSpinBox->setMaximum(999999);
Chris@73:         m_realDurationUSecsSpinBox->setSuffix(tr(" usec"));
Chris@73:         m_realDurationUSecsSpinBox->setSingleStep(singleStep);
Chris@101:         subgrid->addWidget(m_realDurationUSecsSpinBox, subrow, 2);
Chris@73:         connect(m_realDurationUSecsSpinBox, SIGNAL(valueChanged(int)),
Chris@73:                 this, SLOT(realDurationUSecsChanged(int)));
Chris@70: 
Chris@73:         ++subrow;
Chris@73:     }
Chris@70: 
Chris@73:     if ((options & ShowValue) || (options & ShowText)) {
Chris@70: 
Chris@73:         valueBox = new QGroupBox;
Chris@73:         valueBox->setTitle(tr("Properties"));
Chris@73:         grid->addWidget(valueBox, row, 0);
Chris@73: 
Chris@73:         subgrid = new QGridLayout;
Chris@73:         valueBox->setLayout(subgrid);
Chris@70: 
Chris@70:         ++row;
Chris@70:     }
Chris@70: 
Chris@73:     subrow = 0;
Chris@73: 
Chris@70:     if (options & ShowValue) {
Chris@70:         
Chris@73:         subgrid->addWidget(new QLabel(tr("Value:")), subrow, 0);
Chris@70: 
Chris@73:         m_valueSpinBox = new QDoubleSpinBox;
Chris@73:         m_valueSpinBox->setSuffix(QString(" %1").arg(valueUnits));
Chris@73:         m_valueSpinBox->setDecimals(10);
Chris@685:         m_valueSpinBox->setMinimum(-1e10);
Chris@685:         m_valueSpinBox->setMaximum(1e10);
Chris@73:         connect(m_valueSpinBox, SIGNAL(valueChanged(double)),
Chris@70:                 this, SLOT(valueChanged(double)));
Chris@73:         subgrid->addWidget(m_valueSpinBox, subrow, 1);
Chris@70: 
Chris@73:         ++subrow;
Chris@70:     }
Chris@70: 
Chris@70:     if (options & ShowText) {
Chris@70:         
Chris@73:         subgrid->addWidget(new QLabel(tr("Text:")), subrow, 0);
Chris@70: 
Chris@73:         m_textField = new QLineEdit;
Chris@73:         connect(m_textField, SIGNAL(textChanged(QString)),
Chris@70:                 this, SLOT(textChanged(QString)));
Chris@73:         subgrid->addWidget(m_textField, subrow, 1);
Chris@70: 
Chris@73:         ++subrow;
Chris@73:     }
Chris@73: 
Chris@73:     if (options & ShowText) {
Chris@73:         m_textField->setFocus(Qt::OtherFocusReason);
Chris@73:     } else if (options & ShowValue) {
Chris@73:         m_valueSpinBox->setFocus(Qt::OtherFocusReason);
Chris@70:     }
Chris@282:     
Chris@282:     QDialogButtonBox *bb = new QDialogButtonBox(Qt::Horizontal);
Chris@282:     grid->addWidget(bb, row, 0, 1, 2);
Chris@70:     
Chris@70:     QPushButton *ok = new QPushButton(tr("OK"));
Chris@73:     m_resetButton = new QPushButton(tr("Reset"));
Chris@70:     QPushButton *cancel = new QPushButton(tr("Cancel"));
Chris@282:     bb->addButton(ok, QDialogButtonBox::AcceptRole);
Chris@282:     bb->addButton(m_resetButton, QDialogButtonBox::ResetRole);
Chris@282:     bb->addButton(cancel, QDialogButtonBox::RejectRole);
Chris@70:     connect(ok, SIGNAL(clicked()), this, SLOT(accept()));
Chris@73:     connect(m_resetButton, SIGNAL(clicked()), this, SLOT(reset()));
Chris@70:     connect(cancel, SIGNAL(clicked()), this, SLOT(reject()));
Chris@73:     m_resetButton->setEnabled(false);
Chris@70: }
Chris@70: 
Chris@70: void
Chris@904: ItemEditDialog::setFrameTime(sv_frame_t frame)
Chris@70: {
Chris@73:     if (!m_frameTimeSpinBox) return;
Chris@73: 
Chris@73:     RealTime rt(RealTime::frame2RealTime(frame, m_sampleRate));
Chris@73:     m_realTimeSecsSpinBox->setValue(rt.sec);
Chris@73:     m_realTimeUSecsSpinBox->setValue(rt.usec());
Chris@908:     m_frameTimeSpinBox->setValue(int(frame));
Chris@73:     m_defaultFrame = frame;
Chris@73:     m_resetButton->setEnabled(false);
Chris@70: }
Chris@70: 
Chris@904: sv_frame_t
Chris@70: ItemEditDialog::getFrameTime() const
Chris@70: {
Chris@73:     return m_frameTimeSpinBox->value();
Chris@70: }
Chris@70: 
Chris@70: void
Chris@70: ItemEditDialog::setRealTime(RealTime rt)
Chris@70: {
Chris@73:     setFrameTime(RealTime::realTime2Frame(rt, m_sampleRate));
Chris@70: }
Chris@70: 
Chris@70: RealTime
Chris@70: ItemEditDialog::getRealTime() const
Chris@70: {
Chris@73:     return RealTime::frame2RealTime(getFrameTime(), m_sampleRate);
Chris@70: }
Chris@70: 
Chris@70: void
Chris@904: ItemEditDialog::setFrameDuration(sv_frame_t duration)
Chris@70: {
Chris@73:     if (!m_frameDurationSpinBox) return;
Chris@73: 
Chris@73:     RealTime rt(RealTime::frame2RealTime(duration, m_sampleRate));
Chris@73:     m_realDurationSecsSpinBox->setValue(rt.sec);
Chris@73:     m_realDurationUSecsSpinBox->setValue(rt.usec());
Chris@908:     m_frameDurationSpinBox->setValue(int(duration));
Chris@73:     m_defaultDuration = duration;
Chris@73:     m_resetButton->setEnabled(false);
Chris@70: }
Chris@70: 
Chris@904: sv_frame_t
Chris@70: ItemEditDialog::getFrameDuration() const
Chris@70: {
Chris@73:     return m_frameDurationSpinBox->value();
Chris@70: }
Chris@70: 
Chris@70: void
Chris@70: ItemEditDialog::setRealDuration(RealTime rt)
Chris@70: {
Chris@73:     setFrameDuration(RealTime::realTime2Frame(rt, m_sampleRate));
Chris@70: }
Chris@70: 
Chris@70: RealTime
Chris@70: ItemEditDialog::getRealDuration() const
Chris@70: {
Chris@73:     return RealTime::frame2RealTime(getFrameDuration(), m_sampleRate);
Chris@70: }
Chris@70: 
Chris@70: void
Chris@70: ItemEditDialog::setValue(float v)
Chris@70: {
Chris@73:     if (!m_valueSpinBox) return;
Chris@73: 
Chris@73:     m_valueSpinBox->setValue(v);
Chris@73:     m_defaultValue = v;
Chris@73:     m_resetButton->setEnabled(false);
Chris@70: }
Chris@70: 
Chris@70: float
Chris@70: ItemEditDialog::getValue() const
Chris@70: {
Chris@908:     return float(m_valueSpinBox->value());
Chris@70: }
Chris@70: 
Chris@70: void
Chris@70: ItemEditDialog::setText(QString text)
Chris@70: {
Chris@73:     if (!m_textField) return;
Chris@73: 
Chris@73:     m_textField->setText(text);
Chris@73:     m_defaultText = text;
Chris@73:     m_resetButton->setEnabled(false);
Chris@70: }
Chris@70: 
Chris@70: QString
Chris@70: ItemEditDialog::getText() const
Chris@70: {
Chris@73:     return m_textField->text();
Chris@70: }
Chris@70: 
Chris@70: void
Chris@938: ItemEditDialog::frameTimeChanged(int i)
Chris@70: {
Chris@73:     m_realTimeSecsSpinBox->blockSignals(true);
Chris@73:     m_realTimeUSecsSpinBox->blockSignals(true);
Chris@73: 
Chris@73:     RealTime rt(RealTime::frame2RealTime(i, m_sampleRate));
Chris@73:     m_realTimeSecsSpinBox->setValue(rt.sec);
Chris@73:     m_realTimeUSecsSpinBox->setValue(rt.usec());
Chris@73: 
Chris@73:     m_realTimeSecsSpinBox->blockSignals(false);
Chris@73:     m_realTimeUSecsSpinBox->blockSignals(false);
Chris@73:     m_resetButton->setEnabled(true);
Chris@70: }
Chris@70: 
Chris@70: void
Chris@73: ItemEditDialog::realTimeSecsChanged(int i)
Chris@70: {
Chris@70:     RealTime rt = getRealTime();
Chris@73:     rt.sec = i;
Chris@904:     sv_frame_t frame = RealTime::realTime2Frame(rt, m_sampleRate);
Chris@908:     m_frameTimeSpinBox->setValue(int(frame));
Chris@73:     m_resetButton->setEnabled(true);
Chris@70: }
Chris@70: 
Chris@70: void
Chris@73: ItemEditDialog::realTimeUSecsChanged(int i)
Chris@70: {
Chris@70:     RealTime rt = getRealTime();
Chris@73:     rt.nsec = i * 1000;
Chris@904:     sv_frame_t frame = RealTime::realTime2Frame(rt, m_sampleRate);
Chris@908:     m_frameTimeSpinBox->setValue(int(frame));
Chris@73:     m_resetButton->setEnabled(true);
Chris@70: }
Chris@70: 
Chris@70: void
Chris@938: ItemEditDialog::frameDurationChanged(int i)
Chris@70: {
Chris@73:     m_realDurationSecsSpinBox->blockSignals(true);
Chris@73:     m_realDurationUSecsSpinBox->blockSignals(true);
Chris@73: 
Chris@73:     RealTime rt(RealTime::frame2RealTime(i, m_sampleRate));
Chris@73:     m_realDurationSecsSpinBox->setValue(rt.sec);
Chris@73:     m_realDurationUSecsSpinBox->setValue(rt.usec());
Chris@73: 
Chris@73:     m_realDurationSecsSpinBox->blockSignals(false);
Chris@73:     m_realDurationUSecsSpinBox->blockSignals(false);
Chris@73:     m_resetButton->setEnabled(true);
Chris@70: }
Chris@70: 
Chris@70: void
Chris@73: ItemEditDialog::realDurationSecsChanged(int i)
Chris@70: {
Chris@70:     RealTime rt = getRealDuration();
Chris@73:     rt.sec = i;
Chris@904:     sv_frame_t frame = RealTime::realTime2Frame(rt, m_sampleRate);
Chris@908:     m_frameDurationSpinBox->setValue(int(frame));
Chris@73:     m_resetButton->setEnabled(true);
Chris@70: }
Chris@70: 
Chris@70: void
Chris@73: ItemEditDialog::realDurationUSecsChanged(int i)
Chris@70: {
Chris@70:     RealTime rt = getRealDuration();
Chris@73:     rt.nsec = i * 1000;
Chris@904:     sv_frame_t frame = RealTime::realTime2Frame(rt, m_sampleRate);
Chris@908:     m_frameDurationSpinBox->setValue(int(frame));
Chris@73:     m_resetButton->setEnabled(true);
Chris@70: }
Chris@70: 
Chris@70: void
Chris@73: ItemEditDialog::valueChanged(double)
Chris@70: {
Chris@73:     m_resetButton->setEnabled(true);
Chris@70: }
Chris@70: 
Chris@70: void
Chris@73: ItemEditDialog::textChanged(QString)
Chris@70: {
Chris@73:     m_resetButton->setEnabled(true);
Chris@70: }
Chris@70: 
Chris@73: void
Chris@73: ItemEditDialog::reset()
Chris@73: {
Chris@73:     setFrameTime(m_defaultFrame);
Chris@73:     setFrameDuration(m_defaultDuration);
Chris@73:     setValue(m_defaultValue);
Chris@73:     setText(m_defaultText);
Chris@73:     m_resetButton->setEnabled(false);
Chris@73: }
Chris@73: