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.
401 lines
11 KiB
401 lines
11 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 "KeySignatureDialog.h"
|
|
|
|
#include <tdelocale.h>
|
|
#include "misc/Strings.h"
|
|
#include "base/NotationTypes.h"
|
|
#include "gui/editors/notation/NotePixmapFactory.h"
|
|
#include "gui/widgets/BigArrowButton.h"
|
|
#include <kcombobox.h>
|
|
#include <kdialogbase.h>
|
|
#include <tqbuttongroup.h>
|
|
#include <tqgroupbox.h>
|
|
#include <tqhbox.h>
|
|
#include <tqlabel.h>
|
|
#include <tqobject.h>
|
|
#include <tqpixmap.h>
|
|
#include <tqradiobutton.h>
|
|
#include <tqstring.h>
|
|
#include <tqtooltip.h>
|
|
#include <tqvbox.h>
|
|
#include <tqwidget.h>
|
|
#include <tqcheckbox.h>
|
|
#include <algorithm>
|
|
|
|
namespace Rosegarden
|
|
{
|
|
|
|
KeySignatureDialog::KeySignatureDialog(TQWidget *parent,
|
|
NotePixmapFactory *npf,
|
|
Clef clef,
|
|
Rosegarden::Key defaultKey,
|
|
bool showApplyToAll,
|
|
bool showConversionOptions,
|
|
TQString explanatoryText) :
|
|
KDialogBase(parent, 0, true, i18n("Key Change"), Ok | Cancel | Help),
|
|
m_notePixmapFactory(npf),
|
|
m_key(defaultKey),
|
|
m_clef(clef),
|
|
m_valid(true),
|
|
m_ignoreComboChanges(false),
|
|
m_explanatoryLabel(0),
|
|
m_applyToAllButton(0),
|
|
m_noPercussionCheckBox(0)
|
|
{
|
|
setHelp("nv-signatures-key");
|
|
|
|
TQVBox *vbox = makeVBoxMainWidget();
|
|
|
|
TQHBox *keyBox = 0;
|
|
TQHBox *nameBox = 0;
|
|
|
|
TQGroupBox *keyFrame = new TQGroupBox
|
|
(1, TQt::Horizontal, i18n("Key signature"), vbox);
|
|
|
|
TQGroupBox *transposeFrame = new TQButtonGroup
|
|
(1, TQt::Horizontal, i18n("Key transposition"), vbox);
|
|
|
|
TQGroupBox *buttonFrame = new TQButtonGroup
|
|
(1, TQt::Horizontal, i18n("Scope"), vbox);
|
|
|
|
TQButtonGroup *conversionFrame = new TQButtonGroup
|
|
(1, TQt::Horizontal, i18n("Existing notes following key change"), vbox);
|
|
|
|
keyBox = new TQHBox(keyFrame);
|
|
nameBox = new TQHBox(keyFrame);
|
|
|
|
TQLabel *explanatoryLabel = 0;
|
|
if (!explanatoryText.isNull()) {
|
|
explanatoryLabel = new TQLabel(explanatoryText, keyFrame);
|
|
}
|
|
|
|
BigArrowButton *keyDown = new BigArrowButton(keyBox, TQt::LeftArrow);
|
|
TQToolTip::add
|
|
(keyDown, i18n("Flatten"));
|
|
|
|
m_keyLabel = new TQLabel(i18n("Key"), keyBox);
|
|
m_keyLabel->setAlignment(AlignVCenter | AlignHCenter);
|
|
|
|
BigArrowButton *keyUp = new BigArrowButton(keyBox, TQt::RightArrow);
|
|
TQToolTip::add
|
|
(keyUp, i18n("Sharpen"));
|
|
|
|
m_keyCombo = new KComboBox(nameBox);
|
|
m_majorMinorCombo = new KComboBox(nameBox);
|
|
m_majorMinorCombo->insertItem(i18n("Major"));
|
|
m_majorMinorCombo->insertItem(i18n("Minor"));
|
|
if (m_key.isMinor()) {
|
|
m_majorMinorCombo->setCurrentItem(m_majorMinorCombo->count() - 1);
|
|
}
|
|
|
|
regenerateKeyCombo();
|
|
redrawKeyPixmap();
|
|
m_explanatoryLabel = explanatoryLabel;
|
|
|
|
m_keyLabel->setMinimumWidth(m_keyLabel->pixmap()->width());
|
|
m_keyLabel->setMinimumHeight(m_keyLabel->pixmap()->height());
|
|
|
|
m_yesTransposeButton =
|
|
new TQRadioButton(i18n("Transpose key according to segment transposition"),
|
|
transposeFrame);
|
|
TQRadioButton *noTransposeButton =
|
|
new TQRadioButton(i18n("Use specified key. Do not transpose"), transposeFrame);
|
|
m_yesTransposeButton->setChecked(true);
|
|
|
|
// just to shut up the compiler warning about unused variable:
|
|
noTransposeButton->setChecked(false);
|
|
|
|
if (showApplyToAll) {
|
|
TQRadioButton *applyToOneButton =
|
|
new TQRadioButton(i18n("Apply to current segment only"),
|
|
buttonFrame);
|
|
m_applyToAllButton =
|
|
new TQRadioButton(i18n("Apply to all segments at this time"),
|
|
buttonFrame);
|
|
applyToOneButton->setChecked(true);
|
|
m_noPercussionCheckBox =
|
|
new TQCheckBox(i18n("Exclude percussion segments"), buttonFrame);
|
|
m_noPercussionCheckBox->setChecked(true);
|
|
|
|
} else {
|
|
m_applyToAllButton = 0;
|
|
buttonFrame->hide();
|
|
}
|
|
|
|
if (showConversionOptions) {
|
|
m_noConversionButton =
|
|
new TQRadioButton
|
|
(i18n("Maintain current pitches"), conversionFrame);
|
|
m_convertButton =
|
|
new TQRadioButton
|
|
(i18n("Maintain current accidentals"), conversionFrame);
|
|
m_transposeButton =
|
|
new TQRadioButton
|
|
(i18n("Transpose into this key"), conversionFrame);
|
|
m_noConversionButton->setChecked(true);
|
|
} else {
|
|
m_noConversionButton = 0;
|
|
m_convertButton = 0;
|
|
m_transposeButton = 0;
|
|
conversionFrame->hide();
|
|
}
|
|
|
|
TQObject::connect(keyUp, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotKeyUp()));
|
|
TQObject::connect(keyDown, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotKeyDown()));
|
|
TQObject::connect(m_keyCombo, TQ_SIGNAL(activated(const TQString &)),
|
|
this, TQ_SLOT(slotKeyNameChanged(const TQString &)));
|
|
TQObject::connect(m_keyCombo, TQ_SIGNAL(textChanged(const TQString &)),
|
|
this, TQ_SLOT(slotKeyNameChanged(const TQString &)));
|
|
TQObject::connect(m_majorMinorCombo, TQ_SIGNAL(activated(const TQString &)),
|
|
this, TQ_SLOT(slotMajorMinorChanged(const TQString &)));
|
|
}
|
|
|
|
KeySignatureDialog::ConversionType
|
|
|
|
KeySignatureDialog::getConversionType() const
|
|
{
|
|
if (m_noConversionButton && m_noConversionButton->isChecked()) {
|
|
return NoConversion;
|
|
} else if (m_convertButton && m_convertButton->isChecked()) {
|
|
return Convert;
|
|
} else if (m_transposeButton && m_transposeButton->isChecked()) {
|
|
return Transpose;
|
|
}
|
|
return NoConversion;
|
|
}
|
|
|
|
bool
|
|
KeySignatureDialog::shouldApplyToAll() const
|
|
{
|
|
return m_applyToAllButton && m_applyToAllButton->isChecked();
|
|
}
|
|
|
|
bool
|
|
KeySignatureDialog::shouldBeTransposed() const
|
|
{
|
|
return m_yesTransposeButton && m_yesTransposeButton->isChecked();
|
|
}
|
|
|
|
bool
|
|
KeySignatureDialog::shouldIgnorePercussion() const
|
|
{
|
|
return m_noPercussionCheckBox && m_noPercussionCheckBox->isChecked();
|
|
}
|
|
|
|
void
|
|
KeySignatureDialog::slotKeyUp()
|
|
{
|
|
bool sharp = m_key.isSharp();
|
|
int ac = m_key.getAccidentalCount();
|
|
if (ac == 0)
|
|
sharp = true;
|
|
if (sharp) {
|
|
if (++ac > 7)
|
|
ac = 7;
|
|
} else {
|
|
if (--ac < 1) {
|
|
ac = 0;
|
|
sharp = true;
|
|
}
|
|
}
|
|
|
|
try {
|
|
m_key = Rosegarden::Key(ac, sharp, m_key.isMinor());
|
|
setValid(true);
|
|
} catch (Rosegarden::Key::BadKeySpec s) {
|
|
std::cerr << s.getMessage() << std::endl;
|
|
setValid(false);
|
|
}
|
|
|
|
regenerateKeyCombo();
|
|
redrawKeyPixmap();
|
|
}
|
|
|
|
void
|
|
KeySignatureDialog::slotKeyDown()
|
|
{
|
|
bool sharp = m_key.isSharp();
|
|
int ac = m_key.getAccidentalCount();
|
|
if (ac == 0)
|
|
sharp = false;
|
|
if (sharp) {
|
|
if (--ac < 0) {
|
|
ac = 1;
|
|
sharp = false;
|
|
}
|
|
} else {
|
|
if (++ac > 7)
|
|
ac = 7;
|
|
}
|
|
|
|
try {
|
|
m_key = Rosegarden::Key(ac, sharp, m_key.isMinor());
|
|
setValid(true);
|
|
} catch (Rosegarden::Key::BadKeySpec s) {
|
|
std::cerr << s.getMessage() << std::endl;
|
|
setValid(false);
|
|
}
|
|
|
|
regenerateKeyCombo();
|
|
redrawKeyPixmap();
|
|
}
|
|
|
|
struct KeyNameComparator
|
|
{
|
|
bool operator()(const Rosegarden::Key &k1, const Rosegarden::Key &k2) {
|
|
return (k1.getName() < k2.getName());
|
|
}
|
|
};
|
|
|
|
|
|
void
|
|
KeySignatureDialog::regenerateKeyCombo()
|
|
{
|
|
if (m_explanatoryLabel)
|
|
m_explanatoryLabel->hide();
|
|
|
|
m_ignoreComboChanges = true;
|
|
TQString currentText = m_keyCombo->currentText();
|
|
Rosegarden::Key::KeyList keys(Rosegarden::Key::getKeys(m_key.isMinor()));
|
|
m_keyCombo->clear();
|
|
|
|
std::sort(keys.begin(), keys.end(), KeyNameComparator());
|
|
bool textSet = false;
|
|
|
|
for (Rosegarden::Key::KeyList::iterator i = keys.begin();
|
|
i != keys.end(); ++i) {
|
|
|
|
TQString name(strtoqstr(i->getName()));
|
|
int space = name.find(' ');
|
|
if (space > 0)
|
|
name = name.left(space);
|
|
|
|
m_keyCombo->insertItem(name);
|
|
|
|
if (m_valid && (*i == m_key)) {
|
|
m_keyCombo->setCurrentItem(m_keyCombo->count() - 1);
|
|
textSet = true;
|
|
}
|
|
}
|
|
|
|
if (!textSet) {
|
|
m_keyCombo->setEditText(currentText);
|
|
}
|
|
m_ignoreComboChanges = false;
|
|
}
|
|
|
|
bool
|
|
KeySignatureDialog::isValid() const
|
|
{
|
|
return m_valid;
|
|
}
|
|
|
|
Rosegarden::Key
|
|
KeySignatureDialog::getKey() const
|
|
{
|
|
return m_key;
|
|
}
|
|
|
|
void
|
|
KeySignatureDialog::redrawKeyPixmap()
|
|
{
|
|
if (m_valid) {
|
|
TQPixmap pmap =
|
|
NotePixmapFactory::toTQPixmap(m_notePixmapFactory->makeKeyDisplayPixmap(m_key, m_clef));
|
|
m_keyLabel->setPixmap(pmap);
|
|
} else {
|
|
m_keyLabel->setText(i18n("No such key"));
|
|
}
|
|
}
|
|
|
|
void
|
|
KeySignatureDialog::slotKeyNameChanged(const TQString &s)
|
|
{
|
|
if (m_ignoreComboChanges)
|
|
return ;
|
|
|
|
if (m_explanatoryLabel)
|
|
m_explanatoryLabel->hide();
|
|
|
|
std::string name(getKeyName(s, m_key.isMinor()));
|
|
|
|
try {
|
|
m_key = Rosegarden::Key(name);
|
|
setValid(true);
|
|
|
|
int space = name.find(' ');
|
|
if (space > 0)
|
|
name = name.substr(0, space);
|
|
m_keyCombo->setEditText(strtoqstr(name));
|
|
|
|
} catch (Rosegarden::Key::BadKeyName s) {
|
|
std::cerr << s.getMessage() << std::endl;
|
|
setValid(false);
|
|
}
|
|
|
|
redrawKeyPixmap();
|
|
}
|
|
|
|
void
|
|
KeySignatureDialog::slotMajorMinorChanged(const TQString &s)
|
|
{
|
|
if (m_ignoreComboChanges)
|
|
return ;
|
|
|
|
std::string name(getKeyName(m_keyCombo->currentText(), s == i18n("Minor")));
|
|
|
|
try {
|
|
m_key = Rosegarden::Key(name);
|
|
setValid(true);
|
|
} catch (Rosegarden::Key::BadKeyName s) {
|
|
std::cerr << s.getMessage() << std::endl;
|
|
setValid(false);
|
|
}
|
|
|
|
regenerateKeyCombo();
|
|
redrawKeyPixmap();
|
|
}
|
|
|
|
void
|
|
KeySignatureDialog::setValid(bool valid)
|
|
{
|
|
m_valid = valid;
|
|
enableButton(Ok, m_valid);
|
|
}
|
|
|
|
std::string
|
|
KeySignatureDialog::getKeyName(const TQString &s, bool minor)
|
|
{
|
|
TQString u((s.length() >= 1) ? (s.left(1).upper() + s.right(s.length() - 1))
|
|
: s);
|
|
|
|
std::string name(qstrtostr(u));
|
|
name = name + " " + (minor ? "minor" : "major");
|
|
return name;
|
|
}
|
|
|
|
}
|
|
#include "KeySignatureDialog.moc"
|