MuseScore/mscore/editdrumset.cpp
2016-04-13 11:35:21 +02:00

384 lines
14 KiB
C++

//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: editdrumset.cpp 5384 2012-02-27 12:21:49Z wschweer $
//
// Copyright (C) 2002-2007 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "editdrumset.h"
#include "musescore.h"
#include "libmscore/xml.h"
#include "libmscore/utils.h"
#include "libmscore/chord.h"
#include "libmscore/score.h"
#include "libmscore/note.h"
#include "libmscore/stem.h"
namespace Ms {
enum Column : char { PITCH, NOTE, SHORTCUT, NAME };
//---------------------------------------------------------
// noteHeadNames (see also libmscore/note.{h,cpp})
// same order as NoteHead::Group, "Sol" and "Alt. Brevis" omitted,
// as not being useful for drums
//---------------------------------------------------------
const char* noteHeadNames[int(NoteHead::Group::HEAD_GROUPS)] = {
QT_TRANSLATE_NOOP("EditDrumset", "Normal"),
QT_TRANSLATE_NOOP("EditDrumset", "Cross"),
QT_TRANSLATE_NOOP("EditDrumset", "Diamond"),
QT_TRANSLATE_NOOP("EditDrumset", "Triangle"),
QT_TRANSLATE_NOOP("EditDrumset", "Mi"),
QT_TRANSLATE_NOOP("EditDrumset", "Slash"),
QT_TRANSLATE_NOOP("EditDrumset", "XCircle"),
QT_TRANSLATE_NOOP("EditDrumset", "Do"),
QT_TRANSLATE_NOOP("EditDrumset", "Re"),
QT_TRANSLATE_NOOP("EditDrumset", "Fa"),
QT_TRANSLATE_NOOP("EditDrumset", "La"),
QT_TRANSLATE_NOOP("EditDrumset", "Ti"),
};
//---------------------------------------------------------
// EditDrumset
//---------------------------------------------------------
EditDrumset::EditDrumset(const Drumset* ds, QWidget* parent)
: QDialog(parent)
{
nDrumset = *ds;
setupUi(this);
setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
drumNote->setGrid(70, 80);
drumNote->setDrawGrid(false);
drumNote->setReadOnly(true);
updateList();
noteHead->addItem(tr("invalid"));
for (int i = 0; i < int(NoteHead::Group::HEAD_GROUPS) - 2 ; ++i)
noteHead->addItem(tr(noteHeadNames[i]));
connect(pitchList, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
SLOT(itemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
connect(buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(bboxClicked(QAbstractButton*)));
connect(name, SIGNAL(textChanged(const QString&)), SLOT(nameChanged(const QString&)));
connect(noteHead, SIGNAL(currentIndexChanged(int)), SLOT(valueChanged()));
connect(staffLine, SIGNAL(valueChanged(int)), SLOT(valueChanged()));
connect(voice, SIGNAL(currentIndexChanged(int)), SLOT(valueChanged()));
connect(stemDirection, SIGNAL(currentIndexChanged(int)), SLOT(valueChanged()));
connect(shortcut, SIGNAL(currentIndexChanged(int)), SLOT(shortcutChanged()));
connect(loadButton, SIGNAL(clicked()), SLOT(load()));
connect(saveButton, SIGNAL(clicked()), SLOT(save()));
}
//---------------------------------------------------------
// updateList
//---------------------------------------------------------
void EditDrumset::updateList()
{
pitchList->clear();
for (int i = 0; i < 128; ++i) {
QTreeWidgetItem* item = new QTreeWidgetItem(pitchList);
item->setText(Column::PITCH, QString("%1").arg(i));
item->setText(Column::NOTE, pitch2string(i));
if (nDrumset.shortcut(i) == 0)
item->setText(Column::SHORTCUT, "");
else {
QString s(QChar(nDrumset.shortcut(i)));
item->setText(Column::SHORTCUT, s);
}
item->setText(Column::NAME, qApp->translate("drumset", nDrumset.name(i).toUtf8().constData()));
item->setData(0, Qt::UserRole, i);
}
}
void EditDrumset::updateList2()
{
for (int i = 0; i < pitchList->topLevelItemCount(); ++i) {
QTreeWidgetItem* item = pitchList->topLevelItem(i);
int pitch = item->data(0, Qt::UserRole).toInt();
if (nDrumset.shortcut(pitch) == 0)
item->setText(Column::SHORTCUT, "");
else {
QString s(QChar(nDrumset.shortcut(pitch)));
item->setText(Column::SHORTCUT, s);
}
item->setText(Column::NAME, qApp->translate("drumset", nDrumset.name(pitch).toUtf8().constData()));
item->setData(0, Qt::UserRole, pitch);
}
}
//---------------------------------------------------------
// nameChanged
//---------------------------------------------------------
void EditDrumset::nameChanged(const QString& name)
{
QTreeWidgetItem* item = pitchList->currentItem();
if (item)
item->setText(Column::NAME, name);
}
//---------------------------------------------------------
// shortcutChanged
//---------------------------------------------------------
void EditDrumset::shortcutChanged()
{
QTreeWidgetItem* item = pitchList->currentItem();
if (!item)
return;
int pitch = item->data(Column::PITCH, Qt::UserRole).toInt();
int sc;
if (shortcut->currentIndex() == 7)
sc = 0;
else
sc = "ABCDEFG"[shortcut->currentIndex()];
if (QString(QChar(nDrumset.drum(pitch).shortcut)) != shortcut->currentText()) {
//
// remove conflicting shortcuts
//
for (int i = 0; i < DRUM_INSTRUMENTS; ++i) {
if (i == pitch)
continue;
if (nDrumset.drum(i).shortcut == sc)
nDrumset.drum(i).shortcut = 0;
}
nDrumset.drum(pitch).shortcut = sc;
if (shortcut->currentIndex() == 7)
item->setText(Column::SHORTCUT, "");
else
item->setText(Column::SHORTCUT, shortcut->currentText());
}
updateList2();
}
//---------------------------------------------------------
// bboxClicked
//---------------------------------------------------------
void EditDrumset::bboxClicked(QAbstractButton* button)
{
QDialogButtonBox::ButtonRole br = buttonBox->buttonRole(button);
switch(br) {
case QDialogButtonBox::ApplyRole:
apply();
break;
case QDialogButtonBox::AcceptRole:
apply();
// fall through
case QDialogButtonBox::RejectRole:
close();
break;
default:
qDebug("EditDrumSet: unknown button");
break;
}
}
//---------------------------------------------------------
// apply
//---------------------------------------------------------
void EditDrumset::apply()
{
valueChanged(); //save last changes in name
}
//---------------------------------------------------------
// itemChanged
//---------------------------------------------------------
void EditDrumset::itemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous)
{
if (previous) {
int pitch = previous->data(0, Qt::UserRole).toInt();
nDrumset.drum(pitch).name = name->text();
nDrumset.drum(pitch).notehead = NoteHead::Group(noteHead->currentIndex() - 1);
nDrumset.drum(pitch).line = staffLine->value();
nDrumset.drum(pitch).voice = voice->currentIndex();
if (shortcut->currentIndex() == 7)
nDrumset.drum(pitch).shortcut = 0;
else
nDrumset.drum(pitch).shortcut = "ABCDEFG"[shortcut->currentIndex()];
nDrumset.drum(pitch).stemDirection = Direction(stemDirection->currentIndex());
previous->setText(Column::NAME, qApp->translate("drumset", nDrumset.name(pitch).toUtf8().constData()));
}
if (current == 0)
return;
name->blockSignals(true);
staffLine->blockSignals(true);
voice->blockSignals(true);
stemDirection->blockSignals(true);
noteHead->blockSignals(true);
int pitch = current->data(0, Qt::UserRole).toInt();
name->setText(qApp->translate("drumset", nDrumset.name(pitch).toUtf8().constData()));
staffLine->setValue(nDrumset.line(pitch));
qDebug("BEFORE %d", nDrumset.voice(pitch));
voice->setCurrentIndex(nDrumset.voice(pitch));
qDebug("AFTER %d", nDrumset.voice(pitch));
stemDirection->setCurrentIndex(int(nDrumset.stemDirection(pitch)));
NoteHead::Group nh = nDrumset.noteHead(pitch);
noteHead->setCurrentIndex(int(nh) + 1);
if (nDrumset.shortcut(pitch) == 0)
shortcut->setCurrentIndex(7);
else
shortcut->setCurrentIndex(nDrumset.shortcut(pitch) - 'A');
name->blockSignals(false);
staffLine->blockSignals(false);
voice->blockSignals(false);
stemDirection->blockSignals(false);
noteHead->blockSignals(false);
updateExample();
}
//---------------------------------------------------------
// valueChanged
//---------------------------------------------------------
void EditDrumset::valueChanged()
{
if(!pitchList->currentItem())
return;
int pitch = pitchList->currentItem()->data(Column::PITCH, Qt::UserRole).toInt();
nDrumset.drum(pitch).name = name->text();
nDrumset.drum(pitch).notehead = NoteHead::Group(noteHead->currentIndex() - 1);
nDrumset.drum(pitch).line = staffLine->value();
nDrumset.drum(pitch).voice = voice->currentIndex();
nDrumset.drum(pitch).stemDirection = Direction(stemDirection->currentIndex());
if (QString(QChar(nDrumset.drum(pitch).shortcut)) != shortcut->currentText()) {
if (shortcut->currentText().isEmpty())
nDrumset.drum(pitch).shortcut = 0;
else
nDrumset.drum(pitch).shortcut = shortcut->currentText().at(0).toLatin1();
}
updateExample();
}
//---------------------------------------------------------
// updateExample
//---------------------------------------------------------
void EditDrumset::updateExample()
{
int pitch = pitchList->currentItem()->data(0, Qt::UserRole).toInt();
if (!nDrumset.isValid(pitch)) {
drumNote->add(0, 0, "");
return;
}
int line = nDrumset.line(pitch);
NoteHead::Group noteHead = nDrumset.noteHead(pitch);
int voice = nDrumset.voice(pitch);
Direction dir = nDrumset.stemDirection(pitch);
bool up;
if (dir == Direction::UP)
up = true;
else if (dir == Direction::DOWN)
up = false;
else
up = line > 4;
Chord* chord = new Chord(gscore);
chord->setDurationType(TDuration::DurationType::V_QUARTER);
chord->setStemDirection(dir);
chord->setTrack(voice);
chord->setUp(up);
Note* note = new Note(gscore);
note->setParent(chord);
note->setTrack(voice);
note->setPitch(pitch);
note->setTpcFromPitch();
note->setLine(line);
note->setPos(0.0, gscore->spatium() * .5 * line);
note->setHeadGroup(noteHead);
chord->add(note);
Stem* stem = new Stem(gscore);
stem->setLen((up ? -3.0 : 3.0) * gscore->spatium());
chord->add(stem);
stem->setPos(chord->stemPos());
drumNote->add(0, chord, qApp->translate("drumset", nDrumset.name(pitch).toUtf8().constData()));
}
//---------------------------------------------------------
// load
//---------------------------------------------------------
void EditDrumset::load()
{
QString name = mscore->getDrumsetFilename(true);
if (name.isEmpty())
return;
QFile fp(name);
if (!fp.open(QIODevice::ReadOnly))
return;
XmlReader e(&fp);
nDrumset.clear();
while (e.readNextStartElement()) {
if (e.name() == "museScore") {
while (e.readNextStartElement()) {
if (e.name() == "Drum")
nDrumset.load(e);
else
e.unknown();
}
}
}
fp.close();
updateList();
}
//---------------------------------------------------------
// save
//---------------------------------------------------------
void EditDrumset::save()
{
QString name = mscore->getDrumsetFilename(false);
if (name.isEmpty())
return;
QFile f(name);
if (!f.open(QIODevice::WriteOnly)) {
QString s = tr("Open File\n%1\nfailed: ")
+ QString(strerror(errno));
QMessageBox::critical(mscore, tr("MuseScore: Open File"), s.arg(f.fileName()));
return;
}
valueChanged(); //save last changes in name
Xml xml(&f);
xml.header();
xml.stag("museScore version=\"" MSC_VERSION "\"");
nDrumset.save(xml);
xml.etag();
if (f.error() != QFile::NoError) {
QString s = tr("Write File failed: ") + f.errorString();
QMessageBox::critical(this, tr("MuseScore: Write Drumset"), s);
}
}
}