You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
527 lines
17 KiB
527 lines
17 KiB
/*
|
|
Rosegarden
|
|
A MIDI and audio sequencer and musical notation editor.
|
|
|
|
This program is Copyright 2000-2008
|
|
Guillaume Laurent <glaurent@telegraph-road.org>,
|
|
Chris Cannam <cannam@all-day-breakfast.com>,
|
|
Richard Bown <richard.bown@ferventsoftware.com>
|
|
|
|
The moral rights of Guillaume Laurent, Chris Cannam, and Richard
|
|
Bown to claim authorship of this work have been asserted.
|
|
|
|
Other copyrights also apply to some parts of this work. Please
|
|
see the AUTHORS file and individual file headers for details.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version. See the file
|
|
COPYING included with this distribution for more information.
|
|
*/
|
|
|
|
|
|
#include "EventEditDialog.h"
|
|
|
|
#include <tdelocale.h>
|
|
#include "misc/Strings.h"
|
|
#include "base/Event.h"
|
|
#include "base/MidiTypes.h"
|
|
#include "base/NotationTypes.h"
|
|
#include "base/PropertyName.h"
|
|
#include "base/RealTime.h"
|
|
#include "gui/editors/notation/NotePixmapFactory.h"
|
|
#include <kdialogbase.h>
|
|
#include <tdemessagebox.h>
|
|
#include <tqcheckbox.h>
|
|
#include <tqfont.h>
|
|
#include <tqgrid.h>
|
|
#include <tqgroupbox.h>
|
|
#include <tqhbox.h>
|
|
#include <tqlabel.h>
|
|
#include <tqlineedit.h>
|
|
#include <tqobject.h>
|
|
#include <tqobjectlist.h>
|
|
#include <tqpushbutton.h>
|
|
#include <tqscrollview.h>
|
|
#include <tqsize.h>
|
|
#include <tqspinbox.h>
|
|
#include <tqstring.h>
|
|
#include <tqtooltip.h>
|
|
#include <tqvbox.h>
|
|
#include <tqwidget.h>
|
|
|
|
|
|
namespace Rosegarden
|
|
{
|
|
|
|
EventEditDialog::EventEditDialog(TQWidget *parent,
|
|
const Event &event,
|
|
bool editable) :
|
|
KDialogBase(parent, 0, true, i18n(editable ? "Advanced Event Edit" : "Advanced Event Viewer"),
|
|
(editable ? (Ok | Cancel) : Ok)),
|
|
m_durationDisplay(0),
|
|
m_durationDisplayAux(0),
|
|
m_persistentGrid(0),
|
|
m_nonPersistentGrid(0),
|
|
m_nonPersistentView(0),
|
|
m_originalEvent(event),
|
|
m_event(event),
|
|
m_type(event.getType()),
|
|
m_absoluteTime(event.getAbsoluteTime()),
|
|
m_duration(event.getDuration()),
|
|
m_subOrdering(event.getSubOrdering()),
|
|
m_modified(false)
|
|
{
|
|
TQVBox *vbox = makeVBoxMainWidget();
|
|
|
|
TQGroupBox *intrinsicBox = new TQGroupBox
|
|
(1, Qt::Horizontal, i18n("Intrinsics"), vbox);
|
|
|
|
TQGrid *intrinsicGrid = new TQGrid(4, Qt::Horizontal, intrinsicBox);
|
|
|
|
new TQLabel(i18n("Event type: "), intrinsicGrid);
|
|
new TQLabel("", intrinsicGrid);
|
|
new TQLabel("", intrinsicGrid);
|
|
TQLineEdit *lineEdit = new TQLineEdit(intrinsicGrid);
|
|
lineEdit->setText(strtoqstr(event.getType()));
|
|
|
|
new TQLabel(i18n("Absolute time: "), intrinsicGrid);
|
|
new TQLabel("", intrinsicGrid);
|
|
new TQLabel("", intrinsicGrid);
|
|
TQSpinBox *absoluteTime = new TQSpinBox
|
|
(INT_MIN, INT_MAX, Note(Note::Shortest).getDuration(), intrinsicGrid);
|
|
absoluteTime->setValue(event.getAbsoluteTime());
|
|
TQObject::connect(absoluteTime, TQT_SIGNAL(valueChanged(int)),
|
|
this, TQT_SLOT(slotAbsoluteTimeChanged(int)));
|
|
slotAbsoluteTimeChanged(event.getAbsoluteTime());
|
|
|
|
new TQLabel(i18n("Duration: "), intrinsicGrid);
|
|
m_durationDisplay = new TQLabel("(note)", intrinsicGrid);
|
|
m_durationDisplay->setMinimumWidth(20);
|
|
m_durationDisplayAux = new TQLabel("(note)", intrinsicGrid);
|
|
m_durationDisplayAux->setMinimumWidth(20);
|
|
|
|
TQSpinBox *duration = new TQSpinBox
|
|
(0, INT_MAX, Note(Note::Shortest).getDuration(), intrinsicGrid);
|
|
duration->setValue(event.getDuration());
|
|
TQObject::connect(duration, TQT_SIGNAL(valueChanged(int)),
|
|
this, TQT_SLOT(slotDurationChanged(int)));
|
|
slotDurationChanged(event.getDuration());
|
|
|
|
new TQLabel(i18n("Sub-ordering: "), intrinsicGrid);
|
|
new TQLabel("", intrinsicGrid);
|
|
new TQLabel("", intrinsicGrid);
|
|
|
|
TQSpinBox *subOrdering = new TQSpinBox( -100, 100, 1, intrinsicGrid);
|
|
subOrdering->setValue(event.getSubOrdering());
|
|
TQObject::connect(subOrdering, TQT_SIGNAL(valueChanged(int)),
|
|
this, TQT_SLOT(slotSubOrderingChanged(int)));
|
|
slotSubOrderingChanged(event.getSubOrdering());
|
|
|
|
TQGroupBox *persistentBox = new TQGroupBox
|
|
(1, Qt::Horizontal, i18n("Persistent properties"), vbox);
|
|
m_persistentGrid = new TQGrid(4, Qt::Horizontal, persistentBox);
|
|
|
|
TQLabel *label = new TQLabel(i18n("Name"), m_persistentGrid);
|
|
TQFont font(label->font());
|
|
font.setItalic(true);
|
|
label->setFont(font);
|
|
|
|
label = new TQLabel(i18n("Type"), m_persistentGrid);
|
|
label->setFont(font);
|
|
label = new TQLabel(i18n("Value"), m_persistentGrid);
|
|
label->setFont(font);
|
|
label = new TQLabel("", m_persistentGrid);
|
|
label->setFont(font);
|
|
|
|
Event::PropertyNames p = event.getPersistentPropertyNames();
|
|
|
|
for (Event::PropertyNames::iterator i = p.begin();
|
|
i != p.end(); ++i) {
|
|
addPersistentProperty(*i);
|
|
}
|
|
|
|
p = event.getNonPersistentPropertyNames();
|
|
|
|
if (p.begin() == p.end()) {
|
|
m_nonPersistentView = 0;
|
|
m_nonPersistentGrid = 0;
|
|
} else {
|
|
|
|
TQGroupBox *nonPersistentBox = new TQGroupBox
|
|
(1, Qt::Horizontal, i18n("Non-persistent properties"), vbox);
|
|
new TQLabel(i18n("These are cached values, lost if the event is modified."),
|
|
nonPersistentBox);
|
|
|
|
m_nonPersistentView = new TQScrollView(nonPersistentBox);
|
|
//m_nonPersistentView->setHScrollBarMode(TQScrollView::AlwaysOff);
|
|
m_nonPersistentView->setResizePolicy(TQScrollView::AutoOneFit);
|
|
|
|
m_nonPersistentGrid = new TQGrid
|
|
(4, Qt::Horizontal, m_nonPersistentView->viewport());
|
|
m_nonPersistentView->addChild(m_nonPersistentGrid);
|
|
|
|
m_nonPersistentGrid->setSpacing(4);
|
|
m_nonPersistentGrid->setMargin(5);
|
|
|
|
label = new TQLabel(i18n("Name "), m_nonPersistentGrid);
|
|
label->setFont(font);
|
|
label = new TQLabel(i18n("Type "), m_nonPersistentGrid);
|
|
label->setFont(font);
|
|
label = new TQLabel(i18n("Value "), m_nonPersistentGrid);
|
|
label->setFont(font);
|
|
label = new TQLabel("", m_nonPersistentGrid);
|
|
label->setFont(font);
|
|
|
|
for (Event::PropertyNames::iterator i = p.begin();
|
|
i != p.end(); ++i) {
|
|
|
|
new TQLabel(strtoqstr(*i), m_nonPersistentGrid, strtoqstr(*i).ascii());
|
|
new TQLabel(strtoqstr(event.getPropertyTypeAsString(*i)), m_nonPersistentGrid, strtoqstr(*i).ascii());
|
|
new TQLabel(strtoqstr(event.getAsString(*i)), m_nonPersistentGrid, strtoqstr(*i).ascii());
|
|
TQPushButton *button = new TQPushButton("P", m_nonPersistentGrid, strtoqstr(*i).ascii());
|
|
button->setFixedSize(TQSize(24, 24));
|
|
TQToolTip::add
|
|
(button, i18n("Make persistent"));
|
|
TQObject::connect(button, TQT_SIGNAL(clicked()),
|
|
this, TQT_SLOT(slotPropertyMadePersistent()));
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
EventEditDialog::addPersistentProperty(const PropertyName &name)
|
|
{
|
|
TQLabel *label = new TQLabel(strtoqstr(name), m_persistentGrid, strtoqstr(name).ascii());
|
|
label->show();
|
|
label = new TQLabel(strtoqstr(m_originalEvent.getPropertyTypeAsString(name)),
|
|
m_persistentGrid, strtoqstr(name).ascii());
|
|
label->show();
|
|
|
|
PropertyType type(m_originalEvent.getPropertyType(name));
|
|
switch (type) {
|
|
|
|
case Int: {
|
|
int min = INT_MIN, max = INT_MAX;
|
|
// DMM - constrain program changes to a useful range of values
|
|
// Might other types have a similar need for such limits?
|
|
if (m_originalEvent.isa(ProgramChange::EventType)) {
|
|
min = 0;
|
|
max = 127;
|
|
}
|
|
TQSpinBox *spinBox = new TQSpinBox
|
|
(min, max, 1, m_persistentGrid, strtoqstr(name).ascii());
|
|
spinBox->setValue(m_originalEvent.get<Int>(name));
|
|
TQObject::connect(spinBox, TQT_SIGNAL(valueChanged(int)),
|
|
this, TQT_SLOT(slotIntPropertyChanged(int)));
|
|
spinBox->show();
|
|
break;
|
|
}
|
|
case UInt: {
|
|
int min = 0;
|
|
int max = UINT_MAX;
|
|
if (m_originalEvent.isa(ProgramChange::EventType)) {
|
|
min = 0;
|
|
max = 65535;
|
|
}
|
|
TQSpinBox *spinBox = new TQSpinBox
|
|
(min, max, 1, m_persistentGrid, strtoqstr(name).ascii());
|
|
spinBox->setValue(m_originalEvent.get<UInt>(name));
|
|
TQObject::connect(spinBox, TQT_SIGNAL(valueChanged(int)),
|
|
this, TQT_SLOT(slotIntPropertyChanged(int)));
|
|
spinBox->show();
|
|
break;
|
|
}
|
|
case RealTimeT: {
|
|
RealTime realTime = m_originalEvent.get<RealTimeT>(name);
|
|
|
|
TQHBox* hbox = new TQHBox(m_persistentGrid);
|
|
|
|
// seconds
|
|
//
|
|
TQSpinBox *spinBox = new TQSpinBox
|
|
(INT_MIN, INT_MAX, 1,
|
|
hbox, TQString(strtoqstr(name) + "%sec").ascii());
|
|
spinBox->setValue(realTime.sec);
|
|
|
|
TQObject::connect(spinBox, TQT_SIGNAL(valueChanged(int)),
|
|
this, TQT_SLOT(slotRealTimePropertyChanged(int)));
|
|
|
|
// nseconds
|
|
//
|
|
spinBox = new TQSpinBox
|
|
(INT_MIN, INT_MAX, 1,
|
|
hbox, TQString(strtoqstr(name) + "%nsec").ascii());
|
|
spinBox->setValue(realTime.nsec);
|
|
|
|
TQObject::connect(spinBox, TQT_SIGNAL(valueChanged(int)),
|
|
this, TQT_SLOT(slotRealTimePropertyChanged(int)));
|
|
spinBox->show();
|
|
break;
|
|
}
|
|
|
|
case Bool: {
|
|
TQCheckBox *checkBox = new TQCheckBox
|
|
("", m_persistentGrid, strtoqstr(name).ascii());
|
|
checkBox->setChecked(m_originalEvent.get<Bool>(name));
|
|
TQObject::connect(checkBox, TQT_SIGNAL(activated()),
|
|
this, TQT_SLOT(slotBoolPropertyChanged()));
|
|
checkBox->show();
|
|
break;
|
|
}
|
|
|
|
case String: {
|
|
TQLineEdit *lineEdit = new TQLineEdit
|
|
(strtoqstr(m_originalEvent.get<String>(name)),
|
|
m_persistentGrid,
|
|
strtoqstr(name).ascii());
|
|
TQObject::connect(lineEdit, TQT_SIGNAL(textChanged(const TQString &)),
|
|
this, TQT_SLOT(slotStringPropertyChanged(const TQString &)));
|
|
lineEdit->show();
|
|
break;
|
|
}
|
|
}
|
|
|
|
TQPushButton *button = new TQPushButton("X", m_persistentGrid,
|
|
strtoqstr(name).ascii());
|
|
button->setFixedSize(TQSize(24, 24));
|
|
TQToolTip::add
|
|
(button, i18n("Delete this property"));
|
|
TQObject::connect(button, TQT_SIGNAL(clicked()),
|
|
this, TQT_SLOT(slotPropertyDeleted()));
|
|
button->show();
|
|
}
|
|
|
|
Event
|
|
EventEditDialog::getEvent() const
|
|
{
|
|
return Event(m_event, m_absoluteTime, m_duration, m_subOrdering);
|
|
}
|
|
|
|
void
|
|
EventEditDialog::slotEventTypeChanged(const TQString &type)
|
|
{
|
|
std::string t(qstrtostr(type));
|
|
if (t != m_type) {
|
|
m_modified = true;
|
|
m_type = t;
|
|
}
|
|
}
|
|
|
|
void
|
|
EventEditDialog::slotAbsoluteTimeChanged(int value)
|
|
{
|
|
if (value == m_absoluteTime)
|
|
return ;
|
|
m_modified = true;
|
|
m_absoluteTime = value;
|
|
}
|
|
|
|
void
|
|
EventEditDialog::slotDurationChanged(int value)
|
|
{
|
|
timeT error = 0;
|
|
m_durationDisplay->setPixmap
|
|
(NotePixmapFactory::toTQPixmap(m_notePixmapFactory.makeNoteMenuPixmap(timeT(value), error)));
|
|
|
|
if (error >= value / 2) {
|
|
m_durationDisplayAux->setText("++ ");
|
|
} else if (error > 0) {
|
|
m_durationDisplayAux->setText("+ ");
|
|
} else if (error < 0) {
|
|
m_durationDisplayAux->setText("- ");
|
|
} else {
|
|
m_durationDisplayAux->setText(" ");
|
|
}
|
|
|
|
if (timeT(value) == m_duration)
|
|
return ;
|
|
|
|
m_modified = true;
|
|
m_duration = value;
|
|
}
|
|
|
|
void
|
|
EventEditDialog::slotSubOrderingChanged(int value)
|
|
{
|
|
if (value == m_subOrdering)
|
|
return ;
|
|
m_modified = true;
|
|
m_subOrdering = value;
|
|
}
|
|
|
|
void
|
|
EventEditDialog::slotIntPropertyChanged(int value)
|
|
{
|
|
const TQObject *s = sender();
|
|
const TQSpinBox *spinBox = dynamic_cast<const TQSpinBox *>(s);
|
|
if (!spinBox)
|
|
return ;
|
|
|
|
m_modified = true;
|
|
TQString propertyName = spinBox->name();
|
|
m_event.set<Int>(qstrtostr(propertyName), value);
|
|
}
|
|
|
|
void
|
|
EventEditDialog::slotRealTimePropertyChanged(int value)
|
|
{
|
|
const TQObject *s = sender();
|
|
const TQSpinBox *spinBox = dynamic_cast<const TQSpinBox *>(s);
|
|
if (!spinBox)
|
|
return ;
|
|
|
|
m_modified = true;
|
|
TQString propertyFullName = spinBox->name();
|
|
|
|
TQString propertyName = propertyFullName.section('%', 0, 0),
|
|
nsecOrSec = propertyFullName.section('%', 1, 1);
|
|
|
|
RealTime realTime = m_event.get<RealTimeT>(qstrtostr(propertyName));
|
|
|
|
if (nsecOrSec == "sec")
|
|
realTime.sec = value;
|
|
else
|
|
realTime.nsec = value;
|
|
|
|
m_event.set<Int>(qstrtostr(propertyName), value);
|
|
}
|
|
|
|
void
|
|
EventEditDialog::slotBoolPropertyChanged()
|
|
{
|
|
const TQObject *s = sender();
|
|
const TQCheckBox *checkBox = dynamic_cast<const TQCheckBox *>(s);
|
|
if (!checkBox)
|
|
return ;
|
|
|
|
m_modified = true;
|
|
TQString propertyName = checkBox->name();
|
|
bool checked = checkBox->isChecked();
|
|
|
|
m_event.set<Bool>(qstrtostr(propertyName), checked);
|
|
}
|
|
|
|
void
|
|
EventEditDialog::slotStringPropertyChanged(const TQString &value)
|
|
{
|
|
const TQObject *s = sender();
|
|
const TQLineEdit *lineEdit = dynamic_cast<const TQLineEdit *>(s);
|
|
if (!lineEdit)
|
|
return ;
|
|
|
|
m_modified = true;
|
|
TQString propertyName = lineEdit->name();
|
|
m_event.set<String>(qstrtostr(propertyName), qstrtostr(value));
|
|
}
|
|
|
|
void
|
|
EventEditDialog::slotPropertyDeleted()
|
|
{
|
|
const TQObject *s = sender();
|
|
const TQPushButton *pushButton = dynamic_cast<const TQPushButton *>(s);
|
|
if (!pushButton)
|
|
return ;
|
|
|
|
TQString propertyName = pushButton->name();
|
|
|
|
if (KMessageBox::warningContinueCancel
|
|
(this,
|
|
i18n("Are you sure you want to delete the \"%1\" property?\n\n"
|
|
"Removing necessary properties may cause unexpected behavior.").
|
|
arg(propertyName),
|
|
i18n("Edit Event"),
|
|
i18n("&Delete")) != KMessageBox::Continue)
|
|
return ;
|
|
|
|
m_modified = true;
|
|
TQObjectList *list = m_persistentGrid->queryList(0, propertyName.ascii(), false);
|
|
TQObjectListIt i(*list);
|
|
TQObject *obj;
|
|
while ((obj = i.current()) != 0) {
|
|
++i;
|
|
delete obj;
|
|
}
|
|
delete list;
|
|
|
|
m_event.unset(qstrtostr(propertyName));
|
|
}
|
|
|
|
void
|
|
EventEditDialog::slotPropertyMadePersistent()
|
|
{
|
|
const TQObject *s = sender();
|
|
const TQPushButton *pushButton = dynamic_cast<const TQPushButton *>(s);
|
|
if (!pushButton)
|
|
return ;
|
|
|
|
TQString propertyName = pushButton->name();
|
|
|
|
if (KMessageBox::warningContinueCancel
|
|
(this,
|
|
i18n("Are you sure you want to make the \"%1\" property persistent?\n\n"
|
|
"This could cause problems if it overrides a different "
|
|
"computed value later on.").
|
|
arg(propertyName),
|
|
i18n("Edit Event"),
|
|
i18n("Make &Persistent")) != KMessageBox::Continue)
|
|
return ;
|
|
|
|
TQObjectList *list = m_nonPersistentGrid->queryList(0, propertyName.ascii(), false);
|
|
TQObjectListIt i(*list);
|
|
TQObject *obj;
|
|
while ((obj = i.current()) != 0) {
|
|
++i;
|
|
delete obj;
|
|
}
|
|
delete list;
|
|
|
|
m_modified = true;
|
|
addPersistentProperty(qstrtostr(propertyName));
|
|
|
|
PropertyType type =
|
|
m_originalEvent.getPropertyType(qstrtostr(propertyName));
|
|
|
|
switch (type) {
|
|
|
|
case Int:
|
|
m_event.set<Int>
|
|
(qstrtostr(propertyName),
|
|
m_originalEvent.get<Int>
|
|
(qstrtostr(propertyName)));
|
|
break;
|
|
|
|
case UInt:
|
|
m_event.set<UInt>
|
|
(qstrtostr(propertyName),
|
|
m_originalEvent.get<UInt>
|
|
(qstrtostr(propertyName)));
|
|
break;
|
|
|
|
case RealTimeT:
|
|
m_event.set<RealTimeT>
|
|
(qstrtostr(propertyName),
|
|
m_originalEvent.get<RealTimeT>
|
|
(qstrtostr(propertyName)));
|
|
break;
|
|
|
|
case Bool:
|
|
m_event.set<Bool>
|
|
(qstrtostr(propertyName),
|
|
m_originalEvent.get<Bool>
|
|
(qstrtostr(propertyName)));
|
|
break;
|
|
|
|
case String:
|
|
m_event.set<String>
|
|
(qstrtostr(propertyName),
|
|
m_originalEvent.get<String>
|
|
(qstrtostr(propertyName)));
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
#include "EventEditDialog.moc"
|