/* -*- 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 "EventView.h" #include "EventViewItem.h" #include "TrivialVelocityDialog.h" #include "base/BaseProperties.h" #include "misc/Debug.h" #include "misc/Strings.h" #include "base/Clipboard.h" #include "base/Event.h" #include "base/MidiTypes.h" #include "base/NotationTypes.h" #include "base/RealTime.h" #include "base/Segment.h" #include "base/SegmentPerformanceHelper.h" #include "base/Selection.h" #include "base/Track.h" #include "base/TriggerSegment.h" #include "commands/edit/CopyCommand.h" #include "commands/edit/CutCommand.h" #include "commands/edit/EraseCommand.h" #include "commands/edit/EventEditCommand.h" #include "commands/edit/PasteEventsCommand.h" #include "commands/edit/EventInsertionCommand.h" #include "commands/segment/SegmentLabelCommand.h" #include "commands/segment/SetTriggerSegmentBasePitchCommand.h" #include "commands/segment/SetTriggerSegmentBaseVelocityCommand.h" #include "commands/segment/SetTriggerSegmentDefaultRetuneCommand.h" #include "commands/segment/SetTriggerSegmentDefaultTimeAdjustCommand.h" #include "document/RosegardenGUIDoc.h" #include "document/ConfigGroups.h" #include "gui/dialogs/EventEditDialog.h" #include "gui/dialogs/PitchDialog.h" #include "gui/dialogs/SimpleEventEditDialog.h" #include "gui/general/EditViewBase.h" #include "gui/general/MidiPitchLabel.h" #include "gui/kdeext/KTmpStatusMsg.h" #include "gui/dialogs/EventFilterDialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Rosegarden { int EventView::m_lastSetEventFilter = -1; EventView::EventView(RosegardenGUIDoc *doc, std::vector segments, TQWidget *tqparent): EditViewBase(doc, segments, 2, tqparent, "eventview"), m_eventFilter(Note | Text | SystemExclusive | Controller | ProgramChange | PitchBend | Indication | Other), m_menu(0) { m_isTriggerSegment = false; m_triggerName = m_triggerPitch = m_triggerVelocity = 0; if (!segments.empty()) { Segment *s = *segments.begin(); if (s->getComposition()) { int id = s->getComposition()->getTriggerSegmentId(s); if (id >= 0) m_isTriggerSegment = true; } } if (m_lastSetEventFilter < 0) m_lastSetEventFilter = m_eventFilter; else m_eventFilter = m_lastSetEventFilter; initStatusBar(); setupActions(); // define some note filtering buttons in a group // m_filterGroup = new TQButtonGroup(1, Qt::Horizontal, i18n("Event filters"), getCentralWidget()); m_noteCheckBox = new TQCheckBox(i18n("Note"), m_filterGroup); m_programCheckBox = new TQCheckBox(i18n("Program Change"), m_filterGroup); m_controllerCheckBox = new TQCheckBox(i18n("Controller"), m_filterGroup); m_pitchBendCheckBox = new TQCheckBox(i18n("Pitch Bend"), m_filterGroup); m_sysExCheckBox = new TQCheckBox(i18n("System Exclusive"), m_filterGroup); m_keyPressureCheckBox = new TQCheckBox(i18n("Key Pressure"), m_filterGroup); m_channelPressureCheckBox = new TQCheckBox(i18n("Channel Pressure"), m_filterGroup); m_restCheckBox = new TQCheckBox(i18n("Rest"), m_filterGroup); m_indicationCheckBox = new TQCheckBox(i18n("Indication"), m_filterGroup); m_textCheckBox = new TQCheckBox(i18n("Text"), m_filterGroup); m_otherCheckBox = new TQCheckBox(i18n("Other"), m_filterGroup); m_grid->addWidget(m_filterGroup, 2, 0); // Connect up // connect(m_filterGroup, TQT_SIGNAL(released(int)), TQT_SLOT(slotModifyFilter(int))); m_eventList = new KListView(getCentralWidget()); m_eventList->setItemsRenameable(true); m_grid->addWidget(m_eventList, 2, 1); if (m_isTriggerSegment) { int id = segments[0]->getComposition()->getTriggerSegmentId(segments[0]); TriggerSegmentRec *rec = segments[0]->getComposition()->getTriggerSegmentRec(id); TQGroupBox *groupBox = new TQGroupBox (1, Qt::Horizontal, i18n("Triggered Segment Properties"), getCentralWidget()); TQFrame *frame = new TQFrame(groupBox); TQGridLayout *tqlayout = new TQGridLayout(frame, 5, 3, 5, 5); tqlayout->addWidget(new TQLabel(i18n("Label: "), frame), 0, 0); TQString label = strtoqstr(segments[0]->getLabel()); if (label == "") label = i18n(""); m_triggerName = new TQLabel(label, frame); tqlayout->addWidget(m_triggerName, 0, 1); TQPushButton *editButton = new TQPushButton(i18n("edit"), frame); tqlayout->addWidget(editButton, 0, 2); connect(editButton, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(slotEditTriggerName())); tqlayout->addWidget(new TQLabel(i18n("Base pitch: "), frame), 1, 0); m_triggerPitch = new TQLabel(TQString("%1").tqarg(rec->getBasePitch()), frame); tqlayout->addWidget(m_triggerPitch, 1, 1); editButton = new TQPushButton(i18n("edit"), frame); tqlayout->addWidget(editButton, 1, 2); connect(editButton, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(slotEditTriggerPitch())); tqlayout->addWidget(new TQLabel(i18n("Base velocity: "), frame), 2, 0); m_triggerVelocity = new TQLabel(TQString("%1").tqarg(rec->getBaseVelocity()), frame); tqlayout->addWidget(m_triggerVelocity, 2, 1); editButton = new TQPushButton(i18n("edit"), frame); tqlayout->addWidget(editButton, 2, 2); connect(editButton, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(slotEditTriggerVelocity())); /*!!! Comment out these two options, which are not yet used anywhere else -- intended for use with library ornaments, not yet implemented tqlayout->addWidget(new TQLabel(i18n("Default timing: "), frame), 3, 0); KComboBox *adjust = new KComboBox(frame); tqlayout->addMultiCellWidget(adjust, 3, 3, 1, 2); adjust->insertItem(i18n("As stored")); adjust->insertItem(i18n("Truncate if longer than note")); adjust->insertItem(i18n("End at same time as note")); adjust->insertItem(i18n("Stretch or squash segment to note duration")); std::string timing = rec->getDefaultTimeAdjust(); if (timing == BaseProperties::TRIGGER_SEGMENT_ADJUST_NONE) { adjust->setCurrentItem(0); } else if (timing == BaseProperties::TRIGGER_SEGMENT_ADJUST_STQUISH) { adjust->setCurrentItem(3); } else if (timing == BaseProperties::TRIGGER_SEGMENT_ADJUST_SYNC_START) { adjust->setCurrentItem(1); } else if (timing == BaseProperties::TRIGGER_SEGMENT_ADJUST_SYNC_END) { adjust->setCurrentItem(2); } connect(adjust, TQT_SIGNAL(activated(int)), TQT_TQOBJECT(this), TQT_SLOT(slotTriggerTimeAdjustChanged(int))); TQCheckBox *retune = new TQCheckBox(i18n("Adjust pitch to trigger note by default"), frame); retune->setChecked(rec->getDefaultRetune()); connect(retune, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(slotTriggerRetuneChanged())); tqlayout->addMultiCellWidget(retune, 4, 4, 1, 2); */ m_grid->addWidget(groupBox, 2, 2); } updateViewCaption(); for (unsigned int i = 0; i < m_segments.size(); ++i) { m_segments[i]->addObserver(this); } // Connect double clicker // connect(m_eventList, TQT_SIGNAL(doubleClicked(TQListViewItem*)), TQT_SLOT(slotPopupEventEditor(TQListViewItem*))); connect(m_eventList, TQT_SIGNAL(rightButtonPressed(TQListViewItem*, const TQPoint&, int)), TQT_SLOT(slotPopupMenu(TQListViewItem*, const TQPoint&, int))); m_eventList->setAllColumnsShowFocus(true); m_eventList->setSelectionMode(TQListView::Extended); m_eventList->addColumn(i18n("Time ")); m_eventList->addColumn(i18n("Duration ")); m_eventList->addColumn(i18n("Event Type ")); m_eventList->addColumn(i18n("Pitch ")); m_eventList->addColumn(i18n("Velocity ")); m_eventList->addColumn(i18n("Type (Data1) ")); m_eventList->addColumn(i18n("Value (Data2) ")); for (int col = 0; col < m_eventList->columns(); ++col) m_eventList->setRenameable(col, true); readOptions(); setButtonsToFilter(); applyLayout(); makeInitialSelection(doc->getComposition().getPosition()); slotCompositionStateUpdate(); setOutOfCtor(); } EventView::~EventView() { for (unsigned int i = 0; i < m_segments.size(); ++i) { RG_DEBUG << "~EventView - removing this observer from " << m_segments[i] << endl; m_segments[i]->removeObserver(this); } } void EventView::eventRemoved(const Segment *, Event *e) { m_deletedEvents.insert(e); } void EventView::segmentDeleted(const Segment *s) { std::vector::iterator i = std::find(m_segments.begin(), m_segments.end(), s); if (i != m_segments.end()) { m_segments.erase(i); } else { RG_DEBUG << "%%% WARNING - EventView::segmentDeleted() called on non-registered segment - should not happen\n"; } } bool EventView::applyLayout(int /*staffNo*/) { // If no selection has already been set then we copy what's // already set and try to replicate this after the rebuild // of the view. // if (m_listSelection.size() == 0) { TQPtrList selection = m_eventList->selectedItems(); if (selection.count()) { TQPtrListIterator it(selection); TQListViewItem *listItem; while ((listItem = it.current()) != 0) { m_listSelection.push_back(m_eventList->itemIndex(*it)); ++it; } } } // Ok, recreate list // m_eventList->clear(); m_config->setGroup(EventViewConfigGroup); int timeMode = m_config->readNumEntry("timemode", 0); for (unsigned int i = 0; i < m_segments.size(); i++) { SegmentPerformanceHelper helper(*m_segments[i]); for (Segment::iterator it = m_segments[i]->begin(); m_segments[i]->isBeforeEndMarker(it); it++) { timeT eventTime = helper.getSoundingAbsoluteTime(it); TQString velyStr; TQString pitchStr; TQString data1Str = ""; TQString data2Str = ""; TQString durationStr; // Event filters // if ((*it)->isa(Note::EventRestType)) { if (!(m_eventFilter & Rest)) continue; } else if ((*it)->isa(Note::EventType)) { if (!(m_eventFilter & Note)) continue; } else if ((*it)->isa(Indication::EventType)) { if (!(m_eventFilter & Indication)) continue; } else if ((*it)->isa(PitchBend::EventType)) { if (!(m_eventFilter & PitchBend)) continue; } else if ((*it)->isa(SystemExclusive::EventType)) { if (!(m_eventFilter & SystemExclusive)) continue; } else if ((*it)->isa(ProgramChange::EventType)) { if (!(m_eventFilter & ProgramChange)) continue; } else if ((*it)->isa(ChannelPressure::EventType)) { if (!(m_eventFilter & ChannelPressure)) continue; } else if ((*it)->isa(KeyPressure::EventType)) { if (!(m_eventFilter & KeyPressure)) continue; } else if ((*it)->isa(Controller::EventType)) { if (!(m_eventFilter & Controller)) continue; } else if ((*it)->isa(Text::EventType)) { if (!(m_eventFilter & Text)) continue; } else { if (!(m_eventFilter & Other)) continue; } // avoid debug stuff going to stderr if no properties found if ((*it)->has(BaseProperties::PITCH)) { int p = (*it)->get (BaseProperties::PITCH); pitchStr = TQString("%1 %2 ") .tqarg(p).tqarg(MidiPitchLabel(p).getTQString()); } else if ((*it)->isa(Note::EventType)) { pitchStr = ""; } if ((*it)->has(BaseProperties::VELOCITY)) { velyStr = TQString("%1 "). arg((*it)->get (BaseProperties::VELOCITY)); } else if ((*it)->isa(Note::EventType)) { velyStr = ""; } if ((*it)->has(Controller::NUMBER)) { data1Str = TQString("%1 "). arg((*it)->get (Controller::NUMBER)); } else if ((*it)->has(Text::TextTypePropertyName)) { data1Str = TQString("%1 "). arg(strtoqstr((*it)->get (Text::TextTypePropertyName))); } else if ((*it)->has(Indication:: IndicationTypePropertyName)) { data1Str = TQString("%1 "). arg(strtoqstr((*it)->get (Indication:: IndicationTypePropertyName))); } else if ((*it)->has(::Rosegarden::Key::KeyPropertyName)) { data1Str = TQString("%1 "). arg(strtoqstr((*it)->get (::Rosegarden::Key::KeyPropertyName))); } else if ((*it)->has(Clef::ClefPropertyName)) { data1Str = TQString("%1 "). arg(strtoqstr((*it)->get (Clef::ClefPropertyName))); } else if ((*it)->has(PitchBend::MSB)) { data1Str = TQString("%1 "). arg((*it)->get (PitchBend::MSB)); } else if ((*it)->has(BaseProperties::BEAMED_GROUP_TYPE)) { data1Str = TQString("%1 "). arg(strtoqstr((*it)->get (BaseProperties::BEAMED_GROUP_TYPE))); } if ((*it)->has(Controller::VALUE)) { data2Str = TQString("%1 "). arg((*it)->get (Controller::VALUE)); } else if ((*it)->has(Text::TextPropertyName)) { data2Str = TQString("%1 "). arg(strtoqstr((*it)->get (Text::TextPropertyName))); /*!!! } else if ((*it)->has(Indication:: IndicationTypePropertyName)) { data2Str = TQString("%1 "). arg((*it)->get(Indication:: IndicationDurationPropertyName)); */ } else if ((*it)->has(PitchBend::LSB)) { data2Str = TQString("%1 "). arg((*it)->get (PitchBend::LSB)); } else if ((*it)->has(BaseProperties::BEAMED_GROUP_ID)) { data2Str = i18n("(group %1) "). arg((*it)->get (BaseProperties::BEAMED_GROUP_ID)); } if ((*it)->has(ProgramChange::PROGRAM)) { data1Str = TQString("%1 "). arg((*it)->get (ProgramChange::PROGRAM) + 1); } if ((*it)->has(ChannelPressure::PRESSURE)) { data1Str = TQString("%1 "). arg((*it)->get (ChannelPressure::PRESSURE)); } if ((*it)->isa(KeyPressure::EventType) && (*it)->has(KeyPressure::PITCH)) { data1Str = TQString("%1 "). arg((*it)->get (KeyPressure::PITCH)); } if ((*it)->has(KeyPressure::PRESSURE)) { data2Str = TQString("%1 "). arg((*it)->get (KeyPressure::PRESSURE)); } if ((*it)->getDuration() > 0 || (*it)->isa(Note::EventType) || (*it)->isa(Note::EventRestType)) { durationStr = makeDurationString(eventTime, (*it)->getDuration(), timeMode); } TQString timeStr = makeTimeString(eventTime, timeMode); new EventViewItem(m_segments[i], *it, m_eventList, timeStr, durationStr, strtoqstr((*it)->getType()), pitchStr, velyStr, data1Str, data2Str); } } if (m_eventList->childCount() == 0) { if (m_segments.size()) new TQListViewItem(m_eventList, i18n("")); else new TQListViewItem(m_eventList, i18n("")); m_eventList->setSelectionMode(TQListView::NoSelection); stateChanged("have_selection", KXMLGUIClient::StateReverse); } else { m_eventList->setSelectionMode(TQListView::Extended); // If no selection then select the first event if (m_listSelection.size() == 0) m_listSelection.push_back(0); stateChanged("have_selection", KXMLGUIClient::StateNoReverse); } // Set a selection from a range of indexes // std::vector::iterator sIt = m_listSelection.begin(); int index = 0; for (; sIt != m_listSelection.end(); ++sIt) { index = *sIt; while (index > 0 && !m_eventList->itemAtIndex(index)) index--; m_eventList->setSelected(m_eventList->itemAtIndex(index), true); m_eventList->setCurrentItem(m_eventList->itemAtIndex(index)); // ensure visible m_eventList->ensureItemVisible(m_eventList->itemAtIndex(index)); } m_listSelection.clear(); m_deletedEvents.clear(); return true; } void EventView::makeInitialSelection(timeT time) { m_listSelection.clear(); EventViewItem *goodItem = 0; int goodItemNo = 0; int i = 0; for (TQListViewItem *child = m_eventList->firstChild(); child; child = child->nextSibling()) { EventViewItem * item = dynamic_cast(child); if (item) { if (item->getEvent()->getAbsoluteTime() > time) break; goodItem = item; goodItemNo = i; } ++i; } /*!!! for (int i = 0; m_eventList->itemAtIndex(i); ++i) { EventViewItem *item = dynamic_cast (m_eventList->itemAtIndex(i)); if (item) { if (item->getEvent()->getAbsoluteTime() > time) break; goodItem = item; goodItemNo = i; } } */ if (goodItem) { m_listSelection.push_back(goodItemNo); m_eventList->setSelected(goodItem, true); m_eventList->ensureItemVisible(goodItem); } } TQString EventView::makeTimeString(timeT time, int timeMode) { switch (timeMode) { case 0: // musical time { int bar, beat, fraction, remainder; getDocument()->getComposition().getMusicalTimeForAbsoluteTime (time, bar, beat, fraction, remainder); ++bar; return TQString("%1%2%3-%4%5-%6%7-%8%9 ") .tqarg(bar / 100) .tqarg((bar % 100) / 10) .tqarg(bar % 10) .tqarg(beat / 10) .tqarg(beat % 10) .tqarg(fraction / 10) .tqarg(fraction % 10) .tqarg(remainder / 10) .tqarg(remainder % 10); } case 1: // real time { RealTime rt = getDocument()->getComposition().getElapsedRealTime(time); // return TQString("%1 ").tqarg(rt.toString().c_str()); return TQString("%1 ").tqarg(rt.toText().c_str()); } default: return TQString("%1 ").tqarg(time); } } TQString EventView::makeDurationString(timeT time, timeT duration, int timeMode) { switch (timeMode) { case 0: // musical time { int bar, beat, fraction, remainder; getDocument()->getComposition().getMusicalTimeForDuration (time, duration, bar, beat, fraction, remainder); return TQString("%1%2%3-%4%5-%6%7-%8%9 ") .tqarg(bar / 100) .tqarg((bar % 100) / 10) .tqarg(bar % 10) .tqarg(beat / 10) .tqarg(beat % 10) .tqarg(fraction / 10) .tqarg(fraction % 10) .tqarg(remainder / 10) .tqarg(remainder % 10); } case 1: // real time { RealTime rt = getDocument()->getComposition().getRealTimeDifference (time, time + duration); // return TQString("%1 ").tqarg(rt.toString().c_str()); return TQString("%1 ").tqarg(rt.toText().c_str()); } default: return TQString("%1 ").tqarg(duration); } } void EventView::refreshSegment(Segment * /*segment*/, timeT /*startTime*/, timeT /*endTime*/) { RG_DEBUG << "EventView::refreshSegment" << endl; applyLayout(0); } void EventView::updateView() { m_eventList->update(); } void EventView::slotEditTriggerName() { bool ok = false; TQString newLabel = KLineEditDlg::getText(i18n("Segment label"), i18n("Label:"), strtoqstr(m_segments[0]->getLabel()), &ok, this); if (ok) { SegmentSelection selection; selection.insert(m_segments[0]); SegmentLabelCommand *cmd = new SegmentLabelCommand(selection, newLabel); addCommandToHistory(cmd); m_triggerName->setText(newLabel); } } void EventView::slotEditTriggerPitch() { int id = m_segments[0]->getComposition()->getTriggerSegmentId(m_segments[0]); TriggerSegmentRec *rec = m_segments[0]->getComposition()->getTriggerSegmentRec(id); PitchDialog *dlg = new PitchDialog(this, i18n("Base pitch"), rec->getBasePitch()); if (dlg->exec() == TQDialog::Accepted) { addCommandToHistory(new SetTriggerSegmentBasePitchCommand (&getDocument()->getComposition(), id, dlg->getPitch())); m_triggerPitch->setText(TQString("%1").tqarg(dlg->getPitch())); } } void EventView::slotEditTriggerVelocity() { int id = m_segments[0]->getComposition()->getTriggerSegmentId(m_segments[0]); TriggerSegmentRec *rec = m_segments[0]->getComposition()->getTriggerSegmentRec(id); TrivialVelocityDialog *dlg = new TrivialVelocityDialog (this, i18n("Base velocity"), rec->getBaseVelocity()); if (dlg->exec() == TQDialog::Accepted) { addCommandToHistory(new SetTriggerSegmentBaseVelocityCommand (&getDocument()->getComposition(), id, dlg->getVelocity())); m_triggerVelocity->setText(TQString("%1").tqarg(dlg->getVelocity())); } } void EventView::slotTriggerTimeAdjustChanged(int option) { std::string adjust = BaseProperties::TRIGGER_SEGMENT_ADJUST_STQUISH; switch (option) { case 0: adjust = BaseProperties::TRIGGER_SEGMENT_ADJUST_NONE; break; case 1: adjust = BaseProperties::TRIGGER_SEGMENT_ADJUST_SYNC_START; break; case 2: adjust = BaseProperties::TRIGGER_SEGMENT_ADJUST_SYNC_END; break; case 3: adjust = BaseProperties::TRIGGER_SEGMENT_ADJUST_STQUISH; break; default: break; } int id = m_segments[0]->getComposition()->getTriggerSegmentId(m_segments[0]); TriggerSegmentRec *rec = m_segments[0]->getComposition()->getTriggerSegmentRec(id); addCommandToHistory(new SetTriggerSegmentDefaultTimeAdjustCommand (&getDocument()->getComposition(), id, adjust)); } void EventView::slotTriggerRetuneChanged() { int id = m_segments[0]->getComposition()->getTriggerSegmentId(m_segments[0]); TriggerSegmentRec *rec = m_segments[0]->getComposition()->getTriggerSegmentRec(id); addCommandToHistory(new SetTriggerSegmentDefaultRetuneCommand (&getDocument()->getComposition(), id, !rec->getDefaultRetune())); } void EventView::slotEditCut() { TQPtrList selection = m_eventList->selectedItems(); if (selection.count() == 0) return ; RG_DEBUG << "EventView::slotEditCut - cutting " << selection.count() << " items" << endl; TQPtrListIterator it(selection); TQListViewItem *listItem; EventViewItem *item; EventSelection *cutSelection = 0; int itemIndex = -1; while ((listItem = it.current()) != 0) { item = dynamic_cast((*it)); if (itemIndex == -1) itemIndex = m_eventList->itemIndex(*it); if (item) { if (cutSelection == 0) cutSelection = new EventSelection(*(item->getSegment())); cutSelection->addEvent(item->getEvent()); } ++it; } if (cutSelection) { if (itemIndex >= 0) { m_listSelection.clear(); m_listSelection.push_back(itemIndex); } addCommandToHistory(new CutCommand(*cutSelection, getDocument()->getClipboard())); } } void EventView::slotEditCopy() { TQPtrList selection = m_eventList->selectedItems(); if (selection.count() == 0) return ; RG_DEBUG << "EventView::slotEditCopy - copying " << selection.count() << " items" << endl; TQPtrListIterator it(selection); TQListViewItem *listItem; EventViewItem *item; EventSelection *copySelection = 0; // clear the selection for post modification updating // m_listSelection.clear(); while ((listItem = it.current()) != 0) { item = dynamic_cast((*it)); m_listSelection.push_back(m_eventList->itemIndex(*it)); if (item) { if (copySelection == 0) copySelection = new EventSelection(*(item->getSegment())); copySelection->addEvent(item->getEvent()); } ++it; } if (copySelection) { addCommandToHistory(new CopyCommand(*copySelection, getDocument()->getClipboard())); } } void EventView::slotEditPaste() { if (getDocument()->getClipboard()->isEmpty()) { slotStatusHelpMsg(i18n("Clipboard is empty")); return ; } KTmpStatusMsg msg(i18n("Inserting clipboard contents..."), this); timeT insertionTime = 0; TQPtrList selection = m_eventList->selectedItems(); if (selection.count()) { EventViewItem *item = dynamic_cast(selection.at(0)); if (item) insertionTime = item->getEvent()->getAbsoluteTime(); // remember the selection // m_listSelection.clear(); TQPtrListIterator it(selection); TQListViewItem *listItem; while ((listItem = it.current()) != 0) { m_listSelection.push_back(m_eventList->itemIndex(*it)); ++it; } } PasteEventsCommand *command = new PasteEventsCommand (*m_segments[0], getDocument()->getClipboard(), insertionTime, PasteEventsCommand::MatrixOverlay); if (!command->isPossible()) { slotStatusHelpMsg(i18n("Couldn't paste at this point")); } else addCommandToHistory(command); RG_DEBUG << "EventView::slotEditPaste - pasting " << selection.count() << " items" << endl; } void EventView::slotEditDelete() { TQPtrList selection = m_eventList->selectedItems(); if (selection.count() == 0) return ; RG_DEBUG << "EventView::slotEditDelete - deleting " << selection.count() << " items" << endl; TQPtrListIterator it(selection); TQListViewItem *listItem; EventViewItem *item; EventSelection *deleteSelection = 0; int itemIndex = -1; while ((listItem = it.current()) != 0) { item = dynamic_cast((*it)); if (itemIndex == -1) itemIndex = m_eventList->itemIndex(*it); if (item) { if (m_deletedEvents.find(item->getEvent()) != m_deletedEvents.end()) { ++it; continue; } if (deleteSelection == 0) deleteSelection = new EventSelection(*m_segments[0]); deleteSelection->addEvent(item->getEvent()); } ++it; } if (deleteSelection) { if (itemIndex >= 0) { m_listSelection.clear(); m_listSelection.push_back(itemIndex); } addCommandToHistory(new EraseCommand(*deleteSelection)); } } void EventView::slotEditInsert() { RG_DEBUG << "EventView::slotEditInsert" << endl; timeT insertTime = m_segments[0]->getStartTime(); timeT insertDuration = 960; TQPtrList selection = m_eventList->selectedItems(); if (selection.count() > 0) { EventViewItem *item = dynamic_cast(selection.getFirst()); if (item) { insertTime = item->getEvent()->getAbsoluteTime(); insertDuration = item->getEvent()->getDuration(); } } // Create default event // Event *event = new Event(Note::EventType, insertTime, insertDuration); event->set (BaseProperties::PITCH, 70); event->set (BaseProperties::VELOCITY, 100); SimpleEventEditDialog dialog(this, getDocument(), *event, true); if (dialog.exec() == TQDialog::Accepted) { EventInsertionCommand *command = new EventInsertionCommand(*m_segments[0], new Event(dialog.getEvent())); addCommandToHistory(command); } } void EventView::slotEditEvent() { RG_DEBUG << "EventView::slotEditEvent" << endl; TQPtrList selection = m_eventList->selectedItems(); if (selection.count() > 0) { EventViewItem *item = dynamic_cast(selection.getFirst()); if (item) { Event *event = item->getEvent(); SimpleEventEditDialog dialog(this, getDocument(), *event, false); if (dialog.exec() == TQDialog::Accepted && dialog.isModified()) { EventEditCommand *command = new EventEditCommand(*(item->getSegment()), event, dialog.getEvent()); addCommandToHistory(command); } } } } void EventView::slotEditEventAdvanced() { RG_DEBUG << "EventView::slotEditEventAdvanced" << endl; TQPtrList selection = m_eventList->selectedItems(); if (selection.count() > 0) { EventViewItem *item = dynamic_cast(selection.getFirst()); if (item) { Event *event = item->getEvent(); EventEditDialog dialog(this, *event); if (dialog.exec() == TQDialog::Accepted && dialog.isModified()) { EventEditCommand *command = new EventEditCommand(*(item->getSegment()), event, dialog.getEvent()); addCommandToHistory(command); } } } } void EventView::slotSelectAll() { m_listSelection.clear(); for (int i = 0; m_eventList->itemAtIndex(i); ++i) { m_listSelection.push_back(i); m_eventList->setSelected(m_eventList->itemAtIndex(i), true); } } void EventView::slotClearSelection() { m_listSelection.clear(); for (int i = 0; m_eventList->itemAtIndex(i); ++i) { m_eventList->setSelected(m_eventList->itemAtIndex(i), false); } } void EventView::slotFilterSelection() { m_listSelection.clear(); TQPtrList selection = m_eventList->selectedItems(); if (selection.count() == 0) return ; EventFilterDialog dialog(this); if (dialog.exec() == TQDialog::Accepted) { TQPtrListIterator it(selection); TQListViewItem *listItem; while ((listItem = it.current()) != 0) { EventViewItem * item = dynamic_cast(*it); if (!item) { ++it; continue; } if (!dialog.keepEvent(item->getEvent())) { m_listSelection.push_back(m_eventList->itemIndex(*it)); m_eventList->setSelected(item, false); } ++it; } } } void EventView::setupActions() { EditViewBase::setupActions("eventlist.rc"); TQString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/"); TQIconSet icon(TQPixmap(pixmapDir + "/toolbar/event-insert.png")); new KAction(i18n("&Insert Event"), icon, Key_I, TQT_TQOBJECT(this), TQT_SLOT(slotEditInsert()), actionCollection(), "insert"); TQCanvasPixmap pixmap(pixmapDir + "/toolbar/event-delete.png"); icon = TQIconSet(pixmap); new KAction(i18n("&Delete Event"), icon, Key_Delete, TQT_TQOBJECT(this), TQT_SLOT(slotEditDelete()), actionCollection(), "delete"); pixmap.load(pixmapDir + "/toolbar/event-edit.png"); icon = TQIconSet(pixmap); new KAction(i18n("&Edit Event"), icon, Key_E, TQT_TQOBJECT(this), TQT_SLOT(slotEditEvent()), actionCollection(), "edit_simple"); pixmap.load(pixmapDir + "/toolbar/event-edit-advanced.png"); icon = TQIconSet(pixmap); new KAction(i18n("&Advanced Event Editor"), icon, Key_A, TQT_TQOBJECT(this), TQT_SLOT(slotEditEventAdvanced()), actionCollection(), "edit_advanced"); // icon = TQIconSet(TQCanvasPixmap(pixmapDir + "/toolbar/eventfilter.xpm")); new KAction(i18n("&Filter Selection"), "filter", Key_F, TQT_TQOBJECT(this), TQT_SLOT(slotFilterSelection()), actionCollection(), "filter_selection"); new KAction(i18n("Select &All"), Key_A + CTRL, TQT_TQOBJECT(this), TQT_SLOT(slotSelectAll()), actionCollection(), "select_all"); new KAction(i18n("Clear Selection"), Key_Escape, TQT_TQOBJECT(this), TQT_SLOT(slotClearSelection()), actionCollection(), "clear_selection"); m_config->setGroup(EventViewConfigGroup); int timeMode = m_config->readNumEntry("timemode", 0); KRadioAction *action; pixmap.load(pixmapDir + "/toolbar/time-musical.png"); icon = TQIconSet(pixmap); action = new KRadioAction(i18n("&Musical Times"), icon, 0, TQT_TQOBJECT(this), TQT_SLOT(slotMusicalTime()), actionCollection(), "time_musical"); action->setExclusiveGroup("timeMode"); if (timeMode == 0) action->setChecked(true); pixmap.load(pixmapDir + "/toolbar/time-real.png"); icon = TQIconSet(pixmap); action = new KRadioAction(i18n("&Real Times"), icon, 0, TQT_TQOBJECT(this), TQT_SLOT(slotRealTime()), actionCollection(), "time_real"); action->setExclusiveGroup("timeMode"); if (timeMode == 1) action->setChecked(true); pixmap.load(pixmapDir + "/toolbar/time-raw.png"); icon = TQIconSet(pixmap); action = new KRadioAction(i18n("Ra&w Times"), icon, 0, TQT_TQOBJECT(this), TQT_SLOT(slotRawTime()), actionCollection(), "time_raw"); action->setExclusiveGroup("timeMode"); if (timeMode == 2) action->setChecked(true); if (m_isTriggerSegment) { KAction *action = actionCollection()->action("open_in_matrix"); if (action) delete action; action = actionCollection()->action("open_in_notation"); if (action) delete action; } createGUI(getRCFileName()); } void EventView::initStatusBar() { KStatusBar* sb = statusBar(); /* m_hoveredOverNoteName = new TQLabel(sb); m_hoveredOverAbsoluteTime = new TQLabel(sb); m_hoveredOverNoteName->setMinimumWidth(32); m_hoveredOverAbsoluteTime->setMinimumWidth(160); sb->addWidget(m_hoveredOverAbsoluteTime); sb->addWidget(m_hoveredOverNoteName); */ sb->insertItem(KTmpStatusMsg::getDefaultMsg(), KTmpStatusMsg::getDefaultId(), 1); sb->setItemAlignment(KTmpStatusMsg::getDefaultId(), AlignLeft | AlignVCenter); //m_selectionCounter = new TQLabel(sb); //sb->addWidget(m_selectionCounter); } TQSize EventView::getViewSize() { return m_eventList->size(); } void EventView::setViewSize(TQSize s) { m_eventList->setFixedSize(s); } void EventView::readOptions() { m_config->setGroup(EventViewConfigGroup); EditViewBase::readOptions(); m_eventFilter = m_config->readNumEntry("eventfilter", m_eventFilter); m_eventList->restoreLayout(m_config, EventViewLayoutConfigGroupName); } void EventView::slotSaveOptions() { m_config->setGroup(EventViewConfigGroup); m_config->writeEntry("eventfilter", m_eventFilter); m_eventList->saveLayout(m_config, EventViewLayoutConfigGroupName); } Segment * EventView::getCurrentSegment() { if (m_segments.empty()) return 0; else return *m_segments.begin(); } void EventView::slotModifyFilter(int button) { TQCheckBox *checkBox = dynamic_cast(m_filterGroup->tqfind(button)); if (checkBox == 0) return ; if (checkBox->isChecked()) { switch (button) { case 0: m_eventFilter |= EventView::Note; break; case 1: m_eventFilter |= EventView::ProgramChange; break; case 2: m_eventFilter |= EventView::Controller; break; case 3: m_eventFilter |= EventView::PitchBend; break; case 4: m_eventFilter |= EventView::SystemExclusive; break; case 5: m_eventFilter |= EventView::KeyPressure; break; case 6: m_eventFilter |= EventView::ChannelPressure; break; case 7: m_eventFilter |= EventView::Rest; break; case 8: m_eventFilter |= EventView::Indication; break; case 9: m_eventFilter |= EventView::Text; break; case 10: m_eventFilter |= EventView::Other; break; default: break; } } else { switch (button) { case 0: m_eventFilter ^= EventView::Note; break; case 1: m_eventFilter ^= EventView::ProgramChange; break; case 2: m_eventFilter ^= EventView::Controller; break; case 3: m_eventFilter ^= EventView::PitchBend; break; case 4: m_eventFilter ^= EventView::SystemExclusive; break; case 5: m_eventFilter ^= EventView::KeyPressure; break; case 6: m_eventFilter ^= EventView::ChannelPressure; break; case 7: m_eventFilter ^= EventView::Rest; break; case 8: m_eventFilter ^= EventView::Indication; break; case 9: m_eventFilter ^= EventView::Text; break; case 10: m_eventFilter ^= EventView::Other; break; default: break; } } m_lastSetEventFilter = m_eventFilter; applyLayout(0); } void EventView::setButtonsToFilter() { if (m_eventFilter & Note) m_noteCheckBox->setChecked(true); else m_noteCheckBox->setChecked(false); if (m_eventFilter & ProgramChange) m_programCheckBox->setChecked(true); else m_programCheckBox->setChecked(false); if (m_eventFilter & Controller) m_controllerCheckBox->setChecked(true); else m_controllerCheckBox->setChecked(false); if (m_eventFilter & SystemExclusive) m_sysExCheckBox->setChecked(true); else m_sysExCheckBox->setChecked(false); if (m_eventFilter & Text) m_textCheckBox->setChecked(true); else m_textCheckBox->setChecked(false); if (m_eventFilter & Rest) m_restCheckBox->setChecked(true); else m_restCheckBox->setChecked(false); if (m_eventFilter & PitchBend) m_pitchBendCheckBox->setChecked(true); else m_pitchBendCheckBox->setChecked(false); if (m_eventFilter & ChannelPressure) m_channelPressureCheckBox->setChecked(true); else m_channelPressureCheckBox->setChecked(false); if (m_eventFilter & KeyPressure) m_keyPressureCheckBox->setChecked(true); else m_keyPressureCheckBox->setChecked(false); if (m_eventFilter & Indication) { m_indicationCheckBox->setChecked(true); } else { m_indicationCheckBox->setChecked(false); } if (m_eventFilter & Other) { m_otherCheckBox->setChecked(true); } else { m_otherCheckBox->setChecked(false); } } void EventView::slotMusicalTime() { m_config->setGroup(EventViewConfigGroup); m_config->writeEntry("timemode", 0); applyLayout(); } void EventView::slotRealTime() { m_config->setGroup(EventViewConfigGroup); m_config->writeEntry("timemode", 1); applyLayout(); } void EventView::slotRawTime() { m_config->setGroup(EventViewConfigGroup); m_config->writeEntry("timemode", 2); applyLayout(); } void EventView::slotPopupEventEditor(TQListViewItem *item) { EventViewItem *eItem = dynamic_cast(item); //!!! trigger events if (eItem) { Event *event = eItem->getEvent(); SimpleEventEditDialog *dialog = new SimpleEventEditDialog(this, getDocument(), *event, false); if (dialog->exec() == TQDialog::Accepted && dialog->isModified()) { EventEditCommand *command = new EventEditCommand(*(eItem->getSegment()), event, dialog->getEvent()); addCommandToHistory(command); } } } void EventView::slotPopupMenu(TQListViewItem *item, const TQPoint &pos, int) { if (!item) return ; EventViewItem *eItem = dynamic_cast(item); if (!eItem || !eItem->getEvent()) return ; if (!m_menu) createMenu(); if (m_menu) //m_menu->exec(TQCursor::pos()); m_menu->exec(pos); else RG_DEBUG << "EventView::showMenu() : no menu to show\n"; } void EventView::createMenu() { m_menu = new TQPopupMenu(this); m_menu->insertItem(i18n("Open in Event Editor"), 0); m_menu->insertItem(i18n("Open in Expert Event Editor"), 1); connect(m_menu, TQT_SIGNAL(activated(int)), TQT_SLOT(slotMenuActivated(int))); } void EventView::slotMenuActivated(int value) { RG_DEBUG << "EventView::slotMenuActivated - value = " << value << endl; if (value == 0) { EventViewItem *eItem = dynamic_cast (m_eventList->currentItem()); if (eItem) { Event *event = eItem->getEvent(); SimpleEventEditDialog *dialog = new SimpleEventEditDialog(this, getDocument(), *event, false); if (dialog->exec() == TQDialog::Accepted && dialog->isModified()) { EventEditCommand *command = new EventEditCommand(*(eItem->getSegment()), event, dialog->getEvent()); addCommandToHistory(command); } } } else if (value == 1) { EventViewItem *eItem = dynamic_cast (m_eventList->currentItem()); if (eItem) { Event *event = eItem->getEvent(); EventEditDialog *dialog = new EventEditDialog(this, *event); if (dialog->exec() == TQDialog::Accepted && dialog->isModified()) { EventEditCommand *command = new EventEditCommand(*(eItem->getSegment()), event, dialog->getEvent()); addCommandToHistory(command); } } } return ; } void EventView::updateViewCaption() { if (m_isTriggerSegment) { setCaption(i18n("%1 - Triggered Segment: %2") .tqarg(getDocument()->getTitle()) .tqarg(strtoqstr(m_segments[0]->getLabel()))); } else if (m_segments.size() == 1) { TrackId trackId = m_segments[0]->getTrack(); Track *track = m_segments[0]->getComposition()->getTrackById(trackId); int trackPosition = -1; if (track) trackPosition = track->getPosition(); setCaption(i18n("%1 - Segment Track #%2 - Event List") .tqarg(getDocument()->getTitle()) .tqarg(trackPosition + 1)); } else { setCaption(i18n("%1 - %2 Segments - Event List") .tqarg(getDocument()->getTitle()) .tqarg(m_segments.size())); } } } #include "EventView.moc"