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.
194 lines
5.0 KiB
194 lines
5.0 KiB
/* -*- 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 "NoteStyleFileReader.h"
|
|
|
|
#include <string>
|
|
#include "NoteStyle.h"
|
|
#include <tqfileinfo.h>
|
|
#include <tqdir.h>
|
|
|
|
#include <kglobal.h>
|
|
#include <kstddirs.h>
|
|
#include <klocale.h>
|
|
|
|
#include "misc/Strings.h"
|
|
#include "NotationStrings.h"
|
|
#include "misc/Debug.h"
|
|
|
|
namespace Rosegarden {
|
|
|
|
|
|
NoteStyleFileReader::NoteStyleFileReader(std::string name) :
|
|
m_style(new NoteStyle(name)),
|
|
m_haveNote(false)
|
|
{
|
|
TQString styleDirectory =
|
|
KGlobal::dirs()->findResource("appdata", "styles/");
|
|
|
|
TQString styleFileName =
|
|
TQString("%1/%2.xml").arg(styleDirectory).arg(strtoqstr(name));
|
|
|
|
TQFileInfo fileInfo(styleFileName);
|
|
|
|
if (!fileInfo.isReadable()) {
|
|
throw StyleFileReadFailed
|
|
(qstrtostr(i18n("Can't open style file %1").arg(styleFileName)));
|
|
}
|
|
|
|
TQFile styleFile(styleFileName);
|
|
|
|
TQXmlInputSource source(styleFile);
|
|
TQXmlSimpleReader reader;
|
|
reader.setContentHandler(this);
|
|
reader.setErrorHandler(this);
|
|
bool ok = reader.parse(source);
|
|
styleFile.close();
|
|
|
|
if (!ok) {
|
|
throw StyleFileReadFailed(qstrtostr(m_errorString));
|
|
}
|
|
}
|
|
|
|
bool
|
|
NoteStyleFileReader::startElement(const TQString &, const TQString &,
|
|
const TQString &qName,
|
|
const TQXmlAttributes &attributes)
|
|
{
|
|
TQString lcName = qName.lower();
|
|
|
|
if (lcName == "rosegarden-note-style") {
|
|
|
|
TQString s = attributes.value("base-style");
|
|
if (!s.isNull()) m_style->setBaseStyle(qstrtostr(s));
|
|
|
|
} else if (lcName == "note") {
|
|
|
|
m_haveNote = true;
|
|
|
|
TQString s = attributes.value("type");
|
|
if (!s) {
|
|
m_errorString = i18n("type is a required attribute of note");
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
Note::Type type = NotationStrings::getNoteForName(s).getNoteType();
|
|
if (!setFromAttributes(type, attributes)) return false;
|
|
|
|
} catch (NotationStrings::MalformedNoteName n) {
|
|
m_errorString = i18n("Unrecognised note name %1").arg(s);
|
|
return false;
|
|
}
|
|
|
|
} else if (lcName == "global") {
|
|
|
|
if (m_haveNote) {
|
|
m_errorString = i18n("global element must precede note elements");
|
|
return false;
|
|
}
|
|
|
|
for (Note::Type type = Note::Shortest; type <= Note::Longest; ++type) {
|
|
if (!setFromAttributes(type, attributes)) return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool
|
|
NoteStyleFileReader::setFromAttributes(Note::Type type,
|
|
const TQXmlAttributes &attributes)
|
|
{
|
|
TQString s;
|
|
bool haveShape = false;
|
|
|
|
s = attributes.value("shape");
|
|
if (!s.isNull()) {
|
|
m_style->setShape(type, qstrtostr(s.lower()));
|
|
haveShape = true;
|
|
}
|
|
|
|
s = attributes.value("charname");
|
|
if (!s.isNull()) {
|
|
if (haveShape) {
|
|
m_errorString = i18n("global and note elements may have shape "
|
|
"or charname attribute, but not both");
|
|
return false;
|
|
}
|
|
m_style->setShape(type, NoteStyle::CustomCharName);
|
|
m_style->setCharName(type, qstrtostr(s));
|
|
}
|
|
|
|
s = attributes.value("filled");
|
|
if (!s.isNull()) m_style->setFilled(type, s.lower() == "true");
|
|
|
|
s = attributes.value("stem");
|
|
if (!s.isNull()) m_style->setStem(type, s.lower() == "true");
|
|
|
|
s = attributes.value("flags");
|
|
if (!s.isNull()) m_style->setFlagCount(type, s.toInt());
|
|
|
|
s = attributes.value("slashes");
|
|
if (!s.isNull()) m_style->setSlashCount(type, s.toInt());
|
|
|
|
NoteStyle::HFixPoint hfix;
|
|
NoteStyle::VFixPoint vfix;
|
|
m_style->getStemFixPoints(type, hfix, vfix);
|
|
bool haveHFix = false;
|
|
bool haveVFix = false;
|
|
|
|
s = attributes.value("hfixpoint");
|
|
if (!s.isNull()) {
|
|
s = s.lower();
|
|
haveHFix = true;
|
|
if (s == "normal") hfix = NoteStyle::Normal;
|
|
else if (s == "central") hfix = NoteStyle::Central;
|
|
else if (s == "reversed") hfix = NoteStyle::Reversed;
|
|
else haveHFix = false;
|
|
}
|
|
|
|
s = attributes.value("vfixpoint");
|
|
if (!s.isNull()) {
|
|
s = s.lower();
|
|
haveVFix = true;
|
|
if (s == "near") vfix = NoteStyle::Near;
|
|
else if (s == "middle") vfix = NoteStyle::Middle;
|
|
else if (s == "far") vfix = NoteStyle::Far;
|
|
else haveVFix = false;
|
|
}
|
|
|
|
if (haveHFix || haveVFix) {
|
|
m_style->setStemFixPoints(type, hfix, vfix);
|
|
// otherwise they inherit from base style, so avoid setting here
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
}
|
|
|