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.
1213 lines
35 KiB
1213 lines
35 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 "SegmentParameterBox.h"
|
|
#include <tqlayout.h>
|
|
#include <tdeapplication.h>
|
|
|
|
#include <tdelocale.h>
|
|
#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 <kcolordialog.h>
|
|
#include <kcombobox.h>
|
|
#include <kcommand.h>
|
|
#include <tdeconfig.h>
|
|
#include <klineeditdlg.h>
|
|
#include <ktabwidget.h>
|
|
#include <tqbutton.h>
|
|
#include <tqcheckbox.h>
|
|
#include <tqcolor.h>
|
|
#include <tqdialog.h>
|
|
#include <tqfont.h>
|
|
#include <tqfontmetrics.h>
|
|
#include <tqframe.h>
|
|
#include <tqlabel.h>
|
|
#include <tqpixmap.h>
|
|
#include <tqpushbutton.h>
|
|
#include <tqscrollview.h>
|
|
#include <tqspinbox.h>
|
|
#include <tqstring.h>
|
|
#include <tqtooltip.h>
|
|
#include <tqvbox.h>
|
|
#include <tqwidget.h>
|
|
#include <tqwidgetstack.h>
|
|
|
|
|
|
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(), TQ_SIGNAL(commandExecuted()),
|
|
this, TQ_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, TQ_SIGNAL(released()),
|
|
TQ_SLOT(slotEditSegmentLabel()));
|
|
|
|
m_repeatValue = new TristateCheckBox(this);
|
|
m_repeatValue->setFont(font);
|
|
//m_repeatValue->setFixedHeight(comboHeight);
|
|
|
|
// handle state changes
|
|
connect(m_repeatValue, TQ_SIGNAL(pressed()), TQ_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, TQ_SIGNAL(activated(int)),
|
|
TQ_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, TQ_SIGNAL(activated(int)),
|
|
TQ_SLOT(slotTransposeSelected(int)));
|
|
|
|
// and text changes
|
|
connect(m_transposeValue, TQ_SIGNAL(textChanged(const TQString&)),
|
|
TQ_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, TQ_SIGNAL(activated(int)),
|
|
TQ_SLOT(slotDelaySelected(int)));
|
|
|
|
// Detect when the document colours are updated
|
|
connect(m_doc, TQ_SIGNAL(docColoursChanged()),
|
|
this, TQ_SLOT(slotDocColoursChanged()));
|
|
|
|
// handle text changes for delay
|
|
connect(m_delayValue, TQ_SIGNAL(textChanged(const TQString&)),
|
|
TQ_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, TQ_SIGNAL(activated(int)),
|
|
TQ_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, TQ_SIGNAL(released()),
|
|
// TQ_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, TQ_SIGNAL(released()),
|
|
// TQ_SLOT(slotLowestPressed()));
|
|
|
|
// Audio autofade enabled
|
|
//
|
|
// m_autoFadeBox = new TQCheckBox(this);
|
|
// connect(m_autoFadeBox, TQ_SIGNAL(stateChanged(int)),
|
|
// this, TQ_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, TQ_SIGNAL(valueChanged(int)),
|
|
// this, TQ_SLOT(slotFadeInChanged(int)));
|
|
|
|
// m_fadeOutSpin = new TQSpinBox(this);
|
|
// m_fadeOutSpin->setMinValue(0);
|
|
// m_fadeOutSpin->setMaxValue(5000);
|
|
// m_fadeOutSpin->setSuffix(i18n(" ms"));
|
|
// connect(m_fadeOutSpin, TQ_SIGNAL(valueChanged(int)),
|
|
// this, TQ_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, TQ_SIGNAL(docColoursChanged()),
|
|
this, TQ_SLOT(slotDocColoursChanged()));
|
|
|
|
m_doc = doc;
|
|
|
|
// Detect when the document colours are updated
|
|
connect (m_doc, TQ_SIGNAL(docColoursChanged()),
|
|
this, TQ_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<Segment*>::iterator it =
|
|
m_segments.begin(); it != m_segments.end(); ++it) {
|
|
|
|
if (*it == segment) {
|
|
m_segments.erase(it);
|
|
return ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
SegmentParameterBox::populateBoxFromSegments()
|
|
{
|
|
std::vector<Segment*>::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<Segment*>::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<Segment*>::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<Segment*>::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<Segment*>::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<Segment*>::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<Segment*>::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<Segment*>::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<Segment*>::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<Segment*>::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<Segment*>::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<Segment*>::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<Segment*>::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<Segment*>::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"
|