/* 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 "KeySignatureDialog.h" #include #include "misc/Strings.h" #include "base/NotationTypes.h" #include "gui/editors/notation/NotePixmapFactory.h" #include "gui/widgets/BigArrowButton.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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"