//============================================== // MuseScore // // Quena Notation plugin for MuseScore Ver. 4.4 and later Ver4.6 (2026.4.2) // // Copyright (C)2012-2026 Hiroshi Tachibana // // // 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 3 of the License, or // (at your option) any later version. // // 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, see . //============================================== import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import MuseScore 3.0 MuseScore { menuPath: "Plugins.Quena Fingerings" version: "2026.4.2" description: "Quena fingerings, Note names" pluginType: "dialog" id: window width:220 // menu window size height:400 // グローバル変数 property var quenaLength property var fontNum property var fontSizeF // 運指のフォントサイズ property var fontSizeT // 文字のフォントサイズ property var yPosition property var xPosition property var partNum property var colorNum property var fontName: [ "QuenaBoliviav2","Doremi","Doremib","Helvetica" ] property var iOct property var normReal ColumnLayout { RowLayout { //====================== Length Label { text: " Quena type" } ComboBox { id: quenaLengthList currentIndex: 12 model: ListModel { ListElement { text: "High G5" } ListElement { text: "High F#5" } ListElement { text: "High F5" } ListElement { text: "High E5" } ListElement { text: "High D#5" } ListElement { text: "High D5" } ListElement { text: "C#5" } ListElement { text: "C5" } ListElement { text: "B4" } ListElement { text: "A#4" } ListElement { text: "A4" } ListElement { text: "G#4" } ListElement { text: "G4 =====" } ListElement { text: "F#4" } ListElement { text: "F4" } ListElement { text: "E4" } ListElement { text: "D#4" } ListElement { text: "D4" } ListElement { text: "Low C#4" } ListElement { text: "Low C4" } ListElement { text: "Low B3" } ListElement { text: "Low A#3" } ListElement { text: "Low A3" } ListElement { text: "Low G#3" } ListElement { text: "Low G3" } } } // end ComboBox } RowLayout { //====================== Font type, Fingering or Note name Label { text: " Display" } ComboBox { id: fontList currentIndex: 0 // 初期設定を変更できます。 model: ListModel { ListElement { text: "DoReMi+Fingering" } ListElement { text: "CDE+Fingering" } ListElement { text: "Fingering" } ListElement { text: "DoReMi" } ListElement { text: "CDEFG" } } } // end ComboBox } RowLayout { //====================== 音程 通常/実音程 G管の筒音G3とするのが通常、G4とするのが実音程 Label { text: " 通常/実音" } ComboBox { id: normReal currentIndex: 0 // 初期設定を変更できます。 model: ListModel { ListElement { text: " 通常" } ListElement { text: " 実音程" } } } // end ComboBox } RowLayout { //====================== FONT SIZE運指 Label { text: " Fingering Font Size" } SpinBox { id: valFingFontSize implicitWidth: 55 from: 12 to: 128 stepSize: 1 value: 42 // 初期設定を変更できます。 } } RowLayout { //====================== FONT SIZE文字 Label { text: " Text Font Size " } SpinBox { id: valTextFontSize implicitWidth: 55 from: 4 to: 48 stepSize: 1 value: 14 // 初期設定を変更できます。 } } RowLayout { //====================== Y POSITION Label { text: " Y position +↓" } SpinBox { id: valYPosition implicitWidth: 60 from: -20 to: 30 value: 0 // 初期設定を変更できます。 stepSize: 1 } } RowLayout { //====================== X POSITION Label { text: " X position +→" } SpinBox { id: valXPosition implicitWidth: 60 from: -5 to: 5 value: 0 // 初期設定を変更できます。 stepSize: 1 } } RowLayout { //====================== PART Label { text: " Part" } ComboBox { id: partList currentIndex: 0 // 初期設定を変更できます。 model: ListModel { ListElement { text: "Part 1" } ListElement { text: "Part 2" } ListElement { text: "Part 3" } ListElement { text: "Part 4" } } } } RowLayout { //====================== COLOR Label { text: " Color" } ComboBox { id: colorList currentIndex: 0 // 初期設定を変更できます。 model: ListModel { ListElement { text: "Black" } ListElement { text: "Red" } ListElement { text: "Blue" } ListElement { text: "Green" } ListElement { text: "Purple" } ListElement { text: "Gray" } } } } RowLayout { //============ Ver. No. ================ Label { font.pointSize: 8 text: " V"+version+" tcbnhrs
運指監修:柳内淳一" } } Button { Layout.alignment: Qt.AlignRight Layout.preferredWidth: 80 text: "Cancel" onClicked: { quit() } } Button { Layout.alignment: Qt.AlignRight Layout.preferredWidth: 80 text: "OK" onClicked: { quit() main() curScore.startCmd() curScore.endCmd() } highlighted: true } } // end of ColumnLayout function main() { curScore.startCmd() quenaLength=quenaLengthList.currentIndex-12 fontNum = fontList.currentIndex fontSizeF = valFingFontSize.value fontSizeT = valTextFontSize.value yPosition = valYPosition.value xPosition = valXPosition.value partNum = partList.currentIndex colorNum = colorList.currentIndex if(normReal.currentIndex==0) iOct=24 if(normReal.currentIndex==1) iOct=12 applyToSelection() curScore.endCmd() } onRun: { if (typeof curScore === 'undefined') quit(); } // end onRun //*************************************************************************** function applyToSelection() { curScore.startCmd() var cursor = curScore.newCursor(); var startStaff; var endStaff; var endTick; var fullScore = false; var xPos = xPosition var yPosF = yPosition+14 var yPosT = yPosition+6 var fingerings = [ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", // G4=67から "Q", "R", "S", "T", "U", "V", "W", "X","Y", "Z", "a", "b", "c", "d", // "e", "f", "g", "h", "i", "j", "k"] // 1-37 // 3オクターブのG ソまで, "l", "m", "n", "o", "p", "q", "r"] // 1- 44 (0-43) length=44 var noteNameS = [ "C","C#","D","D#","E","F","F#","G","G#","A","A#","B" ] var noteNameF = [ "C","Db","D","Eb","E","F","Gb","G","Ab","A","Bb","B" ] // RGB color Black , Red , Blue , Green , Purple , Gray var colorData= [ "#000000" ,"#FF0000" ,"#0000FF" ,"#00D000" ,"#C007C0" ,"#888888" ]; var fontColor=colorData[colorNum]; var fontFaceTag =""; var fontFaceTagS=""; var fontFaceTagF=""; var fontFaceTagE=""; var selPart=0; cursor.rewind(1); // 選択範囲の最初に移動 if (!cursor.segment) { // 選択がない場合 fullScore = true; startStaff = 0; // 最初 endStaff = curScore.nstaves - 1; // 終わり } else { startStaff = cursor.staffIdx; cursor.rewind(2); // 選択範囲の最後 if (cursor.tick == 0) { endTick = curScore.lastSegment.tick + 1; } else { endTick = cursor.tick; } endStaff = cursor.staffIdx; } for (var staff = startStaff; staff <= endStaff; staff++) { // 対象となった音符の最初から最後まで // for (var voice = 0; voice < 4; voice++) { // var voice=partNum; // 声部の指定 cursor.rewind(1); // beginning of selection cursor.voice = partNum; // 声部の指定 cursor.staffIdx = staff; if (fullScore) cursor.rewind(0); // 選択範囲がない場合は先頭から while (cursor.segment && (fullScore || cursor.tick < endTick)) { if (cursor.element && cursor.element.type == Element.CHORD) { var text = newElement(Element.STAFF_TEXT); // 指使い表示用 var text2 = newElement(Element.STAFF_TEXT); // ドレミ、CDE用 text.placement = Placement.BELOW text.autoplace = false; // add 2026.3.29 text2.placement = Placement.BELOW // add 2026.3.29 text2.autoplace = false; // add 2026.3.29 // ######################## GRACE ##################################### //#################################################################### var notes = cursor.element.notes; var pitchFing; var fontSizeTag; for (var i = 0; i < notes.length; i++) { // 和音の場合のループ // for (var i = 0; i < 1;i++) { // 和音の場合は、一番下の音のみ if(notes[i].tieBack == null ) { // タイの後ろ側の音譜でない場合 if(fontNum==2) { // 指使いのみの表示------------------------------------- pitchFing=notes[i].pitch+quenaLength -67-12+iOct; // 67=G4 , 12=G管 if(pitchFing<0 || pitchFing>=fingerings.length) { // text.text=" "+text.text; // 演奏可能な音域外の場合 } else{ text.text = fingerings[pitchFing]+text.text ; text.color = fontColor; text.offsetX = xPos; text.offsetY = yPosF-3; // 指使いのみの表示を少し上へ fontSizeTag=""; text.fontSize=fontSizeF text.text = fontSizeTag + fontFaceTag + text.text; // 指使い } text.placement = Placement.BELOW; // added 2023.6.25 text.autoplace = false; // added 2023.6.25 text2.placement = Placement.BELOW; // added 2023.6.25 text2.autoplace = false; // added 2023.6.25 if(i == notes.length-1) cursor.add(text); // if文としないと、MuseScoreがクラッシュする。 } else if(fontNum==1) { // 指使いとCDE --------------------------------- pitchFing=notes[i].pitch+quenaLength -67-12+iOct; if(pitchFing<0 || pitchFing>=fingerings.length) { // 演奏可能な音域外の場合は半角スペース } else{ // 演奏可能な音内の場合 // 運指 text.text = fingerings[pitchFing]+text.text ; // 運指の文字コードを与える text.color = fontColor; // 運指の色を与える text.offsetX = xPos; // 運指のX方向位置を与える text.offsetY = yPosF; // 運指のY方向位置を与える fontSizeTag=""; // 運指図の場合、文字サイズを拡大 text.fontSize=fontSizeF text.text = fontSizeTag + fontFaceTag + text.text; // 文字サイズと運指用フォント名を与える // CDE if(notes[i].tpc>=6 && notes[i].tpc<=12 ) { // プロパティーtpcで判定、 flat ♭の場合 text2.text=noteNameF[(notes[i].pitch % 12)] +text2.text; // ♭場合の英語音名を与える } else if ( notes[i].tpc>=20 && notes[i].tpc<=26 ){ // sharp ♯の場合 text2.text=noteNameS[(notes[i].pitch % 12)] +text2.text ; // ♯場合の英語音名を与える } else{ // ♯♭でない場合は、♯♭どちらのフォントでもよい text2.text=noteNameF[(notes[i].pitch % 12)] +text2.text; } text2.color= fontColor; // 英語音名の色を与える text2.offsetX= xPos; // 英語音名のX方向位置を与える text2.offsetY = yPosT; // 英語音名のY方向位置を与える fontSizeTag=""; text2.fontSize=fontSizeT text2.text= fontSizeTag + fontFaceTagE + text2.text; // 文字サイズと英語音名用フォント名を与える } text.placement = Placement.BELOW; // added 2023.6.25 text.autoplace = false; // added 2023.6.25 text2.placement = Placement.BELOW; // added 2023.6.25 text2.autoplace = false; // added 2023.6.25 if(i == notes.length-1) cursor.add(text); // 運指を表示する if(i == notes.length-1) cursor.add(text2); // CDEを表示する } else if(fontNum==0) { // 指使いとドレミDoReMi--------------------------- pitchFing=notes[i].pitch+quenaLength -67-12+iOct; if(pitchFing<0 || pitchFing>=fingerings.length) { // 演奏可能な音域外の場合 } else{ // 演奏可能な音内の場合 // 運指 text.text = fingerings[pitchFing]+text.text ; text.color = fontColor; text.offsetX = xPos; text.offsetY = yPosF; text.fontSize=fontSizeF fontSizeTag=""; text.text = fontSizeTag +fontFaceTag+ text.text; // ドレミ // pitchFing=(notes[i].pitch +quenaLength) % 12 ; //移動ドに対応する場合 pitchFing=(notes[i].pitch ) % 12 ; text2.text=fingerings[pitchFing]+text2.text ; fontSizeTag=""; if(notes[i].tpc>=6 && notes[i].tpc<=12 ) { // Flat ドレミ♭ text2.text= fontSizeTag + fontFaceTagF + text2.text; } else if ( notes[i].tpc>=20 && notes[i].tpc<=26 ){ // Sharp ドレミ♯ text2.text= fontSizeTag + fontFaceTagS + text2.text; } else { text2.text= fontSizeTag + fontFaceTagS + text2.text; text2.text= fontSizeTag + fontFaceTagS + text2.text; } text2.color = fontColor; text2.offsetX = xPos; text2.offsetY = yPosT text2.fontSize=fontSizeT } text.placement = Placement.BELOW; // added 2023.6.25 text.autoplace = false; // added 2023.6.25 text2.placement = Placement.BELOW; // added 2023.6.25 text2.autoplace = false; // added 2023.6.25 if(i == notes.length-1) cursor.add(text); if(i == notes.length-1) cursor.add(text2); } else if(fontNum==4) { // CDEのみ---------------------------------- if ( i > 0 ) text2.text = "\n"+ text2.text; // 和音の場合は、順次改行して縦に表示する。 if(notes[i].tpc>=6 && notes[i].tpc<=12 ) { // flat ♭の場合 text2.text=noteNameF[(notes[i].pitch % 12)] +text2.text; // ♭場合の英語音名を与える } else if ( notes[i].tpc>=20 && notes[i].tpc<=26 ){ // sharp ♯の場合 text2.text=noteNameS[(notes[i].pitch % 12)] +text2.text ; } else{ text2.text=noteNameF[(notes[i].pitch % 12)] +text2.text ; } text2.color= fontColor; text2.offsetX = xPos; text2.offsetY = yPosT; text2.fontSize=fontSizeT fontSizeTag=""; text2.text= fontSizeTag + fontFaceTagE + text2.text; text.placement = Placement.BELOW; // added 2023.6.25 text.autoplace = false; // added 2023.6.25 text2.placement = Placement.BELOW; // added 2023.6.25 text2.autoplace = false; // added 2023.6.25 if(i == notes.length-1) cursor.add(text2); } else if(fontNum==3) { // DoReMiのみ------------------------------- if ( i > 0 ) text2.text = "\n"+ text2.text; // 和音の場合は、順次改行して縦に表示する。 // pitchFing=(notes[i].pitch +quenaLength) % 12 ; pitchFing=(notes[i].pitch) % 12 ; text2.text=fingerings[pitchFing]+text2.text ; fontSizeTag=""; // 英語音名より少し小さめとする。 if(notes[i].tpc>=6 && notes[i].tpc<=12 ) { // Flat ドレミ♭ text2.text= fontSizeTag + fontFaceTagF + text2.text; } else if ( notes[i].tpc>=20 && notes[i].tpc<=26 ) { // Sharp ドレミ♯ text2.text= fontSizeTag + fontFaceTagS + text2.text; } else { text2.text= fontSizeTag + fontFaceTagS + text2.text; } text2.color = fontColor; text2.offsetX = xPos; text2.offsetY = yPosT; text2.fontSize=fontSizeT text.placement = Placement.BELOW; // added 2023.6.25 text.autoplace = false; // added 2023.6.25 text2.placement = Placement.BELOW; // added 2023.6.25 text2.autoplace = false; // added 2023.6.25 if(i == notes.length-1) cursor.add(text2); } } // end != Tie /* switch (voice) { case 0: text.pos.y = yPos; break; case 1: text.pos.y = yPos+2; break; case 2: text.pos.y = yPos+4; break; case 3: text.pos.y = yPos+6; break; } */ } // end for note i 和音 } // end if CHORD cursor.next(); // 次の音符へ移動する } // end while segment } // end for staff curScore.endCmd() quit(); } // end apply } // end MuseScore