/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Rosegarden A MIDI and audio sequencer and musical notation editor. This program is Copyright 2000-2008 Guillaume Laurent , Chris Cannam , Richard Bown 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 #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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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(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(name)); TQObject::connect(spinBox, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotIntPropertyChanged(int))); spinBox->show(); break; } case RealTimeT: { RealTime realTime = m_originalEvent.get(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(name)); TQObject::connect(checkBox, TQT_SIGNAL(activated()), this, TQT_SLOT(slotBoolPropertyChanged())); checkBox->show(); break; } case String: { TQLineEdit *lineEdit = new TQLineEdit (strtoqstr(m_originalEvent.get(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 = TQT_TQOBJECT_CONST(const_cast(sender())); const TQSpinBox *spinBox = dynamic_cast(s); if (!spinBox) return ; m_modified = true; TQString propertyName = spinBox->name(); m_event.set(qstrtostr(propertyName), value); } void EventEditDialog::slotRealTimePropertyChanged(int value) { const TQObject *s = TQT_TQOBJECT_CONST(const_cast(sender())); const TQSpinBox *spinBox = dynamic_cast(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(qstrtostr(propertyName)); if (nsecOrSec == "sec") realTime.sec = value; else realTime.nsec = value; m_event.set(qstrtostr(propertyName), value); } void EventEditDialog::slotBoolPropertyChanged() { const TQObject *s = TQT_TQOBJECT_CONST(const_cast(sender())); const TQCheckBox *checkBox = dynamic_cast(s); if (!checkBox) return ; m_modified = true; TQString propertyName = checkBox->name(); bool checked = checkBox->isChecked(); m_event.set(qstrtostr(propertyName), checked); } void EventEditDialog::slotStringPropertyChanged(const TQString &value) { const TQObject *s = TQT_TQOBJECT_CONST(const_cast(sender())); const TQLineEdit *lineEdit = dynamic_cast(s); if (!lineEdit) return ; m_modified = true; TQString propertyName = lineEdit->name(); m_event.set(qstrtostr(propertyName), qstrtostr(value)); } void EventEditDialog::slotPropertyDeleted() { const TQObject *s = TQT_TQOBJECT_CONST(const_cast(sender())); const TQPushButton *pushButton = dynamic_cast(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 = TQT_TQOBJECT_CONST(const_cast(sender())); const TQPushButton *pushButton = dynamic_cast(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 (qstrtostr(propertyName), m_originalEvent.get (qstrtostr(propertyName))); break; case UInt: m_event.set (qstrtostr(propertyName), m_originalEvent.get (qstrtostr(propertyName))); break; case RealTimeT: m_event.set (qstrtostr(propertyName), m_originalEvent.get (qstrtostr(propertyName))); break; case Bool: m_event.set (qstrtostr(propertyName), m_originalEvent.get (qstrtostr(propertyName))); break; case String: m_event.set (qstrtostr(propertyName), m_originalEvent.get (qstrtostr(propertyName))); break; } } } #include "EventEditDialog.moc"