/* -*- 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 "SegmentParameterBox.h" #include #include #include #include "misc/Debug.h" #include "misc/Strings.h" #include "document/ConfigGroups.h" #include "base/Colour.h" #include "base/ColourMap.h" #include "base/Composition.h" #include "base/MidiProgram.h" #include "base/NotationTypes.h" #include "base/BasicQuantizer.h" #include "base/RealTime.h" #include "base/Segment.h" #include "base/Selection.h" #include "commands/segment/SegmentChangeQuantizationCommand.h" #include "commands/segment/SegmentColourCommand.h" #include "commands/segment/SegmentColourMapCommand.h" #include "commands/segment/SegmentCommandRepeat.h" #include "commands/segment/SegmentLabelCommand.h" #include "document/MultiViewCommandHistory.h" #include "document/RosegardenGUIDoc.h" #include "gui/dialogs/PitchPickerDialog.h" #include "gui/editors/notation/NotationStrings.h" #include "gui/editors/notation/NotePixmapFactory.h" #include "gui/general/GUIPalette.h" #include "gui/widgets/ColourTable.h" #include "gui/widgets/TristateCheckBox.h" #include "RosegardenParameterArea.h" #include "RosegardenParameterBox.h" #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 { SegmentParameterBox::SegmentParameterBox(RosegardenGUIDoc* doc, TQWidget *parent) : RosegardenParameterBox(i18n("Segment"), i18n("Segment Parameters"), parent), m_highestPlayable(127), m_lowestPlayable(0), m_standardQuantizations(BasicQuantizer::getStandardQuantizations()), m_doc(doc), m_transposeRange(48) { initBox(); m_doc->getComposition().addObserver(this); connect(getCommandHistory(), TQT_SIGNAL(commandExecuted()), this, TQT_SLOT(update())); } SegmentParameterBox::~SegmentParameterBox() { if (!isCompositionDeleted()) { m_doc->getComposition().removeObserver(this); } } void SegmentParameterBox::initBox() { TQFont font(m_font); TQFontMetrics fontMetrics(font); // magic numbers: 13 is the height of the menu pixmaps, 10 is just 10 //int comboHeight = std::max(fontMetrics.height(), 13) + 10; int width = fontMetrics.width("12345678901234567890"); // TQFrame *frame = new TQFrame(this); TQGridLayout *gridLayout = new TQGridLayout(this, 8, 6, 4, 2); TQLabel *label = new TQLabel(i18n("Label"), this); TQLabel *repeatLabel = new TQLabel(i18n("Repeat"), this); TQLabel *quantizeLabel = new TQLabel(i18n("Quantize"), this); TQLabel *transposeLabel = new TQLabel(i18n("Transpose"), this); TQLabel *delayLabel = new TQLabel(i18n("Delay"), this); TQLabel *colourLabel = new TQLabel(i18n("Color"), this); // m_autoFadeLabel = new TQLabel(i18n("Audio auto-fade"), this); // m_fadeInLabel = new TQLabel(i18n("Fade in"), this); // m_fadeOutLabel = new TQLabel(i18n("Fade out"), this); // m_rangeLabel = new TQLabel(i18n("Range"), this); // Label .. m_label = new TQLabel(this); m_label->setFont(font); m_label->setFixedWidth(width); //m_label->setFixedHeight(comboHeight); m_label->setFrameStyle(TQFrame::Panel | TQFrame::Sunken); // .. and edit button m_labelButton = new TQPushButton(i18n("Edit"), this); m_labelButton->setFont(font); // m_labelButton->setFixedWidth(50); connect(m_labelButton, TQT_SIGNAL(released()), TQT_SLOT(slotEditSegmentLabel())); m_repeatValue = new TristateCheckBox(this); m_repeatValue->setFont(font); //m_repeatValue->setFixedHeight(comboHeight); // handle state changes connect(m_repeatValue, TQT_SIGNAL(pressed()), TQT_SLOT(slotRepeatPressed())); // non-reversing motif style read-only combo m_quantizeValue = new KComboBox(this); m_quantizeValue->setFont(font); //m_quantizeValue->setFixedHeight(comboHeight); // handle quantize changes from drop down connect(m_quantizeValue, TQT_SIGNAL(activated(int)), TQT_SLOT(slotQuantizeSelected(int))); // reversing motif style read-write combo m_transposeValue = new KComboBox(this); m_transposeValue->setFont(font); //m_transposeValue->setFixedHeight(comboHeight); // handle transpose combo changes connect(m_transposeValue, TQT_SIGNAL(activated(int)), TQT_SLOT(slotTransposeSelected(int))); // and text changes connect(m_transposeValue, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(slotTransposeTextChanged(const TQString&))); // reversing motif style read-write combo m_delayValue = new KComboBox(this); m_delayValue->setFont(font); //m_delayValue->setFixedHeight(comboHeight); // handle delay combo changes connect(m_delayValue, TQT_SIGNAL(activated(int)), TQT_SLOT(slotDelaySelected(int))); // Detect when the document colours are updated connect(m_doc, TQT_SIGNAL(docColoursChanged()), this, TQT_SLOT(slotDocColoursChanged())); // handle text changes for delay connect(m_delayValue, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(slotDelayTextChanged(const TQString &))); // set up combo box for colours m_colourValue = new KComboBox(false, this); m_colourValue->setFont(font); //m_colourValue->setFixedHeight(comboHeight); // m_colourValue->setMaximumWidth(width); m_colourValue->setSizeLimit(20); // handle colour combo changes connect(m_colourValue, TQT_SIGNAL(activated(int)), TQT_SLOT(slotColourSelected(int))); // pre-set width of buttons so they don't grow later // width = fontMetrics.width(i18n("used internally for spacing", "High: ----")); // highest playable note // // m_highButton = new TQPushButton(i18n("High: ---"), this); // TQToolTip::add // (m_highButton, i18n("Choose the highest suggested playable note, using a staff")); // m_highButton->setFont(font); // m_highButton->setMinimumWidth(width); // connect(m_highButton, TQT_SIGNAL(released()), // TQT_SLOT(slotHighestPressed())); // lowest playable note // // m_lowButton = new TQPushButton(i18n("Low: ----"), this); // TQToolTip::add // (m_lowButton, i18n("Choose the lowest suggested playable note, using a staff")); // m_lowButton->setFont(font); // m_lowButton->setMinimumWidth(width); // connect(m_lowButton, TQT_SIGNAL(released()), // TQT_SLOT(slotLowestPressed())); // Audio autofade enabled // // m_autoFadeBox = new TQCheckBox(this); // connect(m_autoFadeBox, TQT_SIGNAL(stateChanged(int)), // this, TQT_SLOT(slotAudioFadeChanged(int))); // Fade in and out times // // m_fadeInSpin = new TQSpinBox(this); // m_fadeInSpin->setMinValue(0); // m_fadeInSpin->setMaxValue(5000); // m_fadeInSpin->setSuffix(i18n(" ms")); // connect(m_fadeInSpin, TQT_SIGNAL(valueChanged(int)), // this, TQT_SLOT(slotFadeInChanged(int))); // m_fadeOutSpin = new TQSpinBox(this); // m_fadeOutSpin->setMinValue(0); // m_fadeOutSpin->setMaxValue(5000); // m_fadeOutSpin->setSuffix(i18n(" ms")); // connect(m_fadeOutSpin, TQT_SIGNAL(valueChanged(int)), // this, TQT_SLOT(slotFadeOutChanged(int))); label->setFont(font); repeatLabel->setFont(font); quantizeLabel->setFont(font); transposeLabel->setFont(font); delayLabel->setFont(font); colourLabel->setFont(font); // m_autoFadeLabel->setFont(font); // m_fadeInLabel->setFont(font); // m_fadeOutLabel->setFont(font); // m_rangeLabel->setFont(font); int row = 0; // gridLayout->addRowSpacing(0, 12); // why?? gridLayout->addWidget(label, row, 0); //, AlignRight); gridLayout->addMultiCellWidget(m_label, row, row, 1, 4); //, AlignLeft); gridLayout->addWidget(m_labelButton, row, 5); //, AlignLeft); ++row; gridLayout->addWidget(repeatLabel, row, 0); //, AlignRight); gridLayout->addWidget(m_repeatValue, row, 1); //, AlignLeft); gridLayout->addMultiCellWidget(transposeLabel, row, row, 2, 3, AlignRight); gridLayout->addMultiCellWidget(m_transposeValue, row, row, 4, 5); ++row; gridLayout->addWidget(quantizeLabel, row, 0); //, AlignRight); gridLayout->addMultiCellWidget(m_quantizeValue, row, row, 1, 2); //, AlignLeft); gridLayout->addWidget(delayLabel, row, 3, AlignRight); gridLayout->addMultiCellWidget(m_delayValue, row, row, 4, 5); ++row; gridLayout->addWidget(colourLabel, row, 0); //, AlignRight); gridLayout->addMultiCellWidget(m_colourValue, row, row, 1, 5); ++row; // gridLayout->addWidget(m_rangeLabel, row, 0); //, AlignRight); // gridLayout->addMultiCellWidget(m_lowButton, row, row, 1, 2); // gridLayout->addMultiCellWidget(m_highButton, row, row, 3, 4); // ++row; // m_autoFadeLabel->hide(); // m_autoFadeBox->hide(); /* gridLayout->addWidget(m_fadeInLabel, 5, 0, AlignRight); gridLayout->addWidget(m_fadeInSpin, 5, 1); gridLayout->addWidget(m_fadeOutLabel, 5, 2, AlignRight); gridLayout->addWidget(m_fadeOutSpin, 5, 3); */ // Configure the empty final row to accomodate any extra vertical space. gridLayout->setRowStretch(gridLayout->numRows() - 1, 1); // Configure the empty final column to accomodate any extra horizontal // space. // gridLayout->setColStretch(gridLayout->numCols() - 1, 1); // populate the quantize combo // TQPixmap noMap = NotePixmapFactory::toTQPixmap(NotePixmapFactory::makeToolbarPixmap("menu-no-note")); for (unsigned int i = 0; i < m_standardQuantizations.size(); ++i) { timeT time = m_standardQuantizations[i]; timeT error = 0; TQString label = NotationStrings::makeNoteMenuLabel(time, true, error); TQPixmap pmap = NotePixmapFactory::toTQPixmap(NotePixmapFactory::makeNoteMenuPixmap(time, error)); m_quantizeValue->insertItem(error ? noMap : pmap, label); } m_quantizeValue->insertItem(noMap, i18n("Off")); // default to last item m_quantizeValue->setCurrentItem(m_quantizeValue->count() - 1); // populate the transpose combo // for (int i = -m_transposeRange; i < m_transposeRange + 1; i++) { m_transposeValue->insertItem(noMap, TQString("%1").arg(i)); if (i == 0) m_transposeValue->setCurrentItem(m_transposeValue->count() - 1); } m_delays.clear(); for (int i = 0; i < 6; i++) { timeT time = 0; if (i > 0 && i < 6) { time = Note(Note::Hemidemisemiquaver).getDuration() << (i - 1); } else if (i > 5) { time = Note(Note::Crotchet).getDuration() * (i - 4); } m_delays.push_back(time); // check if it's a valid note duration (it will be for the // time defn above, but if we were basing it on the sequencer // resolution it might not be) & include a note pixmap if so // timeT error = 0; TQString label = NotationStrings::makeNoteMenuLabel(time, true, error); TQPixmap pmap = NotePixmapFactory::toTQPixmap(NotePixmapFactory::makeNoteMenuPixmap(time, error)); m_delayValue->insertItem((error ? noMap : pmap), label); } for (int i = 0; i < 10; i++) { int rtd = (i < 5 ? ((i + 1) * 10) : ((i - 3) * 50)); m_realTimeDelays.push_back(rtd); m_delayValue->insertItem(i18n("%1 ms").arg(rtd)); } // set delay blank initially m_delayValue->setCurrentItem( -1); // populate m_colourValue slotDocColoursChanged(); //!!! disabled until after 1.3 // m_highButton->hide(); // m_lowButton->hide(); // m_rangeLabel->hide(); ////////////////////////////// } void SegmentParameterBox::setDocument(RosegardenGUIDoc* doc) { if (m_doc != 0) disconnect(m_doc, TQT_SIGNAL(docColoursChanged()), this, TQT_SLOT(slotDocColoursChanged())); m_doc = doc; // Detect when the document colours are updated connect (m_doc, TQT_SIGNAL(docColoursChanged()), this, TQT_SLOT(slotDocColoursChanged())); slotDocColoursChanged(); // repopulate combo } void SegmentParameterBox::useSegment(Segment *segment) { m_segments.clear(); m_segments.push_back(segment); populateBoxFromSegments(); } void SegmentParameterBox::useSegments(const SegmentSelection &segments) { m_segments.clear(); m_segments.resize(segments.size()); std::copy(segments.begin(), segments.end(), m_segments.begin()); populateBoxFromSegments(); } void SegmentParameterBox::slotDocColoursChanged() { RG_DEBUG << "SegmentParameterBox::slotDocColoursChanged()" << endl; m_colourValue->clear(); m_colourList.clear(); // Populate it from composition.m_segmentColourMap ColourMap temp = m_doc->getComposition().getSegmentColourMap(); unsigned int i = 0; for (RCMap::const_iterator it = temp.begin(); it != temp.end(); ++it) { TQString qtrunc(strtoqstr(it->second.second)); TQPixmap colour(15, 15); colour.fill(GUIPalette::convertColour(it->second.first)); if (qtrunc == "") { m_colourValue->insertItem(colour, i18n("Default"), i); } else { // truncate name to 15 characters to avoid the combo forcing the // whole kit and kaboodle too wide if (qtrunc.length() > 15) qtrunc = qtrunc.left(12) + "..."; m_colourValue->insertItem(colour, qtrunc, i); } m_colourList[it->first] = i; // maps colour number to menu index ++i; } m_addColourPos = i; m_colourValue->insertItem(i18n("Add New Color"), m_addColourPos); m_colourValue->setCurrentItem(0); } void SegmentParameterBox::update() { RG_DEBUG << "SegmentParameterBox::update()" << endl; populateBoxFromSegments(); } void SegmentParameterBox::segmentRemoved(const Composition *composition, Segment *segment) { if (composition == &m_doc->getComposition()) { for (std::vector::iterator it = m_segments.begin(); it != m_segments.end(); ++it) { if (*it == segment) { m_segments.erase(it); return ; } } } } void SegmentParameterBox::populateBoxFromSegments() { std::vector::iterator it; Tristate repeated = NotApplicable; Tristate quantized = NotApplicable; Tristate transposed = NotApplicable; Tristate delayed = NotApplicable; Tristate diffcolours = NotApplicable; Tristate highlow = NotApplicable; unsigned int myCol = 0; unsigned int myHigh = 127; unsigned int myLow = 0; timeT qntzLevel = 0; // At the moment we have no negative delay, so we use negative // values to represent real-time delay in ms timeT delayLevel = 0; int transposeLevel = 0; if (m_segments.size() == 0) m_label->setText(""); else m_label->setText(strtoqstr(m_segments[0]->getLabel())); for (it = m_segments.begin(); it != m_segments.end(); it++) { // ok, first thing is we know we have at least one segment if (repeated == NotApplicable) repeated = None; if (quantized == NotApplicable) quantized = None; if (transposed == NotApplicable) transposed = None; if (delayed == NotApplicable) delayed = None; if (diffcolours == NotApplicable) diffcolours = None; if (highlow == NotApplicable) highlow = None; // Set label to "*" when multiple labels don't match // if (strtoqstr((*it)->getLabel()) != m_label->text()) m_label->setText("*"); // Are all, some or none of the Segments repeating? if ((*it)->isRepeating()) { if (it == m_segments.begin()) repeated = All; else { if (repeated == None) repeated = Some; } } else { if (repeated == All) repeated = Some; } // Quantization // if ((*it)->hasQuantization()) { if (it == m_segments.begin()) { quantized = All; qntzLevel = (*it)->getQuantizer()->getUnit(); } else { // If quantize levels don't match if (quantized == None || (quantized == All && qntzLevel != (*it)->getQuantizer()->getUnit())) quantized = Some; } } else { if (quantized == All) quantized = Some; } // Transpose // if ((*it)->getTranspose() != 0) { if (it == m_segments.begin()) { transposed = All; transposeLevel = (*it)->getTranspose(); } else { if (transposed == None || (transposed == All && transposeLevel != (*it)->getTranspose())) transposed = Some; } } else { if (transposed == All) transposed = Some; } // Delay // timeT myDelay = (*it)->getDelay(); if (myDelay == 0) { myDelay = -((*it)->getRealTimeDelay().sec * 1000 + (*it)->getRealTimeDelay().msec()); } if (myDelay != 0) { if (it == m_segments.begin()) { delayed = All; delayLevel = myDelay; } else { if (delayed == None || (delayed == All && delayLevel != myDelay)) delayed = Some; } } else { if (delayed == All) delayed = Some; } // Colour if (it == m_segments.begin()) { myCol = (*it)->getColourIndex(); } else { if (myCol != (*it)->getColourIndex()) ; diffcolours = All; } // Highest/Lowest playable // if (it == m_segments.begin()) { myHigh = (*it)->getHighestPlayable(); myLow = (*it)->getLowestPlayable(); } else { if (myHigh != (*it)->getHighestPlayable() || myLow != (*it)->getLowestPlayable()) { highlow = All; } } } switch (repeated) { case All: m_repeatValue->setChecked(true); break; case Some: m_repeatValue->setNoChange(); break; case None: case NotApplicable: default: m_repeatValue->setChecked(false); break; } m_repeatValue->setEnabled(repeated != NotApplicable); switch (quantized) { case All: { for (unsigned int i = 0; i < m_standardQuantizations.size(); ++i) { if (m_standardQuantizations[i] == qntzLevel) { m_quantizeValue->setCurrentItem(i); break; } } } break; case Some: // Set the edit text to an unfeasible blank value meaning "Some" // m_quantizeValue->setCurrentItem( -1); break; // Assuming "Off" is always the last field case None: default: m_quantizeValue->setCurrentItem(m_quantizeValue->count() - 1); break; } m_quantizeValue->setEnabled(quantized != NotApplicable); switch (transposed) { // setCurrentItem works with TQStrings // 2nd arg of "true" means "add if necessary" case All: m_transposeValue-> setCurrentItem(TQString("%1").arg(transposeLevel), true); break; case Some: m_transposeValue->setCurrentItem(TQString(""), true); break; case None: default: m_transposeValue->setCurrentItem("0"); break; } m_transposeValue->setEnabled(transposed != NotApplicable); m_delayValue->blockSignals(true); switch (delayed) { case All: if (delayLevel >= 0) { timeT error = 0; TQString label = NotationStrings::makeNoteMenuLabel(delayLevel, true, error); m_delayValue->setCurrentItem(label, true); } else if (delayLevel < 0) { m_delayValue->setCurrentItem(i18n("%1 ms").arg( -delayLevel), true); } break; case Some: m_delayValue->setCurrentItem("", true); break; case None: default: m_delayValue->setCurrentItem(0); break; } m_delayValue->setEnabled(delayed != NotApplicable); m_delayValue->blockSignals(false); switch (diffcolours) { case None: if (m_colourList.find(myCol) != m_colourList.end()) m_colourValue->setCurrentItem(m_colourList[myCol]); else m_colourValue->setCurrentItem(0); break; case All: case NotApplicable: default: m_colourValue->setCurrentItem(0); break; } m_colourValue->setEnabled(diffcolours != NotApplicable); //!!! this is all borked up and useless; sort out after 1.3 /* switch (highlow) { case All: updateHighLow(); break; case Some: case None: default: m_highButton->setText(i18n("High: ---")); m_lowButton->setText(i18n("Low: ----")); highlow = NotApplicable; break; } m_highButton->setEnabled(highlow != NotApplicable); m_lowButton->setEnabled(highlow != NotApplicable); */ // Enable or disable the fade in/out params /* if (m_segments.size() == 1 && (*(m_segments.begin()))->getType() == Segment::Audio) { m_autoFadeBox->blockSignals(true); m_fadeInSpin->blockSignals(true); m_fadeOutSpin->blockSignals(true); ... !!! No, not setting up autofade widgets. The implementation's too incomplete to finish for this release. (Or for the next one after the one the previous comment referred to.) (Or for the one after the one after that. Will we ever get those working, or should Rich's final legacy simply be quietly disappeared?) m_fadeInLabel->show(); m_fadeInSpin->show(); m_fadeOutLabel->show(); m_fadeOutSpin->show(); instead: m_fadeInLabel->hide(); m_fadeInSpin->hide(); m_fadeOutLabel->hide(); m_fadeOutSpin->hide(); m_autoFadeLabel->setEnabled(true); m_autoFadeBox->setEnabled(true); m_fadeInLabel->setEnabled(true); m_fadeInSpin->setEnabled(true); m_fadeOutLabel->setEnabled(true); m_fadeOutSpin->setEnabled(true); Segment *seg = *(m_segments.begin()); int fadeInTime = seg->getFadeInTime().sec * 1000 + seg->getFadeInTime().msec(); m_fadeInSpin->setValue(fadeInTime); int fadeOutTime = seg->getFadeOutTime().sec * 1000 + seg->getFadeOutTime().msec(); m_fadeOutSpin->setValue(fadeOutTime); m_autoFadeBox->setChecked(seg->isAutoFading()); m_autoFadeBox->blockSignals(false); m_fadeInSpin->blockSignals(false); m_fadeOutSpin->blockSignals(false); } else { m_autoFadeLabel->setEnabled(false); m_autoFadeBox->setEnabled(false); m_fadeInLabel->setEnabled(false); m_fadeInSpin->setEnabled(false); m_fadeOutLabel->setEnabled(false); m_fadeOutSpin->setEnabled(false); m_autoFadeLabel->hide(); m_autoFadeBox->hide(); m_fadeInLabel->hide(); m_fadeInSpin->hide(); m_fadeOutLabel->hide(); m_fadeOutSpin->hide(); m_autoFadeBox->setChecked(false); m_fadeInSpin->setValue(0); m_fadeOutSpin->setValue(0); } */ } void SegmentParameterBox::slotRepeatPressed() { if (m_segments.size() == 0) return ; bool state = false; switch (m_repeatValue->state()) { case TQButton::Off: state = true; break; case TQButton::NoChange: case TQButton::On: default: state = false; break; } // update the check box and all current Segments m_repeatValue->setChecked(state); addCommandToHistory(new SegmentCommandRepeat(m_segments, state)); // std::vector::iterator it; // for (it = m_segments.begin(); it != m_segments.end(); it++) // (*it)->setRepeating(state); } void SegmentParameterBox::slotQuantizeSelected(int qLevel) { bool off = (qLevel == m_quantizeValue->count() - 1); SegmentChangeQuantizationCommand *command = new SegmentChangeQuantizationCommand (off ? 0 : m_standardQuantizations[qLevel]); std::vector::iterator it; for (it = m_segments.begin(); it != m_segments.end(); it++) { command->addSegment(*it); } addCommandToHistory(command); } void SegmentParameterBox::slotTransposeTextChanged(const TQString &text) { if (text.isEmpty() || m_segments.size() == 0) return ; int transposeValue = text.toInt(); // addCommandToHistory(new SegmentCommandChangeTransposeValue(m_segments, // transposeValue)); std::vector::iterator it; for (it = m_segments.begin(); it != m_segments.end(); it++) { (*it)->setTranspose(transposeValue); } emit documentModified(); } void SegmentParameterBox::slotTransposeSelected(int value) { slotTransposeTextChanged(m_transposeValue->text(value)); } void SegmentParameterBox::slotDelayTimeChanged(timeT delayValue) { // by convention and as a nasty hack, we use negative timeT here // to represent positive RealTime in ms if (delayValue > 0) { std::vector::iterator it; for (it = m_segments.begin(); it != m_segments.end(); it++) { (*it)->setDelay(delayValue); (*it)->setRealTimeDelay(RealTime::zeroTime); } } else if (delayValue < 0) { std::vector::iterator it; for (it = m_segments.begin(); it != m_segments.end(); it++) { (*it)->setDelay(0); int sec = ( -delayValue) / 1000; int nsec = (( -delayValue) - 1000 * sec) * 1000000; (*it)->setRealTimeDelay(RealTime(sec, nsec)); } } else { std::vector::iterator it; for (it = m_segments.begin(); it != m_segments.end(); it++) { (*it)->setDelay(0); (*it)->setRealTimeDelay(RealTime::zeroTime); } } emit documentModified(); } void SegmentParameterBox::slotDelayTextChanged(const TQString &text) { if (text.isEmpty() || m_segments.size() == 0) return ; slotDelayTimeChanged( -(text.toInt())); } void SegmentParameterBox::slotDelaySelected(int value) { if (value < int(m_delays.size())) { slotDelayTimeChanged(m_delays[value]); } else { slotDelayTimeChanged( -(m_realTimeDelays[value - m_delays.size()])); } } void SegmentParameterBox::slotColourSelected(int value) { if (value != m_addColourPos) { unsigned int temp = 0; ColourTable::ColourList::const_iterator pos; for (pos = m_colourList.begin(); pos != m_colourList.end(); ++pos) { if (pos->second == value) { temp = pos->first; break; } } SegmentSelection segments; std::vector::iterator it; for (it = m_segments.begin(); it != m_segments.end(); ++it) { segments.insert(*it); } SegmentColourCommand *command = new SegmentColourCommand(segments, temp); addCommandToHistory(command); } else { ColourMap newMap = m_doc->getComposition().getSegmentColourMap(); TQColor newColour; bool ok = false; TQString newName = KLineEditDlg::getText(i18n("New Color Name"), i18n("Enter new name"), i18n("New"), &ok); if ((ok == true) && (!newName.isEmpty())) { KColorDialog box(this, "", true); int result = box.getColor(newColour); if (result == KColorDialog::Accepted) { Colour newRColour = GUIPalette::convertColour(newColour); newMap.addItem(newRColour, qstrtostr(newName)); SegmentColourMapCommand *command = new SegmentColourMapCommand(m_doc, newMap); addCommandToHistory(command); slotDocColoursChanged(); } } // Else we don't do anything as they either didn't give a nameĀ· // or didn't give a colour } } void SegmentParameterBox::updateHighLow() { // Key of C major and NoAccidental means any "black key" notes will be // written as sharps. Accidental accidental = Accidentals::NoAccidental; Rosegarden::Key key = Rosegarden::Key("C major"); Pitch highest(m_highestPlayable, accidental); Pitch lowest(m_lowestPlayable, accidental); TDEConfig *config = kapp->config(); config->setGroup(GeneralOptionsConfigGroup); int base = config->readNumEntry("midipitchoctave", -2); //!!! FIXME this code is broken, and needs to be fixed after the fashion of //the TPB, but I'm not bothering with that at this time, because they are //going to be hidden for 1.3 anyway // m_highButton->setText(TQString("&High: %1%2").arg(highest.getNoteName(key)).arg(highest.getOctave(base))); // m_lowButton->setText(TQString("&Low: %1%2").arg(lowest.getNoteName(key)).arg(lowest.getOctave(base))); } void SegmentParameterBox::slotHighestPressed() { RG_DEBUG << "SegmentParameterBox::slotHighestPressed()" << endl; PitchPickerDialog dialog(0, m_highestPlayable, i18n("Highest playable note")); std::vector::iterator it; if (dialog.exec() == TQDialog::Accepted) { m_highestPlayable = dialog.getPitch(); updateHighLow(); for (it = m_segments.begin(); it != m_segments.end(); it++) { (*it)->setHighestPlayable(m_highestPlayable); } emit documentModified(); } } void SegmentParameterBox::slotLowestPressed() { RG_DEBUG << "SegmentParameterBox::slotLowestPressed()" << endl; PitchPickerDialog dialog(0, m_lowestPlayable, i18n("Lowest playable note")); std::vector::iterator it; if (dialog.exec() == TQDialog::Accepted) { m_lowestPlayable = dialog.getPitch(); updateHighLow(); for (it = m_segments.begin(); it != m_segments.end(); it++) { (*it)->setLowestPlayable(m_lowestPlayable); } emit documentModified(); } } MultiViewCommandHistory* SegmentParameterBox::getCommandHistory() { return m_doc->getCommandHistory(); } void SegmentParameterBox::addCommandToHistory(KCommand *command) { m_doc->getCommandHistory()->addCommand(command); } void SegmentParameterBox::slotEditSegmentLabel() { TQString editLabel; if (m_segments.size() == 0) return ; else if (m_segments.size() == 1) editLabel = i18n("Modify Segment label"); else editLabel = i18n("Modify Segments label"); bool ok = false; // Remove the asterisk if we're using it // TQString label = m_label->text(); if (label == "*") label = ""; TQString newLabel = KLineEditDlg::getText(editLabel, i18n("Enter new label"), m_label->text(), &ok, this); if (ok) { SegmentSelection segments; std::vector::iterator it; for (it = m_segments.begin(); it != m_segments.end(); ++it) segments.insert(*it); SegmentLabelCommand *command = new SegmentLabelCommand(segments, newLabel); addCommandToHistory(command); // fix #1776915, maybe? update(); } } void SegmentParameterBox::slotAudioFadeChanged(int value) { RG_DEBUG << "SegmentParameterBox::slotAudioFadeChanged - value = " << value << endl; /* if (m_segments.size() == 0) return ; bool state = false; if (value == TQButton::On) state = true; std::vector::iterator it; for (it = m_segments.begin(); it != m_segments.end(); it++) { (*it)->setAutoFade(state); } */ } void SegmentParameterBox::slotFadeInChanged(int value) { RG_DEBUG << "SegmentParameterBox::slotFadeInChanged - value = " << value << endl; /* if (m_segments.size() == 0) return ; if (value == 0 && m_fadeOutSpin->value() == 0) slotAudioFadeChanged(TQButton::Off); else slotAudioFadeChanged(TQButton::On); // Convert from ms // RealTime fadeInTime(value / 1000, (value % 1000) * 1000000); std::vector::iterator it; for (it = m_segments.begin(); it != m_segments.end(); it++) { (*it)->setFadeInTime(fadeInTime); } emit documentModified(); */ } void SegmentParameterBox::slotFadeOutChanged(int value) { RG_DEBUG << "SegmentParameterBox::slotFadeOutChanged - value = " << value << endl; /* if (m_segments.size() == 0) return ; if (value == 0 && m_fadeInSpin->value() == 0) slotAudioFadeChanged(TQButton::Off); else slotAudioFadeChanged(TQButton::On); // Convert from ms // RealTime fadeOutTime(value / 1000000, (value % 1000) * 10000000); std::vector::iterator it; for (it = m_segments.begin(); it != m_segments.end(); it++) { (*it)->setFadeOutTime(fadeOutTime); } emit documentModified(); */ } void SegmentParameterBox::showAdditionalControls(bool showThem) { //!!! disabled until after 1.3 /* m_highButton->setShown(showThem); m_lowButton->setShown(showThem); m_rangeLabel->setShown(showThem); */ } TQString SegmentParameterBox::getPreviousBox(RosegardenParameterArea::Arrangement arrangement) const { if (arrangement == RosegardenParameterArea::CLASSIC_STYLE) { return ""; } else { return i18n("Instrument"); } } } #include "SegmentParameterBox.moc"