summaryrefslogtreecommitdiffstats
path: root/src/gui/editors/guitar
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 18:37:05 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 18:37:05 +0000
commit145364a8af6a1fec06556221e66d4b724a62fc9a (patch)
tree53bd71a544008c518034f208d64c932dc2883f50 /src/gui/editors/guitar
downloadrosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.tar.gz
rosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.zip
Added old abandoned KDE3 version of the RoseGarden MIDI tool
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/rosegarden@1097595 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/gui/editors/guitar')
-rw-r--r--src/gui/editors/guitar/Chord.cpp113
-rw-r--r--src/gui/editors/guitar/Chord.h106
-rw-r--r--src/gui/editors/guitar/ChordMap.cpp223
-rw-r--r--src/gui/editors/guitar/ChordMap.h87
-rw-r--r--src/gui/editors/guitar/ChordXmlHandler.cpp154
-rw-r--r--src/gui/editors/guitar/ChordXmlHandler.h78
-rw-r--r--src/gui/editors/guitar/Fingering.cpp152
-rw-r--r--src/gui/editors/guitar/Fingering.h95
-rw-r--r--src/gui/editors/guitar/FingeringBox.cpp293
-rw-r--r--src/gui/editors/guitar/FingeringBox.h106
-rw-r--r--src/gui/editors/guitar/FingeringListBoxItem.cpp36
-rw-r--r--src/gui/editors/guitar/FingeringListBoxItem.h46
-rw-r--r--src/gui/editors/guitar/GuitarChordEditorDialog.cpp109
-rw-r--r--src/gui/editors/guitar/GuitarChordEditorDialog.h67
-rw-r--r--src/gui/editors/guitar/GuitarChordSelectorDialog.cpp475
-rw-r--r--src/gui/editors/guitar/GuitarChordSelectorDialog.h120
-rw-r--r--src/gui/editors/guitar/NoteSymbols.cpp486
-rw-r--r--src/gui/editors/guitar/NoteSymbols.h192
18 files changed, 2938 insertions, 0 deletions
diff --git a/src/gui/editors/guitar/Chord.cpp b/src/gui/editors/guitar/Chord.cpp
new file mode 100644
index 0000000..23efe7d
--- /dev/null
+++ b/src/gui/editors/guitar/Chord.cpp
@@ -0,0 +1,113 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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 "Chord.h"
+#include "base/Event.h"
+
+#include <qstring.h>
+
+namespace Rosegarden
+{
+
+namespace Guitar
+{
+const std::string Chord::EventType = "guitarchord";
+const short Chord::EventSubOrdering = -60;
+const PropertyName Chord::RootPropertyName = "root";
+const PropertyName Chord::ExtPropertyName = "ext";
+const PropertyName Chord::FingeringPropertyName = "fingering";
+
+
+Chord::Chord()
+ : m_isUserChord(false)
+{
+}
+
+Chord::Chord(const QString& root, const QString& ext)
+ : m_root(root),
+ m_ext(ext),
+ m_isUserChord(false)
+{
+ if (m_ext.isEmpty())
+ m_ext = QString::null;
+}
+
+Chord::Chord(const Event& e)
+ : m_isUserChord(false)
+{
+ std::string f;
+ bool ok;
+
+ ok = e.get<String>(RootPropertyName, f);
+ if (ok)
+ m_root = f;
+
+ ok = e.get<String>(ExtPropertyName, f);
+ if (ok) {
+ if (f.length() == 0)
+ m_ext = QString::null;
+ else
+ m_ext = f;
+ }
+
+ ok = e.get<String>(FingeringPropertyName, f);
+ if (ok) {
+ QString qf(f);
+ QString errString;
+
+ Fingering fingering = Fingering::parseFingering(qf, errString);
+ setFingering(fingering);
+ }
+}
+
+Event* Chord::getAsEvent(timeT absoluteTime) const
+{
+ Event *e = new Event(EventType, absoluteTime, 0, EventSubOrdering);
+ e->set<String>(RootPropertyName, m_root);
+ e->set<String>(ExtPropertyName, m_ext);
+ e->set<String>(FingeringPropertyName, getFingering().toString());
+ return e;
+}
+
+const QRegExp Chord::ALT_BASS_REGEXP("/[A-G]");
+
+bool operator<(const Chord& a, const Chord& b)
+{
+ if (a.m_root != b.m_root) {
+ return a.m_root < b.m_root;
+ } else if (a.m_ext != b.m_ext) {
+ if (a.m_ext.isEmpty()) // chords with no ext need to be stored first
+ return true;
+ if (b.m_ext.isEmpty())
+ return false;
+ return a.m_ext < b.m_ext;
+ } else {
+ return a.m_fingering < b.m_fingering;
+ }
+
+}
+
+}
+
+}
diff --git a/src/gui/editors/guitar/Chord.h b/src/gui/editors/guitar/Chord.h
new file mode 100644
index 0000000..9e84cc3
--- /dev/null
+++ b/src/gui/editors/guitar/Chord.h
@@ -0,0 +1,106 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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.
+*/
+
+#ifndef _RG_CHORD_H_
+#define _RG_CHORD_H_
+
+#include "Fingering.h"
+#include "base/Event.h"
+#include "misc/Debug.h"
+
+#include <vector>
+#include <qstring.h>
+#include <qregexp.h>
+
+namespace Rosegarden
+{
+
+class Event;
+
+namespace Guitar
+{
+
+class Chord
+{
+ friend bool operator<(const Chord&, const Chord&);
+
+public:
+ static const std::string EventType;
+ static const short EventSubOrdering;
+ static const PropertyName RootPropertyName;
+ static const PropertyName ExtPropertyName;
+ static const PropertyName FingeringPropertyName;
+
+ Chord();
+ Chord(const QString& root, const QString& ext = QString::null);
+ Chord(const Event&);
+
+ Event* getAsEvent(timeT absoluteTime) const;
+
+ bool isEmpty() const { return m_root.isEmpty(); }
+ bool operator!() const { return !m_root; }
+
+ bool isUserChord() const { return m_isUserChord; }
+ void setUserChord(bool c) { m_isUserChord = c; }
+
+ QString getRoot() const { return m_root; }
+ void setRoot(QString r) { m_root = r; }
+
+ QString getExt() const { return m_ext; }
+ void setExt(QString r) { m_ext = r.isEmpty() ? QString::null : r; }
+
+ bool hasAltBass() const { return m_ext.contains(ALT_BASS_REGEXP); }
+
+ Fingering getFingering() const { return m_fingering; }
+ void setFingering(Fingering f) { m_fingering = f; }
+
+ struct ChordCmp
+ {
+ bool operator()(const Chord &e1, const Chord &e2) const {
+ return e1 < e2;
+ }
+ bool operator()(const Chord *e1, const Chord *e2) const {
+ return *e1 < *e2;
+ }
+ };
+
+protected:
+
+ static const QRegExp ALT_BASS_REGEXP;
+
+ QString m_root;
+ QString m_ext;
+
+ Fingering m_fingering;
+
+ bool m_isUserChord;
+};
+
+bool operator<(const Chord&, const Chord&);
+
+}
+
+}
+
+#endif /*_RG_CHORD2_H_*/
diff --git a/src/gui/editors/guitar/ChordMap.cpp b/src/gui/editors/guitar/ChordMap.cpp
new file mode 100644
index 0000000..06662d9
--- /dev/null
+++ b/src/gui/editors/guitar/ChordMap.cpp
@@ -0,0 +1,223 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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 "misc/Debug.h"
+#include "ChordMap.h"
+
+#include <qfile.h>
+#include <qtextstream.h>
+
+namespace Rosegarden
+{
+
+namespace Guitar
+{
+
+ChordMap::ChordMap()
+ : m_needSave(false)
+{
+}
+
+void ChordMap::insert(const Chord& c)
+{
+ m_map.insert(c);
+ m_needSave = true;
+}
+
+
+ChordMap::chordarray
+ChordMap::getChords(const QString& root, const QString& ext) const
+{
+ chordarray res;
+
+ Chord tmp(root, ext);
+ NOTATION_DEBUG << "ChordMap::getChords : chord = " << tmp << " - ext is empty : " << ext.isEmpty() << endl;
+
+ for (chordset::const_iterator i = m_map.lower_bound(tmp); i != m_map.end(); ++i) {
+ NOTATION_DEBUG << "ChordMap::getChords : checking chord " << *i << endl;
+
+ if (i->getRoot() != root)
+ break;
+
+ if (/* ext.isNull() || */ i->getExt() == ext) {
+ NOTATION_DEBUG << "ChordMap::getChords : adding chord " << *i << endl;
+ res.push_back(*i);
+ } else {
+ break;
+ }
+ }
+
+ return res;
+}
+
+QStringList
+ChordMap::getRootList() const
+{
+ static QStringList rootNotes;
+
+ if (rootNotes.count() == 0) {
+ rootNotes = QStringList::split(QString(","), "A,A#/Bb,B,C,C#/Db,D,D#/Eb,E,F,F#/Gb,G,G#/Ab");
+ }
+
+ // extract roots from map itself - not a very good idea
+ //
+// QString currentRoot;
+//
+// for(chordset::const_iterator i = m_map.begin(); i != m_map.end(); ++i) {
+// const Chord& chord = *i;
+// if (chord.getRoot() != currentRoot) {
+// rootNotes.push_back(chord.getRoot());
+// currentRoot = chord.getRoot();
+// }
+// }
+
+ return rootNotes;
+}
+
+QStringList
+ChordMap::getExtList(const QString& root) const
+{
+ QStringList extList;
+ QString currentExt = "ZZ";
+
+ Chord tmp(root);
+
+ for(chordset::const_iterator i = m_map.lower_bound(tmp); i != m_map.end(); ++i) {
+ const Chord& chord = *i;
+// NOTATION_DEBUG << "ChordMap::getExtList : chord = " << chord << endl;
+
+ if (chord.getRoot() != root)
+ break;
+
+ if (chord.getExt() != currentExt) {
+// NOTATION_DEBUG << "ChordMap::getExtList : adding ext " << chord.getExt() << " for root " << root << endl;
+ extList.push_back(chord.getExt());
+ currentExt = chord.getExt();
+ }
+ }
+
+ return extList;
+}
+
+void
+ChordMap::substitute(const Chord& oldChord, const Chord& newChord)
+{
+ remove(oldChord);
+ insert(newChord);
+}
+
+void
+ChordMap::remove(const Chord& c)
+{
+ m_map.erase(c);
+ m_needSave = true;
+}
+
+bool ChordMap::saveDocument(const QString& filename, bool userChordsOnly, QString& errMsg)
+{
+ QFile file(filename);
+ file.open(IO_WriteOnly);
+
+ QTextStream outStream(&file);
+
+ outStream.setEncoding(QTextStream::UnicodeUTF8);
+
+ outStream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ << "<!DOCTYPE rosegarden-chord-data>\n"
+ << "<rosegarden-chord-data version=\"" << VERSION
+ << "\" format-version-major=\"" << FILE_FORMAT_VERSION_MAJOR
+ << "\" format-version-minor=\"" << FILE_FORMAT_VERSION_MINOR
+ << "\" format-version-point=\"" << FILE_FORMAT_VERSION_POINT
+ << "\">\n";
+
+ outStream << "<chords>\n";
+
+ QString currentExt, currentRoot;
+
+ for(iterator i = begin(); i != end(); ++i) {
+ const Chord& chord = *i;
+
+ if (userChordsOnly && !chord.isUserChord())
+ continue; // skip non-user chords
+
+ if (chord.getRoot() != currentRoot) {
+
+ currentRoot = chord.getRoot();
+
+ // close current chordset (if there was one)
+ if (i != begin())
+ outStream << "\n</chordset>\n";
+
+ // open new chordset
+ outStream << "<chordset root=\"" << chord.getRoot() << "\">\n";
+ currentExt = "NEWEXT"; // to make sure we open a new chord right after that
+ }
+
+ if (chord.getExt() != currentExt) {
+
+ currentExt = chord.getExt();
+
+ // close current chord (if there was one)
+ if (i != begin())
+ outStream << "</chord>\n";
+
+ // open new chord
+ outStream << "<chord";
+ if (!chord.getExt().isEmpty())
+ outStream << " ext=\"" << chord.getExt() << "\"";
+ if (chord.isUserChord())
+ outStream << " user=\"true\"";
+
+ outStream << ">\n";
+ }
+
+ outStream << "<fingering>" << chord.getFingering().toString() << "</fingering>\n";
+ }
+
+ if (!m_map.empty())
+ outStream << "</chord>\n"; // close last written chord
+
+ outStream << "</chords>\n";
+ outStream << "</rosegarden-chord-data>\n";
+
+ return outStream.device()->status() == IO_Ok;
+}
+
+int ChordMap::FILE_FORMAT_VERSION_MAJOR = 1;
+int ChordMap::FILE_FORMAT_VERSION_MINOR = 0;
+int ChordMap::FILE_FORMAT_VERSION_POINT = 0;
+
+
+void
+ChordMap::debugDump() const
+{
+ for(chordset::const_iterator i = m_map.begin(); i != m_map.end(); ++i) {
+ Chord chord = *i;
+ NOTATION_DEBUG << "ChordMap::debugDump " << chord << endl;
+ }
+}
+
+}
+
+}
diff --git a/src/gui/editors/guitar/ChordMap.h b/src/gui/editors/guitar/ChordMap.h
new file mode 100644
index 0000000..5b7488d
--- /dev/null
+++ b/src/gui/editors/guitar/ChordMap.h
@@ -0,0 +1,87 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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.
+*/
+
+#ifndef _RG_CHORDMAP_H_
+#define _RG_CHORDMAP_H_
+
+#include "Chord.h"
+
+#include <qstringlist.h>
+#include <set>
+
+namespace Rosegarden
+{
+
+namespace Guitar
+{
+
+class ChordMap
+{
+ typedef std::set<Chord, Chord::ChordCmp> chordset;
+
+public:
+ typedef std::vector<Chord> chordarray;
+
+ typedef chordset::iterator iterator;
+ typedef chordset::const_iterator const_iterator;
+
+ static int FILE_FORMAT_VERSION_MAJOR;
+ static int FILE_FORMAT_VERSION_MINOR;
+ static int FILE_FORMAT_VERSION_POINT;
+
+ ChordMap();
+
+ void insert(const Chord&);
+ void substitute(const Chord& oldChord, const Chord& newChord);
+ void remove(const Chord&);
+
+ chordarray getChords(const QString& root, const QString& ext) const;
+
+ QStringList getRootList() const;
+ QStringList getExtList(const QString& root) const;
+
+ void debugDump() const;
+
+ bool needSave() const { return m_needSave; }
+ void clearNeedSave() { m_needSave = false; }
+
+ bool saveDocument(const QString& filename, bool userChordsOnly, QString& errMsg);
+
+ iterator begin() { return m_map.begin(); }
+ iterator end() { return m_map.end(); }
+ const_iterator begin() const { return m_map.begin(); }
+ const_iterator end() const { return m_map.end(); }
+
+protected:
+
+ chordset m_map;
+
+ bool m_needSave;
+};
+
+}
+
+}
+
+#endif /*_RG_CHORDMAP2_H_*/
diff --git a/src/gui/editors/guitar/ChordXmlHandler.cpp b/src/gui/editors/guitar/ChordXmlHandler.cpp
new file mode 100644
index 0000000..701c43c
--- /dev/null
+++ b/src/gui/editors/guitar/ChordXmlHandler.cpp
@@ -0,0 +1,154 @@
+// -*- c-basic-offset: 4 -*-
+
+/*
+ Rosegarden
+ A sequencer and musical notation editor.
+
+ This program is Copyright 2000-2008
+ Guillaume Laurent <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral right of the authors to claim authorship of this work
+ has been asserted.
+
+ 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 "ChordXmlHandler.h"
+#include "misc/Debug.h"
+
+namespace Rosegarden
+{
+
+ChordXmlHandler::ChordXmlHandler(Guitar::ChordMap& map)
+ : ProgressReporter(0),
+ m_chordMap(map)
+{
+}
+
+ChordXmlHandler::~ChordXmlHandler()
+{
+}
+
+bool ChordXmlHandler::startDocument()
+{
+ // nothing to do ?
+ return true;
+}
+
+bool ChordXmlHandler::startElement(const QString& namespaceURI,
+ const QString& localName,
+ const QString& qName,
+ const QXmlAttributes& atts)
+{
+ QString lcName = qName.lower();
+
+ if (lcName == "chordset") {
+ // start new chord set
+ m_currentRoot = atts.value("root").stripWhiteSpace();
+
+ } else if (lcName == "chord") {
+
+ m_currentChord = Guitar::Chord(m_currentRoot);
+
+ if (atts.index("ext") >= 0)
+ m_currentChord.setExt(atts.value("ext").stripWhiteSpace());
+
+ if (atts.index("user") >= 0) {
+ QString userVal = atts.value("user").stripWhiteSpace().lower();
+ bool res = (userVal == "yes" || userVal == "1" || userVal == "true");
+ m_currentChord.setUserChord(res);
+ } else {
+ m_currentChord.setUserChord(false);
+ }
+
+ } else if (lcName == "fingering") {
+ m_inFingering = true;
+ }
+
+ return true;
+}
+
+bool ChordXmlHandler::endElement(const QString& namespaceURI,
+ const QString& localName,
+ const QString& qName)
+{
+ QString lcName = qName.lower();
+
+ if (lcName == "fingering") {
+
+ m_inFingering = false;
+ m_chordMap.insert(m_currentChord);
+ NOTATION_DEBUG << "ChordXmlHandler::endElement (fingering) : adding chord " << m_currentChord << endl;
+
+ } else if (lcName == "chord") {
+
+ // adding is done after each parsing of fingering
+ //
+// m_chordMap.insert(m_currentChord);
+
+ }
+
+ return true;
+}
+
+bool ChordXmlHandler::characters(const QString& ch)
+{
+ QString ch2 = ch.simplifyWhiteSpace();
+
+ if (!ch2.isEmpty() && m_inFingering) {
+ if (!parseFingering(ch2))
+ return false;
+ }
+
+ return true;
+}
+
+bool ChordXmlHandler::endDocument()
+{
+ return true;
+}
+
+bool ChordXmlHandler::parseFingering(const QString& ch) {
+
+ QString errString;
+
+ Guitar::Fingering fingering = Guitar::Fingering::parseFingering(ch, errString);
+
+ if (m_errorString.isEmpty()) {
+ NOTATION_DEBUG << "ChordXmlHandler::parseFingering : fingering " << ch << endl;
+ m_currentChord.setFingering(fingering);
+ return true;
+ } else {
+ m_errorString = errString;
+ return false;
+ }
+}
+
+bool
+ChordXmlHandler::error(const QXmlParseException& exception)
+{
+ m_errorString = QString("%1 at line %2, column %3")
+ .arg(exception.message())
+ .arg(exception.lineNumber())
+ .arg(exception.columnNumber());
+ return QXmlDefaultHandler::error( exception );
+}
+
+bool
+ChordXmlHandler::fatalError(const QXmlParseException& exception)
+{
+ m_errorString = QString("%1 at line %2, column %3")
+ .arg(exception.message())
+ .arg(exception.lineNumber())
+ .arg(exception.columnNumber());
+ return QXmlDefaultHandler::fatalError( exception );
+}
+
+
+}
diff --git a/src/gui/editors/guitar/ChordXmlHandler.h b/src/gui/editors/guitar/ChordXmlHandler.h
new file mode 100644
index 0000000..ca25168
--- /dev/null
+++ b/src/gui/editors/guitar/ChordXmlHandler.h
@@ -0,0 +1,78 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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.
+*/
+
+
+#ifndef _RG_CHORDXMLHANDLER_H_
+#define _RG_CHORDXMLHANDLER_H_
+
+#include "gui/general/ProgressReporter.h"
+#include "Chord.h"
+#include "ChordMap.h"
+
+#include <qxml.h>
+
+
+namespace Rosegarden
+{
+
+class ChordXmlHandler : public ProgressReporter, public QXmlDefaultHandler
+{
+public:
+ ChordXmlHandler(Guitar::ChordMap&);
+ virtual ~ChordXmlHandler();
+
+ /// overloaded handler functions
+ virtual bool startDocument();
+ virtual bool startElement(const QString& namespaceURI,
+ const QString& localName,
+ const QString& qName,
+ const QXmlAttributes& atts);
+
+ virtual bool endElement(const QString& namespaceURI,
+ const QString& localName,
+ const QString& qName);
+
+ virtual bool characters(const QString& ch);
+
+ virtual bool endDocument ();
+
+ /// Return the error string set during the parsing (if any)
+ QString errorString() { return m_errorString; }
+ bool error(const QXmlParseException& exception);
+ bool fatalError(const QXmlParseException& exception);
+
+protected:
+
+ bool parseFingering(const QString& ch);
+
+ Guitar::Chord m_currentChord;
+ QString m_currentRoot;
+ QString m_errorString;
+ bool m_inFingering;
+ Guitar::ChordMap& m_chordMap;
+};
+
+}
+
+#endif /*_RG_CHORDXMLHANDLER_H_*/
diff --git a/src/gui/editors/guitar/Fingering.cpp b/src/gui/editors/guitar/Fingering.cpp
new file mode 100644
index 0000000..dd1edbd
--- /dev/null
+++ b/src/gui/editors/guitar/Fingering.cpp
@@ -0,0 +1,152 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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 "Fingering.h"
+
+#include "misc/Debug.h"
+
+#include <qstringlist.h>
+#include <sstream>
+#include <algorithm>
+#include <klocale.h>
+
+namespace Rosegarden
+{
+
+namespace Guitar
+{
+
+Fingering::Fingering(unsigned int nbStrings) :
+ m_strings(nbStrings, MUTED)
+{
+}
+
+Fingering::Fingering(QString s)
+{
+ QString errString;
+ Fingering t = parseFingering(s, errString);
+ m_strings = t.m_strings;
+}
+
+unsigned int
+Fingering::getStartFret() const
+{
+ int min = 999, max = 0;
+ for(std::vector<int>::const_iterator i = m_strings.begin(); i != m_strings.end(); ++i) {
+ if (*i < min && *i > 0)
+ min = *i;
+ if (*i > max)
+ max = *i;
+ }
+
+ if (max < 4)
+ min = 1;
+
+ return min == 999 ? 1 : min;
+}
+
+bool
+Fingering::hasBarre() const
+{
+ int lastStringStatus = m_strings[getNbStrings() - 1];
+
+ return ((m_strings[0] > OPEN && m_strings[0] == lastStringStatus) ||
+ (m_strings[1] > OPEN && m_strings[1] == lastStringStatus) ||
+ (m_strings[2] > OPEN && m_strings[2] == lastStringStatus));
+}
+
+Fingering::Barre
+Fingering::getBarre() const
+{
+ int lastStringStatus = m_strings[getNbStrings() - 1];
+
+ Barre res;
+
+ res.fret = lastStringStatus;
+
+ for(unsigned int i = 0; i < 3; ++i) {
+ if (m_strings[i] > OPEN && m_strings[i] == lastStringStatus)
+ res.start = i;
+ break;
+ }
+
+ res.end = 5;
+
+ return res;
+}
+
+Fingering
+Fingering::parseFingering(const QString& ch, QString& errorString)
+{
+ QStringList tokens = QStringList::split(' ', ch);
+
+ unsigned int idx = 0;
+ Fingering fingering;
+
+ for(QStringList::iterator i = tokens.begin(); i != tokens.end() && idx < fingering.getNbStrings(); ++i, ++idx) {
+ QString t = *i;
+ bool b = false;
+ unsigned int fn = t.toUInt(&b);
+ if (b) {
+// NOTATION_DEBUG << "Fingering::parseFingering : '" << t << "' = " << fn << endl;
+ fingering[idx] = fn;
+ } else if (t.lower() == "x") {
+// NOTATION_DEBUG << "Fingering::parseFingering : '" << t << "' = MUTED\n";
+ fingering[idx] = MUTED;
+ } else {
+ errorString = i18n("couldn't parse fingering '%1' in '%2'").arg(t).arg(ch);
+ }
+ }
+
+ return fingering;
+}
+
+
+std::string Fingering::toString() const
+{
+ std::stringstream s;
+
+ for(std::vector<int>::const_iterator i = m_strings.begin(); i != m_strings.end(); ++i) {
+ if (*i >= 0)
+ s << *i << ' ';
+ else
+ s << "x ";
+ }
+
+ return s.str();
+}
+
+bool operator<(const Fingering& a, const Fingering& b)
+{
+ for(unsigned int i = 0; i < Fingering::DEFAULT_NB_STRINGS; ++i) {
+ if (a.getStringStatus(i) != b.getStringStatus(i)) {
+ return a.getStringStatus(i) < b.getStringStatus(i);
+ }
+ }
+ return false;
+}
+
+}
+
+}
diff --git a/src/gui/editors/guitar/Fingering.h b/src/gui/editors/guitar/Fingering.h
new file mode 100644
index 0000000..41d9799
--- /dev/null
+++ b/src/gui/editors/guitar/Fingering.h
@@ -0,0 +1,95 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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.
+*/
+
+#ifndef _RG_FINGERING_H_
+#define _RG_FINGERING_H_
+
+#include <vector>
+#include <qstring.h>
+#include "base/Event.h"
+
+namespace Rosegarden
+{
+
+namespace Guitar
+{
+
+class Fingering
+{
+public:
+ friend bool operator<(const Fingering&, const Fingering&);
+
+ typedef std::vector<int>::iterator iterator;
+ typedef std::vector<int>::const_iterator const_iterator;
+
+ struct Barre {
+ unsigned int fret;
+ unsigned int start;
+ unsigned int end;
+ };
+
+ static const unsigned int DEFAULT_NB_STRINGS = 6;
+
+ Fingering(unsigned int nbStrings = DEFAULT_NB_STRINGS);
+ Fingering(QString);
+
+ enum { MUTED = -1, OPEN = 0 };
+
+ /**
+ * returns the fret number on which the string is pressed, or one of MUTED and OPEN
+ *
+ */
+ int getStringStatus(int stringNb) const { return m_strings[stringNb]; }
+ void setStringStatus(int stringNb, int status) { m_strings[stringNb] = status; }
+ unsigned int getStartFret() const;
+ unsigned int getNbStrings() const { return m_strings.size(); }
+
+ bool hasBarre() const;
+ Barre getBarre() const;
+
+ int operator[](int i) const { return m_strings[i]; }
+ int& operator[](int i) { return m_strings[i]; }
+
+ bool operator==(const Fingering& o) const { return m_strings == o.m_strings; }
+
+ iterator begin() { return m_strings.begin(); }
+ iterator end() { return m_strings.end(); }
+ const_iterator begin() const { return m_strings.begin(); }
+ const_iterator end() const { return m_strings.end(); }
+
+ static Fingering parseFingering(const QString&, QString& errorString);
+ std::string toString() const;
+
+protected:
+
+ std::vector<int> m_strings;
+};
+
+bool operator<(const Fingering&, const Fingering&);
+
+}
+
+}
+
+#endif /*_RG_FINGERING2_H_*/
diff --git a/src/gui/editors/guitar/FingeringBox.cpp b/src/gui/editors/guitar/FingeringBox.cpp
new file mode 100644
index 0000000..885ba83
--- /dev/null
+++ b/src/gui/editors/guitar/FingeringBox.cpp
@@ -0,0 +1,293 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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 "FingeringBox.h"
+#include "Fingering.h"
+
+#include "misc/Debug.h"
+
+namespace Rosegarden
+{
+
+FingeringBox::FingeringBox(unsigned int nbFrets, unsigned int nbStrings, bool editable, QWidget *parent, const char* name)
+ : QFrame(parent, name),
+ m_nbFretsDisplayed(nbFrets),
+ m_startFret(1),
+ m_nbStrings(nbStrings),
+ m_transientFretNb(0),
+ m_transientStringNb(0),
+ m_editable(editable),
+ m_noteSymbols(m_nbStrings, m_nbFretsDisplayed)
+{
+ init();
+}
+
+FingeringBox::FingeringBox(bool editable, QWidget *parent, const char* name)
+ : QFrame(parent, name),
+ m_nbFretsDisplayed(DEFAULT_NB_DISPLAYED_FRETS),
+ m_startFret(1),
+ m_nbStrings(Guitar::Fingering::DEFAULT_NB_STRINGS),
+ m_editable(editable),
+ m_noteSymbols(m_nbStrings, m_nbFretsDisplayed)
+{
+ init();
+}
+
+void
+FingeringBox::init()
+{
+ setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
+ setFixedSize(IMG_WIDTH, IMG_HEIGHT);
+ setBackgroundMode(PaletteBase);
+ if (m_editable)
+ setMouseTracking(true);
+
+}
+
+void
+FingeringBox::drawContents(QPainter* p)
+{
+// NOTATION_DEBUG << "FingeringBox::drawContents()" << endl;
+
+ // For all strings on guitar
+ // check state of string
+ // If pressed display note
+ // Else display muted or open symbol
+ // For all bars
+ // display bar
+ // Horizontal separator line
+
+ // draw guitar chord fingering
+ //
+ m_noteSymbols.drawFretNumber(p, m_startFret);
+ m_noteSymbols.drawFrets(p);
+ m_noteSymbols.drawStrings(p);
+
+ unsigned int stringNb = 0;
+
+ // draw notes
+ //
+ for (Guitar::Fingering::const_iterator pos = m_fingering.begin();
+ pos != m_fingering.end();
+ ++pos, ++stringNb) {
+
+ switch (*pos) {
+ case Guitar::Fingering::OPEN:
+// NOTATION_DEBUG << "Fingering::drawContents - drawing Open symbol on string " << stringNb << endl;
+ m_noteSymbols.drawOpenSymbol(p, stringNb);
+ break;
+
+ case Guitar::Fingering::MUTED:
+// NOTATION_DEBUG << "Fingering::drawContents - drawing Mute symbol on string" << stringNb << endl;
+ m_noteSymbols.drawMuteSymbol(p, stringNb);
+ break;
+
+ default:
+// NOTATION_DEBUG << "Fingering::drawContents - drawing note symbol at " << *pos << " on string " << stringNb << endl;
+ m_noteSymbols.drawNoteSymbol(p, stringNb, *pos - (m_startFret - 1), false);
+ break;
+ }
+ }
+
+ // TODO: detect barres and draw them in a special way ?
+
+ // draw transient note (visual feedback for mouse move)
+ //
+ if (hasMouse() &&
+ m_transientFretNb > 0 && m_transientFretNb <= m_nbFretsDisplayed &&
+ m_transientStringNb >= 0 && m_transientStringNb <= m_nbStrings) {
+ m_noteSymbols.drawNoteSymbol(p, m_transientStringNb, m_transientFretNb - (m_startFret - 1), true);
+ }
+
+ // DEBUG
+// p->save();
+// p->setPen(Qt::red);
+// unsigned int topBorderY = m_noteSymbols.getTopBorder(maximumHeight());
+// p->drawLine(0, topBorderY, 20, topBorderY);
+// p->drawRect(m_r1);
+// p->setPen(Qt::blue);
+// p->drawRect(m_r2);
+// p->restore();
+}
+
+void
+FingeringBox::setFingering(const Guitar::Fingering& f) {
+ m_fingering = f;
+ m_startFret = m_fingering.getStartFret();
+ update();
+}
+
+unsigned int
+FingeringBox::getStringNumber(const QPoint& pos)
+{
+ PositionPair result = m_noteSymbols.getStringNumber(maximumHeight(),
+ pos.x(),
+ m_nbStrings);
+ unsigned int stringNum = -1;
+
+ if(result.first){
+ stringNum = result.second;
+// RG_DEBUG << "FingeringBox::getStringNumber : res = " << stringNum << endl;
+ }
+
+ return stringNum;
+}
+
+unsigned int
+FingeringBox::getFretNumber(const QPoint& pos)
+{
+ unsigned int fretNum = 0;
+
+ if(true || pos.y() > m_noteSymbols.getTopBorder(maximumHeight())) {
+ // If fret position is below the top line of the guitar chord image.
+ PositionPair result = m_noteSymbols.getFretNumber(maximumWidth(),
+ pos.y(),
+ m_nbFretsDisplayed);
+
+ if(result.first) {
+ fretNum = result.second + (m_startFret - 1);
+// RG_DEBUG << "FingeringBox::getFretNumber : res = " << fretNum << " startFret = " << m_startFret << endl;
+ } else {
+// RG_DEBUG << "FingeringBox::getFretNumber : no res\n";
+ }
+ }
+
+ return fretNum;
+}
+
+void
+FingeringBox::mousePressEvent(QMouseEvent *event)
+{
+ if (!m_editable)
+ return;
+
+ if((event->button() == LeftButton) && m_editable) {
+
+ // Find string position
+ m_press_string_num = getStringNumber(event->pos());
+
+ // Find fret position
+ m_press_fret_num = getFretNumber(event->pos());
+ }
+}
+
+void
+FingeringBox::mouseReleaseEvent(QMouseEvent *event)
+{
+ if(!m_editable)
+ return ;
+
+ unsigned int release_string_num = getStringNumber(event->pos());
+ unsigned int release_fret_num = getFretNumber(event->pos());
+
+ processMouseRelease(release_string_num, release_fret_num);
+}
+
+void
+FingeringBox::processMouseRelease(unsigned int release_string_num,
+ unsigned int release_fret_num)
+{
+ if(m_press_fret_num == release_fret_num) {
+ // If press string & fret pos == release string & fret position, display chord
+ if(m_press_string_num == release_string_num) {
+
+ if(m_press_fret_num < (m_startFret + m_nbFretsDisplayed)) {
+
+ unsigned int aVal = m_press_fret_num;
+
+ if(m_press_fret_num == 0) {
+
+ int stringStatus = m_fingering.getStringStatus(m_press_string_num);
+
+ if (stringStatus == Guitar::Fingering::OPEN)
+ aVal = Guitar::Fingering::MUTED;
+ else if (stringStatus > Guitar::Fingering::OPEN)
+ aVal = Guitar::Fingering::OPEN;
+
+ }
+
+ m_fingering.setStringStatus(m_press_string_num, aVal);
+
+ update();
+ }
+ }
+ // else if press fret pos == release fret pos & press string pos != release string pos, display bar
+ else {
+ if(((m_press_string_num > 0)&&(release_string_num > 0)) &&
+ (( m_press_string_num <= m_nbStrings)&&
+ (release_string_num <= m_nbStrings)) &&
+ (( m_press_fret_num <(m_startFret + m_nbFretsDisplayed)) &&
+ (release_fret_num <(m_startFret + m_nbFretsDisplayed)))) {
+
+ // TODO deal with barre later on
+
+ }
+ }
+ }
+}
+
+
+void
+FingeringBox::mouseMoveEvent( QMouseEvent *event )
+{
+ if (!m_editable)
+ return;
+
+ unsigned int transientStringNb = getStringNumber(event->pos());
+ unsigned int transientFretNb = getFretNumber(event->pos());
+
+ if (transientStringNb != m_transientStringNb ||
+ transientFretNb != m_transientFretNb) {
+
+ QRect r1 = m_noteSymbols.getTransientNoteSymbolRect(size(),
+ m_transientStringNb,
+ m_transientFretNb - (m_startFret - 1));
+ m_transientStringNb = transientStringNb;
+ m_transientFretNb = transientFretNb;
+ QRect r2 = m_noteSymbols.getTransientNoteSymbolRect(size(),
+ m_transientStringNb,
+ m_transientFretNb - (m_startFret - 1));
+
+ m_r1 = r1;
+ m_r2 = r2;
+
+// RG_DEBUG << "Fingering::updateTransientPos r1 = " << r1 << " - r2 = " << r2 << endl;
+
+// QRect updateRect = r1 | r2;
+// update(updateRect);
+
+ update();
+
+ }
+
+}
+
+void
+FingeringBox::leaveEvent(QEvent*)
+{
+ update();
+}
+
+}
diff --git a/src/gui/editors/guitar/FingeringBox.h b/src/gui/editors/guitar/FingeringBox.h
new file mode 100644
index 0000000..b54c0a8
--- /dev/null
+++ b/src/gui/editors/guitar/FingeringBox.h
@@ -0,0 +1,106 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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.
+*/
+
+
+
+#ifndef _RG_FINGERINGBOX_H_
+#define _RG_FINGERINGBOX_H_
+
+#include <qframe.h>
+
+#include "NoteSymbols.h"
+#include "Fingering.h"
+
+namespace Rosegarden
+{
+
+class Fingering;
+
+class FingeringBox : public QFrame
+{
+ static const unsigned int IMG_WIDTH = 200;
+ static const unsigned int IMG_HEIGHT = 200;
+
+public:
+ FingeringBox(unsigned int nbFrets, unsigned int nbStrings, bool editable, QWidget *parent, const char* name = 0);
+ FingeringBox(bool editable, QWidget *parent, const char* name = 0);
+
+ void setStartFret(unsigned int f) { m_startFret = f; update(); }
+ unsigned int getStartFret() const { return m_startFret; }
+
+ void setFingering(const Guitar::Fingering&);
+ const Guitar::Fingering& getFingering() { return m_fingering; }
+
+ const Guitar::NoteSymbols& getNoteSymbols() const { return m_noteSymbols; }
+
+ static const unsigned int DEFAULT_NB_DISPLAYED_FRETS = 4;
+
+protected:
+ void init();
+
+ virtual void drawContents(QPainter*);
+
+ virtual void mousePressEvent(QMouseEvent*);
+ virtual void mouseReleaseEvent(QMouseEvent*);
+ virtual void mouseMoveEvent(QMouseEvent*);
+ virtual void leaveEvent(QEvent*);
+
+ void processMouseRelease( unsigned int release_string_num, unsigned int release_fret_num);
+
+ typedef std::pair<bool, unsigned int> PositionPair;
+
+ unsigned int getStringNumber(const QPoint&);
+
+ unsigned int getFretNumber(const QPoint&);
+
+ //! Maximum number of frets displayed by FingeringBox
+ unsigned int m_nbFretsDisplayed;
+
+ unsigned int m_startFret;
+
+ unsigned int m_nbStrings;
+
+ unsigned int m_transientFretNb;
+ unsigned int m_transientStringNb;
+
+ //! Present mode
+ bool m_editable;
+
+ //! Handle to the present fingering
+ Guitar::Fingering m_fingering;
+
+ //! String number where a mouse press event was located
+ unsigned int m_press_string_num;
+
+ //! Fret number where a mouse press event was located
+ unsigned int m_press_fret_num;
+
+ Guitar::NoteSymbols m_noteSymbols;
+
+ QRect m_r1, m_r2;
+};
+
+}
+
+#endif /*_RG_FINGERINGBOX2_H_*/
diff --git a/src/gui/editors/guitar/FingeringListBoxItem.cpp b/src/gui/editors/guitar/FingeringListBoxItem.cpp
new file mode 100644
index 0000000..31b92e9
--- /dev/null
+++ b/src/gui/editors/guitar/FingeringListBoxItem.cpp
@@ -0,0 +1,36 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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 "FingeringListBoxItem.h"
+
+namespace Rosegarden {
+
+FingeringListBoxItem::FingeringListBoxItem(const Guitar::Chord& chord, QListBox* parent, QPixmap pixmap, QString fingeringString)
+ : QListBoxPixmap(parent, pixmap, fingeringString),
+ m_chord(chord)
+{
+}
+
+}
diff --git a/src/gui/editors/guitar/FingeringListBoxItem.h b/src/gui/editors/guitar/FingeringListBoxItem.h
new file mode 100644
index 0000000..b7625e2
--- /dev/null
+++ b/src/gui/editors/guitar/FingeringListBoxItem.h
@@ -0,0 +1,46 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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.
+*/
+
+
+#ifndef _RG_FINGERINGLISTBOXITEM_H_
+#define _RG_FINGERINGLISTBOXITEM_H_
+
+#include <qlistbox.h>
+#include "Chord.h"
+
+namespace Rosegarden {
+
+class FingeringListBoxItem : public QListBoxPixmap
+{
+public:
+ FingeringListBoxItem(const Guitar::Chord& chord, QListBox* parent, QPixmap pixmap, QString fingeringString);
+
+ const Guitar::Chord& getChord() { return m_chord; }
+protected:
+ Guitar::Chord m_chord;
+};
+
+}
+
+#endif /*_RG_FINGERINGLISTBOXITEM_H_*/
diff --git a/src/gui/editors/guitar/GuitarChordEditorDialog.cpp b/src/gui/editors/guitar/GuitarChordEditorDialog.cpp
new file mode 100644
index 0000000..60da8b6
--- /dev/null
+++ b/src/gui/editors/guitar/GuitarChordEditorDialog.cpp
@@ -0,0 +1,109 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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 "GuitarChordEditorDialog.h"
+#include "FingeringBox.h"
+#include "Chord.h"
+#include "ChordMap.h"
+
+#include <klineedit.h>
+#include <qcombobox.h>
+#include <qspinbox.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstddirs.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+namespace Rosegarden
+{
+
+GuitarChordEditorDialog::GuitarChordEditorDialog(Guitar::Chord& chord, const Guitar::ChordMap& chordMap, QWidget *parent)
+ : KDialogBase(parent, "GuitarChordEditor", true, i18n("Guitar Chord Editor"), Ok|Cancel),
+ m_chord(chord),
+ m_chordMap(chordMap)
+{
+ QWidget *page = new QWidget(this);
+ setMainWidget(page);
+ QGridLayout *topLayout = new QGridLayout(page, 7, 2, spacingHint());
+
+ topLayout->addWidget(new QLabel(i18n("Start fret"), page), 0, 1);
+ m_startFret = new QSpinBox(1, 24, 1, page);
+ topLayout->addWidget(m_startFret, 1, 1);
+
+ connect(m_startFret, SIGNAL(valueChanged(int)),
+ this, SLOT(slotStartFretChanged(int)));
+
+ topLayout->addWidget(new QLabel(i18n("Root"), page), 2, 1);
+ m_rootNotesList = new QComboBox(page);
+ topLayout->addWidget(m_rootNotesList, 3, 1);
+
+ topLayout->addWidget(new QLabel(i18n("Extension"), page), 4, 1);
+ m_ext = new QComboBox(true, page);
+ topLayout->addWidget(m_ext, 5, 1);
+
+ topLayout->addItem(new QSpacerItem(1, 1), 6, 1);
+
+ m_fingeringBox = new FingeringBox(true, page);
+ m_fingeringBox->setFingering(m_chord.getFingering());
+ topLayout->addMultiCellWidget(m_fingeringBox, 0, 7, 0, 0);
+
+ NOTATION_DEBUG << "GuitarChordEditorDialog : chord = " << m_chord << endl;
+
+
+ QStringList rootList = m_chordMap.getRootList();
+ if (rootList.count() > 0) {
+ m_rootNotesList->insertStringList(rootList);
+ m_rootNotesList->setCurrentItem(rootList.findIndex(m_chord.getRoot()));
+ }
+
+ QStringList extList = m_chordMap.getExtList(m_chord.getRoot());
+ if (extList.count() > 0) {
+ m_ext->insertStringList(extList);
+ m_ext->setCurrentItem(extList.findIndex(m_chord.getExt()));
+ }
+
+}
+
+void
+GuitarChordEditorDialog::slotStartFretChanged(int startFret)
+{
+ m_fingeringBox->setStartFret(startFret);
+}
+
+void
+GuitarChordEditorDialog::slotOk()
+{
+ m_chord.setFingering(m_fingeringBox->getFingering());
+ m_chord.setExt(m_ext->currentText());
+ m_chord.setRoot(m_rootNotesList->currentText());
+ m_chord.setUserChord(true);
+ KDialogBase::slotOk();
+}
+
+
+}
+
+#include "GuitarChordEditorDialog.moc"
+
diff --git a/src/gui/editors/guitar/GuitarChordEditorDialog.h b/src/gui/editors/guitar/GuitarChordEditorDialog.h
new file mode 100644
index 0000000..fc01605
--- /dev/null
+++ b/src/gui/editors/guitar/GuitarChordEditorDialog.h
@@ -0,0 +1,67 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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.
+*/
+
+#ifndef _RG_GUITARCHORDEDITOR2_H_
+#define _RG_GUITARCHORDEDITOR2_H_
+
+#include <kdialogbase.h>
+
+#include "Chord.h"
+#include "ChordMap.h"
+
+class QComboBox;
+class QSpinBox;
+
+namespace Rosegarden
+{
+
+class FingeringBox;
+
+
+class GuitarChordEditorDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ GuitarChordEditorDialog(Guitar::Chord&, const Guitar::ChordMap& chordMap, QWidget *parent=0);
+
+protected slots:
+ void slotStartFretChanged(int);
+ virtual void slotOk();
+
+protected:
+
+ void populateExtensions(const QStringList&);
+
+ FingeringBox* m_fingeringBox;
+ QComboBox* m_rootNotesList;
+ QSpinBox* m_startFret;
+ QComboBox* m_ext;
+ Guitar::Chord& m_chord;
+ const Guitar::ChordMap& m_chordMap;
+};
+
+}
+
+#endif /*_RG_GUITARCHORDEDITOR2_H_*/
diff --git a/src/gui/editors/guitar/GuitarChordSelectorDialog.cpp b/src/gui/editors/guitar/GuitarChordSelectorDialog.cpp
new file mode 100644
index 0000000..bd62c1f
--- /dev/null
+++ b/src/gui/editors/guitar/GuitarChordSelectorDialog.cpp
@@ -0,0 +1,475 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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 "GuitarChordSelectorDialog.h"
+#include "GuitarChordEditorDialog.h"
+#include "ChordXmlHandler.h"
+#include "FingeringBox.h"
+#include "FingeringListBoxItem.h"
+
+#include "misc/Debug.h"
+#include <qlistbox.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstddirs.h>
+
+namespace Rosegarden
+{
+
+GuitarChordSelectorDialog::GuitarChordSelectorDialog(QWidget *parent)
+ : KDialogBase(parent, "GuitarChordSelector", true, i18n("Guitar Chord Selector"), Ok|Cancel)
+{
+ QWidget *page = new QWidget(this);
+ setMainWidget(page);
+ QGridLayout *topLayout = new QGridLayout(page, 3, 4, spacingHint());
+
+ topLayout->addWidget(new QLabel(i18n("Root"), page), 0, 0);
+ m_rootNotesList = new QListBox(page);
+ topLayout->addWidget(m_rootNotesList, 1, 0);
+
+ topLayout->addWidget(new QLabel(i18n("Extension"), page), 0, 1);
+ m_chordExtList = new QListBox(page);
+ topLayout->addWidget(m_chordExtList, 1, 1);
+
+ m_newFingeringButton = new QPushButton(i18n("New"), page);
+ m_deleteFingeringButton = new QPushButton(i18n("Delete"), page);
+ m_editFingeringButton = new QPushButton(i18n("Edit"), page);
+
+ m_chordComplexityCombo = new QComboBox(page);
+ m_chordComplexityCombo->insertItem(i18n("beginner"));
+ m_chordComplexityCombo->insertItem(i18n("common"));
+ m_chordComplexityCombo->insertItem(i18n("all"));
+
+ connect(m_chordComplexityCombo, SIGNAL(activated(int)),
+ this, SLOT(slotComplexityChanged(int)));
+
+ QVBoxLayout* vboxLayout = new QVBoxLayout(page, 5);
+ topLayout->addMultiCellLayout(vboxLayout, 1, 3, 2, 2);
+ vboxLayout->addWidget(m_chordComplexityCombo);
+ vboxLayout->addStretch(10);
+ vboxLayout->addWidget(m_newFingeringButton);
+ vboxLayout->addWidget(m_deleteFingeringButton);
+ vboxLayout->addWidget(m_editFingeringButton);
+
+ connect(m_newFingeringButton, SIGNAL(clicked()),
+ this, SLOT(slotNewFingering()));
+ connect(m_deleteFingeringButton, SIGNAL(clicked()),
+ this, SLOT(slotDeleteFingering()));
+ connect(m_editFingeringButton, SIGNAL(clicked()),
+ this, SLOT(slotEditFingering()));
+
+ topLayout->addWidget(new QLabel(i18n("Fingerings"), page), 0, 3);
+ m_fingeringsList = new QListBox(page);
+ topLayout->addMultiCellWidget(m_fingeringsList, 1, 2, 3, 3);
+
+ m_fingeringBox = new FingeringBox(false, page);
+ topLayout->addMultiCellWidget(m_fingeringBox, 2, 2, 0, 1);
+
+ connect(m_rootNotesList, SIGNAL(highlighted(int)),
+ this, SLOT(slotRootHighlighted(int)));
+ connect(m_chordExtList, SIGNAL(highlighted(int)),
+ this, SLOT(slotChordExtHighlighted(int)));
+ connect(m_fingeringsList, SIGNAL(highlighted(QListBoxItem*)),
+ this, SLOT(slotFingeringHighlighted(QListBoxItem*)));
+}
+
+void
+GuitarChordSelectorDialog::init()
+{
+ // populate the listboxes
+ //
+ std::vector<QString> chordFiles = getAvailableChordFiles();
+
+ parseChordFiles(chordFiles);
+
+// m_chordMap.debugDump();
+
+ populate();
+}
+
+void
+GuitarChordSelectorDialog::populate()
+{
+ QStringList rootList = m_chordMap.getRootList();
+ if (rootList.count() > 0) {
+ m_rootNotesList->insertStringList(rootList);
+
+ QStringList extList = m_chordMap.getExtList(rootList.first());
+ populateExtensions(extList);
+
+ Guitar::ChordMap::chordarray chords = m_chordMap.getChords(rootList.first(), extList.first());
+ populateFingerings(chords);
+
+ m_chord.setRoot(rootList.first());
+ m_chord.setExt(extList.first());
+ }
+
+ m_rootNotesList->sort();
+
+ m_rootNotesList->setCurrentItem(0);
+}
+
+void
+GuitarChordSelectorDialog::clear()
+{
+ m_rootNotesList->clear();
+ m_chordExtList->clear();
+ m_fingeringsList->clear();
+}
+
+void
+GuitarChordSelectorDialog::refresh()
+{
+ clear();
+ populate();
+}
+
+void
+GuitarChordSelectorDialog::slotRootHighlighted(int i)
+{
+ NOTATION_DEBUG << "GuitarChordSelectorDialog::slotRootHighlighted " << i << endl;
+
+ m_chord.setRoot(m_rootNotesList->text(i));
+
+ QStringList extList = m_chordMap.getExtList(m_chord.getRoot());
+ populateExtensions(extList);
+ if (m_chordExtList->count() > 0)
+ m_chordExtList->setCurrentItem(0);
+ else
+ m_fingeringsList->clear(); // clear any previous fingerings
+}
+
+void
+GuitarChordSelectorDialog::slotChordExtHighlighted(int i)
+{
+ NOTATION_DEBUG << "GuitarChordSelectorDialog::slotChordExtHighlighted " << i << endl;
+
+ Guitar::ChordMap::chordarray chords = m_chordMap.getChords(m_chord.getRoot(), m_chordExtList->text(i));
+ populateFingerings(chords);
+
+ m_fingeringsList->setCurrentItem(0);
+}
+
+void
+GuitarChordSelectorDialog::slotFingeringHighlighted(QListBoxItem* listBoxItem)
+{
+ NOTATION_DEBUG << "GuitarChordSelectorDialog::slotFingeringHighlighted\n";
+
+ FingeringListBoxItem* fingeringItem = dynamic_cast<FingeringListBoxItem*>(listBoxItem);
+ if (fingeringItem) {
+ m_chord = fingeringItem->getChord();
+ m_fingeringBox->setFingering(m_chord.getFingering());
+ setEditionEnabled(m_chord.isUserChord());
+ }
+}
+
+void
+GuitarChordSelectorDialog::slotComplexityChanged(int)
+{
+ // simply repopulate the extension list box
+ //
+ QStringList extList = m_chordMap.getExtList(m_chord.getRoot());
+ populateExtensions(extList);
+ if (m_chordExtList->count() > 0)
+ m_chordExtList->setCurrentItem(0);
+ else
+ m_fingeringsList->clear(); // clear any previous fingerings
+}
+
+void
+GuitarChordSelectorDialog::slotNewFingering()
+{
+ Guitar::Chord newChord;
+ newChord.setRoot(m_chord.getRoot());
+ newChord.setExt(m_chord.getExt());
+
+ GuitarChordEditorDialog* chordEditorDialog = new GuitarChordEditorDialog(newChord, m_chordMap, this);
+
+ if (chordEditorDialog->exec() == QDialog::Accepted) {
+ m_chordMap.insert(newChord);
+ // populate lists
+ //
+ if (!m_rootNotesList->findItem(newChord.getRoot(), Qt::ExactMatch)) {
+ m_rootNotesList->insertItem(newChord.getRoot());
+ m_rootNotesList->sort();
+ }
+
+ if (!m_chordExtList->findItem(newChord.getExt(), Qt::ExactMatch)) {
+ m_chordExtList->insertItem(newChord.getExt());
+ m_chordExtList->sort();
+ }
+ }
+
+ delete chordEditorDialog;
+
+ refresh();
+}
+
+void
+GuitarChordSelectorDialog::slotDeleteFingering()
+{
+ if (m_chord.isUserChord()) {
+ m_chordMap.remove(m_chord);
+ delete m_fingeringsList->selectedItem();
+ }
+}
+
+void
+GuitarChordSelectorDialog::slotEditFingering()
+{
+ Guitar::Chord newChord = m_chord;
+ GuitarChordEditorDialog* chordEditorDialog = new GuitarChordEditorDialog(newChord, m_chordMap, this);
+
+ if (chordEditorDialog->exec() == QDialog::Accepted) {
+ NOTATION_DEBUG << "GuitarChordSelectorDialog::slotEditFingering() - current map state :\n";
+ m_chordMap.debugDump();
+ m_chordMap.substitute(m_chord, newChord);
+ NOTATION_DEBUG << "GuitarChordSelectorDialog::slotEditFingering() - new map state :\n";
+ m_chordMap.debugDump();
+ setChord(newChord);
+ }
+
+ delete chordEditorDialog;
+
+ refresh();
+}
+
+void
+GuitarChordSelectorDialog::slotOk()
+{
+ if (m_chordMap.needSave()) {
+ saveUserChordMap();
+ m_chordMap.clearNeedSave();
+ }
+
+ KDialogBase::slotOk();
+}
+
+void
+GuitarChordSelectorDialog::setChord(const Guitar::Chord& chord)
+{
+ NOTATION_DEBUG << "GuitarChordSelectorDialog::setChord " << chord << endl;
+
+ m_chord = chord;
+
+ // select the chord's root
+ //
+ m_rootNotesList->setCurrentItem(0);
+ QListBoxItem* correspondingRoot = m_rootNotesList->findItem(chord.getRoot(), Qt::ExactMatch);
+ if (correspondingRoot)
+ m_rootNotesList->setSelected(correspondingRoot, true);
+
+ // update the dialog's complexity setting if needed, then populate the extension list
+ //
+ QString chordExt = chord.getExt();
+ int complexityLevel = m_chordComplexityCombo->currentItem();
+ int chordComplexity = evaluateChordComplexity(chordExt);
+
+ if (chordComplexity > complexityLevel) {
+ m_chordComplexityCombo->setCurrentItem(chordComplexity);
+ }
+
+ QStringList extList = m_chordMap.getExtList(chord.getRoot());
+ populateExtensions(extList);
+
+ // select the chord's extension
+ //
+ if (chordExt.isEmpty()) {
+ chordExt = "";
+ m_chordExtList->setSelected(0, true);
+ } else {
+ QListBoxItem* correspondingExt = m_chordExtList->findItem(chordExt, Qt::ExactMatch);
+ if (correspondingExt)
+ m_chordExtList->setSelected(correspondingExt, true);
+ }
+
+ // populate fingerings and pass the current chord's fingering so it is selected
+ //
+ Guitar::ChordMap::chordarray similarChords = m_chordMap.getChords(chord.getRoot(), chord.getExt());
+ populateFingerings(similarChords, chord.getFingering());
+}
+
+void
+GuitarChordSelectorDialog::populateFingerings(const Guitar::ChordMap::chordarray& chords, const Guitar::Fingering& refFingering)
+{
+ m_fingeringsList->clear();
+
+ for(Guitar::ChordMap::chordarray::const_iterator i = chords.begin(); i != chords.end(); ++i) {
+ const Guitar::Chord& chord = *i;
+ QString fingeringString = chord.getFingering().toString();
+ NOTATION_DEBUG << "GuitarChordSelectorDialog::populateFingerings " << chord << endl;
+ QPixmap fingeringPixmap = getFingeringPixmap(chord.getFingering());
+ FingeringListBoxItem *item = new FingeringListBoxItem(chord, m_fingeringsList, fingeringPixmap, fingeringString);
+ if (refFingering == chord.getFingering()) {
+ NOTATION_DEBUG << "GuitarChordSelectorDialog::populateFingerings - fingering found " << fingeringString << endl;
+ m_fingeringsList->setSelected(item, true);
+ }
+ }
+
+}
+
+
+QPixmap
+GuitarChordSelectorDialog::getFingeringPixmap(const Guitar::Fingering& fingering) const
+{
+ QPixmap pixmap(FINGERING_PIXMAP_WIDTH, FINGERING_PIXMAP_HEIGHT);
+ pixmap.fill();
+
+ QPainter pp(&pixmap);
+ QPainter *p = &pp;
+
+ p->setViewport(FINGERING_PIXMAP_H_MARGIN, FINGERING_PIXMAP_W_MARGIN,
+ FINGERING_PIXMAP_WIDTH - FINGERING_PIXMAP_W_MARGIN,
+ FINGERING_PIXMAP_HEIGHT - FINGERING_PIXMAP_H_MARGIN);
+
+ Guitar::NoteSymbols::drawFingeringPixmap(fingering, m_fingeringBox->getNoteSymbols(), p);
+
+ return pixmap;
+}
+
+void
+GuitarChordSelectorDialog::populateExtensions(const QStringList& extList)
+{
+ m_chordExtList->clear();
+
+ if (m_chordComplexityCombo->currentItem() != COMPLEXITY_ALL) {
+ // some filtering needs to be done
+ int complexityLevel = m_chordComplexityCombo->currentItem();
+
+ QStringList filteredList;
+ for(QStringList::const_iterator i = extList.constBegin(); i != extList.constEnd(); ++i) {
+ if (evaluateChordComplexity((*i).lower().stripWhiteSpace()) <= complexityLevel) {
+ NOTATION_DEBUG << "GuitarChordSelectorDialog::populateExtensions - adding '" << *i << "'\n";
+ filteredList.append(*i);
+ }
+ }
+
+ m_chordExtList->insertStringList(filteredList);
+
+ } else {
+ m_chordExtList->insertStringList(extList);
+ }
+}
+
+int
+GuitarChordSelectorDialog::evaluateChordComplexity(const QString& ext)
+{
+ if (ext.isEmpty() ||
+ ext == "7" ||
+ ext == "m" ||
+ ext == "5")
+ return COMPLEXITY_BEGINNER;
+
+ if (ext == "dim" ||
+ ext == "dim7" ||
+ ext == "aug" ||
+ ext == "sus2" ||
+ ext == "sus4" ||
+ ext == "maj7" ||
+ ext == "m7" ||
+ ext == "mmaj7" ||
+ ext == "m7b5" ||
+ ext == "7sus4")
+
+ return COMPLEXITY_COMMON;
+
+ return COMPLEXITY_ALL;
+}
+
+void
+GuitarChordSelectorDialog::parseChordFiles(const std::vector<QString>& chordFiles)
+{
+ for(std::vector<QString>::const_iterator i = chordFiles.begin(); i != chordFiles.end(); ++i) {
+ parseChordFile(*i);
+ }
+}
+
+void
+GuitarChordSelectorDialog::parseChordFile(const QString& chordFileName)
+{
+ ChordXmlHandler handler(m_chordMap);
+ QFile chordFile(chordFileName);
+ bool ok = chordFile.open(IO_ReadOnly);
+ if (!ok)
+ KMessageBox::error(0, i18n("couldn't open file '%1'").arg(handler.errorString()));
+
+ QXmlInputSource source(chordFile);
+ QXmlSimpleReader reader;
+ reader.setContentHandler(&handler);
+ reader.setErrorHandler(&handler);
+ NOTATION_DEBUG << "GuitarChordSelectorDialog::parseChordFile() parsing " << chordFileName << endl;
+ reader.parse(source);
+ if (!ok)
+ KMessageBox::error(0, i18n("couldn't parse chord dictionnary : %1").arg(handler.errorString()));
+
+}
+
+void
+GuitarChordSelectorDialog::setEditionEnabled(bool enabled)
+{
+ m_deleteFingeringButton->setEnabled(enabled);
+ m_editFingeringButton->setEnabled(enabled);
+}
+
+std::vector<QString>
+GuitarChordSelectorDialog::getAvailableChordFiles()
+{
+ std::vector<QString> names;
+
+ // Read config for default directory
+ QStringList chordDictFiles = KGlobal::dirs()->findAllResources("appdata", "chords/*.xml");
+
+ for(QStringList::iterator i = chordDictFiles.begin(); i != chordDictFiles.end(); ++i) {
+ NOTATION_DEBUG << "GuitarChordSelectorDialog::getAvailableChordFiles : adding file " << *i << endl;
+ names.push_back(*i);
+ }
+
+ return names;
+}
+
+bool
+GuitarChordSelectorDialog::saveUserChordMap()
+{
+ // Read config for user directory
+ QString userDir = KGlobal::dirs()->saveLocation("appdata", "chords/");
+
+ QString userChordDictPath = userDir + "/user_chords.xml";
+
+ NOTATION_DEBUG << "GuitarChordSelectorDialog::saveUserChordMap() : saving user chord map to " << userChordDictPath << endl;
+ QString errMsg;
+
+ m_chordMap.saveDocument(userChordDictPath, true, errMsg);
+
+ return errMsg.isEmpty();
+}
+
+
+}
+
+
+#include "GuitarChordSelectorDialog.moc"
diff --git a/src/gui/editors/guitar/GuitarChordSelectorDialog.h b/src/gui/editors/guitar/GuitarChordSelectorDialog.h
new file mode 100644
index 0000000..6c8f1ad
--- /dev/null
+++ b/src/gui/editors/guitar/GuitarChordSelectorDialog.h
@@ -0,0 +1,120 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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.
+*/
+
+
+#ifndef _RG_GUITARCHORDSELECTORDIALOG_H_
+#define _RG_GUITARCHORDSELECTORDIALOG_H_
+
+#include "Chord.h"
+#include "ChordMap.h"
+
+#include <kdialogbase.h>
+#include <qstring.h>
+#include <vector>
+
+class QListBox;
+class QListBoxItem;
+class QComboBox;
+class QPushButton;
+
+namespace Rosegarden
+{
+
+class FingeringBox;
+
+class GuitarChordSelectorDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ enum { COMPLEXITY_BEGINNER, COMPLEXITY_COMMON, COMPLEXITY_ALL };
+
+public:
+ GuitarChordSelectorDialog(QWidget *parent=0);
+
+ void init();
+
+ const Guitar::Chord& getChord() const { return m_chord; }
+
+ void setChord(const Guitar::Chord&);
+
+protected slots:
+ void slotRootHighlighted(int);
+ void slotChordExtHighlighted(int);
+ void slotFingeringHighlighted(QListBoxItem*);
+ void slotComplexityChanged(int);
+
+ void slotNewFingering();
+ void slotDeleteFingering();
+ void slotEditFingering();
+
+ virtual void slotOk();
+
+protected:
+
+ void parseChordFiles(const std::vector<QString>& chordFiles);
+ void parseChordFile(const QString& chordFileName);
+ void populateFingerings(const Guitar::ChordMap::chordarray&, const Guitar::Fingering& refFingering=Guitar::Fingering(0));
+ void populateExtensions(const QStringList& extList);
+
+ /// set enabled state of edit/delete buttons
+ void setEditionEnabled(bool);
+
+ void populate();
+ void clear();
+ void refresh();
+
+ bool saveUserChordMap();
+ int evaluateChordComplexity(const QString& ext);
+
+ QPixmap getFingeringPixmap(const Guitar::Fingering& fingering) const;
+
+ /// Find all chord list files on the system
+ std::vector<QString> getAvailableChordFiles();
+
+ Guitar::ChordMap m_chordMap;
+
+ /// current selected chord
+ Guitar::Chord m_chord;
+
+ // Chord data
+ QListBox* m_rootNotesList;
+ QListBox* m_chordExtList;
+ QListBox* m_fingeringsList;
+ FingeringBox* m_fingeringBox;
+
+ QComboBox* m_chordComplexityCombo;
+ QPushButton* m_newFingeringButton;
+ QPushButton* m_deleteFingeringButton;
+ QPushButton* m_editFingeringButton;
+
+ static const unsigned int FINGERING_PIXMAP_HEIGHT = 75;
+ static const unsigned int FINGERING_PIXMAP_WIDTH = 75;
+ static const unsigned int FINGERING_PIXMAP_H_MARGIN = 5;
+ static const unsigned int FINGERING_PIXMAP_W_MARGIN = 5;
+
+};
+
+}
+
+#endif /*_RG_GUITARCHORDSELECTORDIALOG_H_*/
diff --git a/src/gui/editors/guitar/NoteSymbols.cpp b/src/gui/editors/guitar/NoteSymbols.cpp
new file mode 100644
index 0000000..14379de
--- /dev/null
+++ b/src/gui/editors/guitar/NoteSymbols.cpp
@@ -0,0 +1,486 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ This file contains code from
+ 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 "NoteSymbols.h"
+#include "Fingering.h"
+#include "misc/Debug.h"
+
+namespace Rosegarden
+{
+
+namespace Guitar
+{
+NoteSymbols::posPair
+NoteSymbols::getX ( int imgWidth, unsigned int stringNb, unsigned int nbOfStrings ) const
+{
+ /*
+ std::cout << "NoteSymbols::getX - input values" << std::endl
+ << " position: " << position << std::endl
+ << " string #: " << string_num << std::endl
+ << " scale: " << scale << std::endl;
+ */
+ unsigned int lBorder = getLeftBorder( imgWidth );
+ unsigned int guitarChordWidth = getGuitarChordWidth( imgWidth );
+ unsigned int columnWidth = guitarChordWidth / nbOfStrings;
+ return std::make_pair( ( stringNb * columnWidth + lBorder ), columnWidth );
+}
+
+NoteSymbols::posPair
+NoteSymbols::getY ( int imgHeight, unsigned int fretNb, unsigned int nbOfFrets ) const
+{
+ /*
+ std::cout << "NoteSymbols::getY - input values" << std::endl
+ << " position: " << fret_pos << std::endl
+ << " max frets: " << maxFretNum << std::endl
+ << " scale: " << scale << std::endl;
+ */
+ unsigned int tBorder = getTopBorder( imgHeight );
+ unsigned int guitarChordHeight = getGuitarChordHeight( imgHeight );
+ unsigned int rowHeight = guitarChordHeight / nbOfFrets;
+ return std::make_pair( ( ( fretNb * rowHeight ) + tBorder ), rowHeight );
+}
+
+void
+NoteSymbols::drawMuteSymbol ( QPainter* p,
+ unsigned int position ) const
+{
+ QRect v = p->viewport();
+
+ posPair x_pos = getX ( v.width(), position, m_nbOfStrings );
+ unsigned int y_pos = getTopBorder( v.height() ) / 2;
+ double columnWidth = x_pos.second;
+ unsigned int width = static_cast<unsigned int>( columnWidth * 0.7 );
+ unsigned int height = static_cast<unsigned int>( columnWidth * 0.7 );
+
+ //std::cout << "NoteSymbols::drawMuteSymbol - drawing Mute symbol at string #" << position
+ //<< std::endl;
+
+ p->drawLine ( x_pos.first - ( width / 2 ),
+ y_pos - ( height / 2 ),
+ ( x_pos.first + ( width / 2 ) ),
+ y_pos + ( height / 2 ) );
+
+ p->drawLine( x_pos.first + ( width / 2 ),
+ y_pos - ( height / 2 ),
+ ( x_pos.first - ( width / 2 ) ),
+ y_pos + ( height / 2 ) );
+}
+
+void
+NoteSymbols::drawOpenSymbol ( QPainter* p,
+ unsigned int position ) const
+{
+ QRect v = p->viewport();
+ posPair x_pos = getX ( v.width(), position, m_nbOfStrings );
+ unsigned int y_pos = getTopBorder( v.height() ) / 2;
+ double columnWidth = x_pos.second;
+ unsigned int radius = static_cast<unsigned int>( columnWidth * 0.7 );
+
+ //std::cout << "NoteSymbols::drawOpenSymbol - drawing Open symbol at string #" << position
+ //<< std::endl;
+
+ p->setBrush( QBrush(p->brush().color(), Qt::NoBrush) );
+ p->drawEllipse( x_pos.first - ( radius / 2 ),
+ y_pos - ( radius / 2 ),
+ radius,
+ radius );
+}
+
+void
+NoteSymbols::drawNoteSymbol ( QPainter* p,
+ unsigned int stringNb,
+ int fretNb,
+ bool transient ) const
+{
+// NOTATION_DEBUG << "NoteSymbols::drawNoteSymbol - string: " << stringNb << ", fret:" << fretNb << endl;
+
+ QRect v = p->viewport();
+ posPair x_pos = getX ( v.width(), stringNb, m_nbOfStrings );
+ posPair y_pos = getY ( v.height(), fretNb, m_nbOfFrets );
+ double columnWidth = x_pos.second;
+ unsigned int radius;
+
+ if (transient) {
+ radius = static_cast<unsigned int>( columnWidth /* * 0.9 */ );
+ p->setBrush( QBrush(p->brush().color(), Qt::NoBrush) );
+ } else {
+ radius = static_cast<unsigned int>( columnWidth * 0.7 );
+ p->setBrush( QBrush(p->brush().color(), Qt::SolidPattern) );
+ }
+
+ int x = x_pos.first - ( radius / 2 ),
+ y = y_pos.first + ( (y_pos.second - radius) / 2) - y_pos.second + TOP_GUITAR_CHORD_MARGIN;
+
+// y = y_pos.first - (radius / 2) - y_pos.second + TOP_GUITAR_CHORD_MARGIN;
+
+// RG_DEBUG << "NoteSymbols::drawNoteSymbol : rect = " << QRect(x,y, radius, radius) << endl;
+
+ p->drawEllipse( x,
+ y,
+ radius,
+ radius );
+
+// p->save();
+// p->setPen(Qt::red);
+// p->drawRect( x, y, radius, radius );
+// p->restore();
+}
+
+void
+NoteSymbols::drawBarreSymbol ( QPainter* p,
+ int fretNb,
+ unsigned int start,
+ unsigned int end ) const
+{
+
+ //std::cout << "NoteSymbols::drawBarreSymbol - start: " << start << ", end:" << end << std::endl;
+
+ drawNoteSymbol ( p, start, fretNb );
+
+ if ( ( end - start ) >= 1 ) {
+ QRect v = p->viewport();
+ posPair startXPos = getX ( v.width(), start, m_nbOfStrings );
+ posPair endXPos = getX ( v.width(), end, m_nbOfStrings );
+ posPair y_pos = getY ( v.height(), fretNb, m_nbOfFrets );
+ double columnWidth = startXPos.second;
+ unsigned int thickness = static_cast<unsigned int>( columnWidth * 0.7 );
+
+ p->drawRect( startXPos.first,
+ y_pos.first + ( y_pos.second / 4 ) + TOP_GUITAR_CHORD_MARGIN,
+ endXPos.first - startXPos.first,
+ thickness );
+ }
+
+ drawNoteSymbol ( p, end, fretNb );
+}
+
+void
+NoteSymbols::drawFretNumber ( QPainter* p,
+ unsigned int fret_num ) const
+{
+ if ( fret_num > 1 ) {
+ QRect v = p->viewport();
+ unsigned int imgWidth = v.width();
+ unsigned int imgHeight = v.height();
+
+ p->save();
+ QFont font;
+ font.setPixelSize(getFontPixelSize(v.width(), v.height()));
+ p->setFont(font);
+
+ QString tmp;
+ tmp.setNum( fret_num );
+
+ // Use NoteSymbols to grab X and Y for first fret
+ posPair y_pos = getY( imgHeight, 0, m_nbOfFrets );
+
+ p->drawText( getLeftBorder( imgWidth ) / 4,
+ y_pos.first + ( y_pos.second / 2 ),
+ tmp );
+
+ p->restore();
+ }
+}
+
+void
+NoteSymbols::drawFrets ( QPainter* p ) const
+{
+ /*
+ std::cout << "NoteSymbols::drawFretHorizontalLines" << std::endl
+ << " scale: " << scale << std::endl
+ << " frets: " << fretsDisplayed << std::endl
+ << " max string: " << maxStringNum << std::endl;
+ */
+
+ QRect v = p->viewport();
+ unsigned int imgWidth = v.width();
+ unsigned int imgHeight = v.height();
+ //unsigned int endXPos = getGuitarChordWidth(imgWidth) + getLeftBorder(imgWidth);
+ posPair endXPos = getX ( imgWidth, m_nbOfStrings - 1, m_nbOfStrings );
+
+ unsigned int yGuitarChord = getGuitarChordHeight( imgHeight );
+ unsigned int rowHeight = yGuitarChord / m_nbOfFrets;
+
+ QPen pen(p->pen());
+ pen.setWidth(imgHeight >= 100 ? FRET_PEN_WIDTH : FRET_PEN_WIDTH / 2);
+ p->save();
+ p->setPen(pen);
+ unsigned int y_pos = (getY ( imgHeight, 0, m_nbOfFrets )).first + TOP_GUITAR_CHORD_MARGIN;
+
+// NOTATION_DEBUG << "NoteSymbols::drawFrets : " << m_nbOfFrets << endl;
+
+ // Horizontal lines
+ for ( unsigned int i = 0; i <= m_nbOfFrets; ++i ) {
+
+ /* This code borrowed from KGuitar 0.5 */
+ p->drawLine( getLeftBorder( imgWidth ),
+ y_pos,
+ endXPos.first,
+ y_pos);
+// NOTATION_DEBUG << "NoteSymbols::drawFrets : " << QPoint(getLeftBorder(imgWidth), y_pos)
+// << " to " << QPoint(endXPos.first, y_pos) << endl;
+
+
+ y_pos += rowHeight;
+ }
+
+ p->restore();
+
+}
+
+void
+NoteSymbols::drawStrings ( QPainter* p ) const
+{
+ // Vertical lines
+ QRect v = p->viewport();
+ int imgHeight = v.height();
+ int imgWidth = v.width();
+
+ unsigned int startPos = getTopBorder( imgHeight ) + TOP_GUITAR_CHORD_MARGIN;
+ unsigned int endPos = (getY ( imgHeight, m_nbOfFrets, m_nbOfFrets )).first + TOP_GUITAR_CHORD_MARGIN;
+
+ unsigned int guitarChordWidth = getGuitarChordWidth( imgWidth );
+ unsigned int columnWidth = guitarChordWidth / m_nbOfStrings;
+
+ unsigned int x_pos = (getX ( imgWidth, 0, m_nbOfStrings )).first;
+
+ QPen pen(p->pen());
+ pen.setWidth(imgWidth >= 100 ? STRING_PEN_WIDTH : STRING_PEN_WIDTH / 2);
+ p->save();
+ p->setPen(pen);
+
+ for ( unsigned int i = 0; i < m_nbOfStrings; ++i ) {
+
+ /* This code borrowed from KGuitar 0.5 */
+ p->drawLine( x_pos,
+ startPos,
+ x_pos,
+ endPos );
+
+ x_pos += columnWidth;
+ }
+
+ p->restore();
+
+}
+
+QRect NoteSymbols::getTransientNoteSymbolRect(QSize guitarChordSize,
+ unsigned int stringNb,
+ int fretNb) const
+{
+ posPair x_pos = getX ( guitarChordSize.width(), stringNb, m_nbOfStrings );
+ posPair y_pos = getY ( guitarChordSize.height(), fretNb, m_nbOfFrets );
+ double columnWidth = x_pos.second;
+ unsigned int radius = static_cast<unsigned int>( columnWidth /* * 0.9 */ );
+
+ int x = x_pos.first - ( radius / 2 ),
+ y = y_pos.first + ( (y_pos.second - radius) / 2) - y_pos.second + TOP_GUITAR_CHORD_MARGIN;
+
+ return QRect(x, y, radius, radius);
+}
+
+unsigned int
+NoteSymbols::getTopBorder ( unsigned int imgHeight ) const
+{
+ return static_cast<unsigned int>( TOP_BORDER_PERCENTAGE * imgHeight );
+}
+
+unsigned int
+NoteSymbols::getBottomBorder ( unsigned int imgHeight ) const
+{
+ return static_cast<unsigned int>( imgHeight * BOTTOM_BORDER_PERCENTAGE );
+}
+
+unsigned int
+NoteSymbols::getLeftBorder ( unsigned int imgWidth ) const
+{
+ unsigned int left = static_cast<unsigned int>( imgWidth * LEFT_BORDER_PERCENTAGE );
+ if ( left < 15 ) {
+ left = 15;
+ }
+ return left;
+}
+
+unsigned int
+NoteSymbols::getRightBorder ( unsigned int imgWidth ) const
+{
+ return static_cast<unsigned int>( imgWidth * RIGHT_BORDER_PERCENTAGE );
+}
+
+unsigned int
+NoteSymbols::getGuitarChordWidth ( int imgWidth ) const
+{
+ return static_cast<unsigned int>( imgWidth * GUITAR_CHORD_WIDTH_PERCENTAGE );
+}
+
+unsigned int
+NoteSymbols::getGuitarChordHeight ( int imgHeight ) const
+{
+ return static_cast<unsigned int>( imgHeight * GUITAR_CHORD_HEIGHT_PERCENTAGE );
+}
+
+unsigned int
+NoteSymbols::getFontPixelSize ( int imgWidth, int imgHeight ) const
+{
+ return std::max(8, imgHeight / 10);
+}
+
+std::pair<bool, unsigned int>
+NoteSymbols::getStringNumber ( int imgWidth,
+ unsigned int x_pos,
+ unsigned int maxStringNum ) const
+{
+ /*
+ std::cout << "NoteSymbols::getNumberOfStrings - input values" << std::endl
+ << " X position: " << x_pos << std::endl
+ << " string #: " << maxStringNum << std::endl
+ << " image width: " << imgWidth << std::endl;
+ */
+ bool valueOk = false;
+
+ posPair xPairPos;
+ unsigned int min = 0;
+ unsigned int max = 0;
+ unsigned int result = 0;
+
+ for ( unsigned int i = 0; i < maxStringNum; ++i ) {
+ xPairPos = getX ( imgWidth, i, maxStringNum );
+
+ // If the counter equals zero then we are at the first
+ // string to the left
+ if ( i == 0 ) {
+ // Add 10 pixel buffer to range comparison
+ min = xPairPos.first - 10;
+ } else {
+ min = xPairPos.first - xPairPos.second / 2;
+ }
+
+ // If the counter equals the maxString number -1 then we are at the last
+ // string to the right
+ if ( i == ( maxStringNum - 1 ) ) {
+ // Add 10 pixel buffer to range comparison
+ max = xPairPos.first + 10;
+ } else {
+ max = xPairPos.first + xPairPos.second / 2;
+ }
+
+ if ( ( x_pos >= min ) && ( x_pos <= max ) ) {
+ result = i;
+ valueOk = true;
+ break;
+ }
+ }
+
+ //std::cout << "NoteSymbols::getNumberOfStrings - string: #" << result << std::endl;
+ return std::make_pair( valueOk, result );
+}
+
+std::pair<bool, unsigned int>
+NoteSymbols::getFretNumber ( int imgHeight,
+ unsigned int y_pos,
+ unsigned int maxFretNum ) const
+{
+ /*
+ std::cout << "NoteSymbols::getNumberOfFrets - input values" << std::endl
+ << " Y position: " << y_pos << std::endl
+ << " max frets: " << maxFretNum << std::endl
+ << " image height: " << imgHeight << std::endl;
+ */
+
+ bool valueOk = false;
+ unsigned int tBorder = getTopBorder( imgHeight );
+ unsigned int result = 0;
+
+ if ( y_pos < tBorder ) {
+ // User pressing above the guitar chord to mark line muted or opened
+ valueOk = true;
+ } else {
+ typedef std::pair<unsigned int, unsigned int> RangePair;
+
+ posPair min_pos;
+ posPair max_pos;
+
+ for ( unsigned int i = 0; i < maxFretNum; ++i ) {
+ min_pos = getY ( imgHeight, i, maxFretNum );
+ max_pos = getY ( imgHeight, i + 1, maxFretNum );
+
+ if ( ( y_pos >= min_pos.first ) && y_pos <= max_pos.first - 1 ) {
+ result = i + 1;
+ valueOk = true;
+ break;
+ }
+ }
+ }
+ // std::cout << " fret #: " << result << std::endl;
+ return std::make_pair( valueOk, result );
+}
+
+void
+NoteSymbols::drawFingeringPixmap(const Guitar::Fingering& fingering, const Guitar::NoteSymbols& noteSymbols, QPainter *p)
+{
+ unsigned int startFret = fingering.getStartFret();
+
+ noteSymbols.drawFretNumber(p, startFret);
+ noteSymbols.drawFrets(p);
+ noteSymbols.drawStrings(p);
+
+ unsigned int stringNb = 0;
+
+ for (Fingering::const_iterator pos = fingering.begin();
+ pos != fingering.end();
+ ++pos, ++stringNb) {
+
+ switch (*pos) {
+ case Fingering::OPEN:
+ noteSymbols.drawOpenSymbol(p, stringNb);
+ break;
+
+ case Fingering::MUTED:
+ noteSymbols.drawMuteSymbol(p, stringNb);
+ break;
+
+ default:
+ noteSymbols.drawNoteSymbol(p, stringNb, *pos - (startFret - 1), false);
+ break;
+ }
+ }
+
+}
+
+
+float const NoteSymbols::LEFT_BORDER_PERCENTAGE = 0.2;
+float const NoteSymbols::RIGHT_BORDER_PERCENTAGE = 0.1;
+float const NoteSymbols::GUITAR_CHORD_WIDTH_PERCENTAGE = 0.8;
+float const NoteSymbols::TOP_BORDER_PERCENTAGE = 0.1;
+float const NoteSymbols::BOTTOM_BORDER_PERCENTAGE = 0.1;
+float const NoteSymbols::GUITAR_CHORD_HEIGHT_PERCENTAGE = 0.8;
+int const NoteSymbols::TOP_GUITAR_CHORD_MARGIN = 5;
+int const NoteSymbols::FRET_PEN_WIDTH = 2;
+int const NoteSymbols::STRING_PEN_WIDTH = 2;
+
+} /* namespace Guitar */
+
+}
+
diff --git a/src/gui/editors/guitar/NoteSymbols.h b/src/gui/editors/guitar/NoteSymbols.h
new file mode 100644
index 0000000..f90fefb
--- /dev/null
+++ b/src/gui/editors/guitar/NoteSymbols.h
@@ -0,0 +1,192 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ The moral rights of Guillaume Laurent, Chris Cannam, and Richard
+ Bown to claim authorship of this work have been asserted.
+
+ This file contains code from
+ 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.
+*/
+
+
+#ifndef _RG_SYMBOLS_H_
+#define _RG_SYMBOLS_H_
+
+#include <qbrush.h>
+#include <qpainter.h>
+
+namespace Rosegarden
+{
+
+/**
+ *----------------------------------------
+ * Finding X position on guitar chord pixmap
+ *----------------------------------------
+ *
+ * Originally x = position * scale + FC::BORDER + FC::CIRCBORD + FC::FRETTEXT
+ *
+ * The last three can be condense into on term called XBorder
+ * XBorder = FC::BORDER + FC::CIRCBORD + FC::FRETTEXT
+ * = 5 + 2 + 10 (see fingers.h)
+ * = 17
+ *
+ * The drawable guitar chord space on the x-axis:
+ * XGuitarChord = pixmap width - XBorder
+ * = width - 17
+ *
+ * The guitar chord x-axis is broken up into colums which represent the drawable
+ * space for a guitar chord component (e.g. note, barre)
+ * Column Width = XGuitarChord / number of strings
+ *
+ * Therefore a new x can be calculated from the position and the column width
+ * x = (position * Column Width) + XBorder
+ *
+ *-------------------------------------------
+ * Finding Y position on guitar chord pixmap
+ *-------------------------------------------
+ *
+ * Originally y = (FC::BORDER * scale) + (2 * FC::SPACER) + (fret * scale) + FC::CIRCBORD
+ *
+ * As with the x-axis the equation can be separated into the position plus the border. In
+ * this case YBorder
+ * YBorder = (FC::BORDER*scale) + (2*FC::SPACER) + FC::CIRCBORD
+ * = 17 (If we want to use the same border as the x-axis)
+ *
+ * The drawable guitar chord space on the y-axis:
+ * YGuitarChord = pixmap height - YBorder
+ *
+ * The guitar chord y-axis is broken up into rows which represent the drawable
+ * space for a guitar chord component (e.g. note, barre)
+ * Row Height = YGuitarChord / number of frets
+ *
+ * Therefore a new y can be calculated from the fret position and the row height
+ * y = fret * Row Height
+ **/
+
+namespace Guitar
+{
+
+class Fingering;
+
+
+class NoteSymbols
+{
+private:
+ typedef std::pair<unsigned int, unsigned int> posPair;
+
+ static float const LEFT_BORDER_PERCENTAGE;
+ static float const RIGHT_BORDER_PERCENTAGE;
+ static float const GUITAR_CHORD_WIDTH_PERCENTAGE;
+ static float const TOP_BORDER_PERCENTAGE;
+ static float const BOTTOM_BORDER_PERCENTAGE;
+ static float const GUITAR_CHORD_HEIGHT_PERCENTAGE;
+ static int const TOP_GUITAR_CHORD_MARGIN;
+ static int const FRET_PEN_WIDTH;
+ static int const STRING_PEN_WIDTH;
+
+public:
+
+ NoteSymbols(unsigned int nbOfStrings, unsigned int nbOfFrets) :
+ m_nbOfStrings(nbOfStrings),
+ m_nbOfFrets(nbOfFrets) {};
+
+ //! Display a mute symbol in the QPainter object
+ void
+ drawMuteSymbol ( QPainter* p,
+ unsigned int position ) const;
+
+ /* This code borrowed from KGuitar 0.5 */
+ //! Display a open symbol in the QPainter object (KGuitar)
+ void drawOpenSymbol ( QPainter* p,
+ unsigned int position ) const;
+
+ /* This code borrowed from KGuitar 0.5 */
+ //! Display a note symbol in the QPainter object (KGuitar)
+ void drawNoteSymbol ( QPainter* p,
+ unsigned int stringNb,
+ int fretNb,
+ bool transient = false ) const;
+
+ /* This code borrowed from KGuitar 0.5 */
+ /**
+ * Display a bar symbol in the QPainter object (KGuitar)
+ * The code from the KGuitar project was modified to display a bar. This feature was not
+ * available in that project
+ */
+ void drawBarreSymbol ( QPainter* p,
+ int fretNb,
+ unsigned int start,
+ unsigned int end ) const;
+
+ void drawFretNumber ( QPainter* p,
+ unsigned int fret_num ) const;
+
+ void drawFrets ( QPainter* p ) const;
+
+ void drawStrings ( QPainter* p ) const;
+
+ unsigned int getTopBorder ( unsigned int imgHeight ) const;
+
+ unsigned int getBottomBorder ( unsigned int imgHeight ) const;
+
+ unsigned int getLeftBorder ( unsigned int imgWidth ) const;
+
+ unsigned int getRightBorder ( unsigned int imgWidth ) const;
+
+ unsigned int getGuitarChordWidth ( int imgWidth ) const;
+
+ unsigned int getGuitarChordHeight ( int imgHeight ) const;
+
+ unsigned int getFontPixelSize ( int imgWidth, int imgHeight ) const;
+
+ std::pair<bool, unsigned int>
+ getStringNumber ( int imgWidth,
+ unsigned int x_pos,
+ unsigned int string_num ) const;
+
+ std::pair<bool, unsigned int>
+ getFretNumber ( int imgHeight,
+ unsigned int y_pos,
+ unsigned int maxFretNum ) const;
+
+ QRect getTransientNoteSymbolRect(QSize guitarChordSize,
+ unsigned int stringNb,
+ int fretNb) const;
+
+ static void drawFingeringPixmap(const Fingering& fingering, const NoteSymbols& noteSymbols, QPainter *p);
+
+private:
+
+ posPair
+ getX ( int imgWidth, unsigned int stringNb, unsigned int nbOfStrings ) const;
+
+ posPair
+ getY ( int imgHeight, unsigned int fretNb, unsigned int nbOfFrets ) const;
+
+
+ unsigned int m_nbOfStrings;
+ unsigned int m_nbOfFrets;
+
+};
+
+} /* namespace Guitar */
+
+}
+
+#endif /* SYMBOLS_H_ */
+