summaryrefslogtreecommitdiffstats
path: root/src/gui/dialogs/KeySignatureDialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/dialogs/KeySignatureDialog.cpp')
-rw-r--r--src/gui/dialogs/KeySignatureDialog.cpp402
1 files changed, 402 insertions, 0 deletions
diff --git a/src/gui/dialogs/KeySignatureDialog.cpp b/src/gui/dialogs/KeySignatureDialog.cpp
new file mode 100644
index 0000000..c703c0a
--- /dev/null
+++ b/src/gui/dialogs/KeySignatureDialog.cpp
@@ -0,0 +1,402 @@
+/* -*- 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 <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 <klocale.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 <qbuttongroup.h>
+#include <qgroupbox.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qobject.h>
+#include <qpixmap.h>
+#include <qradiobutton.h>
+#include <qstring.h>
+#include <qtooltip.h>
+#include <qvbox.h>
+#include <qwidget.h>
+#include <qcheckbox.h>
+#include <algorithm>
+
+namespace Rosegarden
+{
+
+KeySignatureDialog::KeySignatureDialog(QWidget *parent,
+ NotePixmapFactory *npf,
+ Clef clef,
+ Rosegarden::Key defaultKey,
+ bool showApplyToAll,
+ bool showConversionOptions,
+ QString 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");
+
+ QVBox *vbox = makeVBoxMainWidget();
+
+ QHBox *keyBox = 0;
+ QHBox *nameBox = 0;
+
+ QGroupBox *keyFrame = new QGroupBox
+ (1, Horizontal, i18n("Key signature"), vbox);
+
+ QGroupBox *transposeFrame = new QButtonGroup
+ (1, Horizontal, i18n("Key transposition"), vbox);
+
+ QGroupBox *buttonFrame = new QButtonGroup
+ (1, Horizontal, i18n("Scope"), vbox);
+
+ QButtonGroup *conversionFrame = new QButtonGroup
+ (1, Horizontal, i18n("Existing notes following key change"), vbox);
+
+ keyBox = new QHBox(keyFrame);
+ nameBox = new QHBox(keyFrame);
+
+ QLabel *explanatoryLabel = 0;
+ if (explanatoryText) {
+ explanatoryLabel = new QLabel(explanatoryText, keyFrame);
+ }
+
+ BigArrowButton *keyDown = new BigArrowButton(keyBox, Qt::LeftArrow);
+ QToolTip::add
+ (keyDown, i18n("Flatten"));
+
+ m_keyLabel = new QLabel(i18n("Key"), keyBox);
+ m_keyLabel->setAlignment(AlignVCenter | AlignHCenter);
+
+ BigArrowButton *keyUp = new BigArrowButton(keyBox, Qt::RightArrow);
+ QToolTip::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 QRadioButton(i18n("Transpose key according to segment transposition"),
+ transposeFrame);
+ QRadioButton *noTransposeButton =
+ new QRadioButton(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) {
+ QRadioButton *applyToOneButton =
+ new QRadioButton(i18n("Apply to current segment only"),
+ buttonFrame);
+ m_applyToAllButton =
+ new QRadioButton(i18n("Apply to all segments at this time"),
+ buttonFrame);
+ applyToOneButton->setChecked(true);
+ m_noPercussionCheckBox =
+ new QCheckBox(i18n("Exclude percussion segments"), buttonFrame);
+ m_noPercussionCheckBox->setChecked(true);
+
+ } else {
+ m_applyToAllButton = 0;
+ buttonFrame->hide();
+ }
+
+ if (showConversionOptions) {
+ m_noConversionButton =
+ new QRadioButton
+ (i18n("Maintain current pitches"), conversionFrame);
+ m_convertButton =
+ new QRadioButton
+ (i18n("Maintain current accidentals"), conversionFrame);
+ m_transposeButton =
+ new QRadioButton
+ (i18n("Transpose into this key"), conversionFrame);
+ m_noConversionButton->setChecked(true);
+ } else {
+ m_noConversionButton = 0;
+ m_convertButton = 0;
+ m_transposeButton = 0;
+ conversionFrame->hide();
+ }
+
+ QObject::connect(keyUp, SIGNAL(clicked()), this, SLOT(slotKeyUp()));
+ QObject::connect(keyDown, SIGNAL(clicked()), this, SLOT(slotKeyDown()));
+ QObject::connect(m_keyCombo, SIGNAL(activated(const QString &)),
+ this, SLOT(slotKeyNameChanged(const QString &)));
+ QObject::connect(m_keyCombo, SIGNAL(textChanged(const QString &)),
+ this, SLOT(slotKeyNameChanged(const QString &)));
+ QObject::connect(m_majorMinorCombo, SIGNAL(activated(const QString &)),
+ this, SLOT(slotMajorMinorChanged(const QString &)));
+}
+
+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;
+ QString 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) {
+
+ QString 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) {
+ QPixmap pmap =
+ NotePixmapFactory::toQPixmap(m_notePixmapFactory->makeKeyDisplayPixmap(m_key, m_clef));
+ m_keyLabel->setPixmap(pmap);
+ } else {
+ m_keyLabel->setText(i18n("No such key"));
+ }
+}
+
+void
+KeySignatureDialog::slotKeyNameChanged(const QString &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 QString &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 QString &s, bool minor)
+{
+ QString 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"