import QtQuick 2.9 import QtQuick.Window 2.3 import QtQuick.Controls 1.5 import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.2 import QtQuick.Layouts 1.2 import QtQuick.Dialogs 1.0 import Qt.labs.settings 1.0 import QtQml 2.8 import QtQuick.XmlListModel 2.0 import FileIO 3.0 import MuseScore 3.0 MuseScore { /* version: "2.0" */ width: 390; height: 400; property string loginUrl: "https://www.musicalion.com/[lng]/scores/members/login/service" property string uploadUrl: "https://www.musicalion.com/ser/files?musicalion_client_app=muse_score" property string translateUrl: "https://www.musicalion.com/[lng]/admin/translations/locale/ajax?type=service&oper=get&object=musescoreTranslate&language=" property string editFormUrl: "http://www.musicalion.com/[lng]/scores/notes/music-upload/edit?resetpath=1&layout=popup&PHPSESSID=" property string pluginUrl: "http://www.musicalion.com/musescore/plugins/publisher" property string imageUrl: "https://www.musicalion.com/images/" property string aboutUrl: "https://www.musicalion.com/[lng]/scores/notes/info/contribute" property string registerUrl: "https://www.musicalion.com/[lng]/configuration/members/member/sign-up1?cpn=CONTRMUS123" property string sessionId property string fileData property bool isQuit: false property bool isNotStop: true property bool isEditForm: false property string lng: Qt.locale().name.substring(0,2) property bool iniFileExist: true property variant fileTypes: ['mscz', 'musicxml', 'pdf', 'mid'] property variant translations: [] property variant k; Settings { // id: settings; category: "MusicalionPublisherPlugin" // fileName: scoreFl.tempPath() + "/userData.dat" property alias userName: loginIn.text property alias userPassword: passwordIn.text } function qsTr1(source) { if (translations[source] !== undefined) { return translations[source] } else { return source } } //-- onRun: { lng = ((lng === "de" || lng === "es" || lng === "ru")?(lng):("en")) loginUrl = loginUrl.replace("[lng]", lng) uploadUrl = uploadUrl.replace("[lng]", lng) translateUrl = translateUrl.replace("[lng]", lng) editFormUrl = editFormUrl.replace("[lng]", lng) aboutUrl = aboutUrl.replace("[lng]", lng) registerUrl = registerUrl.replace("[lng]", lng) translateXlm.source = translateUrl + lng + "&token=" + Date.parse(Date()) / 1000 translateXlm.reload() loginIn.text = loginIn.text.trim() passwordIn.text = passwordIn.text.trim() if (loginIn.text === "" || passwordIn.text === "") { return } checkConnection() } //-- Rectangle { id: mainRc color: "#EEEEEE" width: parent.width anchors.fill: parent visible: false Column { id: mainGr anchors.fill: parent padding: 5 rightPadding: 5 anchors.rightMargin: 10 spacing: 5 Image { source: imageUrl + "logo-01.png" anchors.horizontalCenter: parent.horizontalCenter } Rectangle { height: 2 Layout.fillWidth: true y: 5 width: parent.width color: 'green' } Text { id: text1 width: parent.width wrapMode: Text.WordWrap horizontalAlignment: Text.AlignJustify text: qsTr1("Musicalion is managed music library with legal sheet music which allows there members to download and use the content.") } Text { id: text2 width: parent.width wrapMode: Text.WordWrap text: qsTr1("Each download will be renumerated to the contributor in cash.") } Text { id: text3 width: parent.width font.pixelSize: 14 text: "" + qsTr1("More information...") + "" onLinkActivated: Qt.openUrlExternally(link) MouseArea { anchors.fill: parent acceptedButtons: Qt.NoButton cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor } } GridLayout { id: loginGr rows: 3 columns: 3 rowSpacing: 5 columnSpacing: 5 Layout.margins: 5 anchors.horizontalCenter: parent.horizontalCenter Label { id: text4 text: qsTr1("Login") font.pixelSize: 14 anchors.margins: 5 } TextField { id: loginIn implicitWidth: 200 font.pixelSize: 14 maximumLength: 20 // text: settings.value("userName") } Button { id: connectBt Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter style: ButtonStyle { label: Text { font.pixelSize: 14 text: control.text } } text: qsTr1("Connect") onClicked: { checkConnection() } } Label { id: text5 text: qsTr1("Password") font.pixelSize: 14 } TextField { id: passwordIn implicitWidth: 200 font.pixelSize: 14 maximumLength: 20 echoMode: TextInput.Password // text: settings.value("userPassword") } Text { text: " " } Text { id: text6 font.pixelSize: 14 Layout.columnSpan: 3 text: "" + qsTr1("or register for free") + "" onLinkActivated: Qt.openUrlExternally(link) MouseArea { anchors.fill: parent acceptedButtons: Qt.NoButton cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor } } } Row { id: connectRw visible: false spacing: 20 anchors.horizontalCenter: parent.horizontalCenter Text { id: loginTx anchors.verticalCenter: parent.verticalCenter } Button { id: logoutBt text: qsTr1("Log out") style: ButtonStyle { label: Text { font.pixelSize: 14 text: control.text } } onClicked: { logMd.insert(0, {record: "--- *** ---"}) logMd.insert(0, {record: qsTr1("User ") + loginIn.text + qsTr1(" was disconnected.")}) connectRw.visible = false loginGr.visible = true loginIn.text = "" passwordIn.text = "" uploadBt.visible = false sessionId = "" } } } Button { id: uploadBt anchors.horizontalCenter: parent.horizontalCenter style: ButtonStyle { label: Text { font.pixelSize: 14 text: control.text } } text: qsTr1("Upload composition") visible: false onClicked: { k = -1 fileUpload() } } ListModel { id: logMd } Label { id: text7 text: qsTr1("Log history:") font.underline: true font.pixelSize: 14 anchors.horizontalCenter: parent.horizontalCenter } Rectangle { height: parent.height width: parent.width border.color: "black" ListView { id: historyLv height: parent.height // no scrolling width: parent.width model: logMd delegate: Text { width: parent.width padding: 5 text: record wrapMode: Text.WordWrap } } } } } //-- FileIO { id: scoreFl onError: { iniFileExist = false console.log(msg + " Filename = " + scoreFl.source) } } //-- FileDialog { id: fileDl title: qsTr1("Please choose a score") nameFilters: [ "Musescore 3 " + qsTr1("formats") + " (*.mscz *.mscx)"] onAccepted: { var filename = fileDl.fileUrl if(filename){ scoreFl.source = filename fileTx.text = filename uploadBt.enabled = true uploadBt.opacity = 1 } } } //-- MessageDialog { id: messageDl title: "" text: "" onAccepted: { if (isEditForm && isNotStop) { isNotStop = false Qt.openUrlExternally(editFormUrl + sessionId) } if (isQuit) { Qt.quit() } } } //-- XmlListModel { id: translateXlm query: "/root/message" XmlRole { name: "source"; query: "source/string()"; isKey: true } XmlRole { name: "translation"; query: "translation/string()" } onStatusChanged: { if (status === XmlListModel.Ready && progress === 1.0) { for(var i = 0; i < translateXlm.count; i++){ var o = translateXlm.get(i); translations[o.source] = o.translation } text1.text = qsTr1(text1.text) text2.text = qsTr1(text2.text) text3.text = "" + qsTr1("More information...") + "" text4.text = qsTr1(text4.text) text5.text = qsTr1(text5.text) text6.text = "" + qsTr1("or register for free") + "" text7.text = qsTr1(text7.text) connectBt.text = qsTr1(connectBt.text) logoutBt.text = qsTr1(logoutBt.text) uploadBt.text = qsTr1(uploadBt.text) mainRc.visible = true } } } //-- function checkConnection() { // settings.setValue("userName","") // settings.setValue("userPassword","") loginIn.text = loginIn.text.trim(); passwordIn.text = passwordIn.text.trim(); if (loginIn.text == "" || passwordIn.text == "") { alertError(qsTr1("Please enter your username and password")) return; } logMd.insert(0, {record: "--- *** ---"}) logMd.insert(0, {record: qsTr1("Open connection to musicalion.com ...")}) sessionId = ""; var request = new XMLHttpRequest() request.open("POST", loginUrl) request.setRequestHeader("MusicalionClientType", "MusescorePlugin"); request.onreadystatechange = function() { if (request.readyState === XMLHttpRequest.DONE) { if (request.status && request.status === 200) { if (request.responseText.toLowerCase().indexOf("error") >= 0) { logMd.insert(0, {record: "--- *** ---"}) logMd.insert(0, {record: qsTr1("User") + " [ " + loginIn.text + " ] " + qsTr1("not connected with error:") + " " + request.responseText}) alertError(request.responseText) return; } sessionId = request.responseText loginGr.visible = false loginTx.text = qsTr1("You are logged in as ") + " " + loginIn.text connectRw.visible = true uploadBt.visible = true // settings.setValue("userName", loginIn.text) // settings.setValue("userPassword", passwordIn.text) logMd.insert(0, {record: "--- *** ---"}) logMd.insert(0, {record: qsTr1("User") + " [ " + loginIn.text + " ] " + qsTr1("connected")}) } else { logMd.insert(0, {record: "--- *** ---"}) logMd.insert(0, {record: qsTr1("User") + " [ " + loginIn.text + " ] " + qsTr1("not connected with error:") + " " + request.responseText}) alertError(request.responseText) } } } request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') request.send("username=" + encodeURIComponent(loginIn.text) + "&password=" + encodeURIComponent(passwordIn.text)) } function logMessage(txt) { logMd.insert(0, {record: "--- *** ---"}) logMd.insert(0, {record: txt}) } //-- function alertError(txt) { messageDl.text = txt messageDl.title = qsTr1("Error") messageDl.icon = StandardIcon.Critical messageDl.standardButtons = StandardButton.Ok messageDl.open() } //-- function alertWarning(txt) { messageDl.text = txt messageDl.title = qsTr1("Warning") messageDl.icon = StandardIcon.Warning messageDl.standardButtons = StandardButton.Ok messageDl.open() } //-- function alertInfo(txt) { messageDl.text = txt messageDl.title = qsTr1("Information") messageDl.icon = StandardIcon.Information messageDl.standardButtons = StandardButton.Ok messageDl.open() } //-- function confirm(txt) { messageDl.text = txt messageDl.title = qsTr1("Information") messageDl.icon = StandardIcon.Information messageDl.standardButtons = StandardButton.Ok messageDl.open() } //-- function fileUpload() { k++ if (k > 3) { logMd.insert(0, {record: "--- *** ---"}) logMd.insert(0, {record: qsTr1("The file upload process is complete.")}) isQuit = true isEditForm = true alertInfo(qsTr1("The file upload process is complete.") + " " + qsTr1("The plugin will be closed.")) return; } var CRLF = '\r\n' var boundary = "---------" + String(Math.random()).slice(2) + 'BouNdaRy' var endBuf = CRLF + '--' + boundary + '--' + CRLF writeScore(curScore, scoreFl.tempPath() + "/" + curScore.scoreName, fileTypes[k]) logMd.insert(0, {record: "--- *** ---"}) logMd.insert(0, {record: qsTr1("Uploading file") + ": [" + curScore.scoreName + "." + fileTypes[k] + "] " + qsTr1("started") + "..."}) var prefBuf = [] prefBuf.push('') prefBuf.push('--' + boundary) prefBuf.push('Content-Disposition: form-data; name="files[]"; filename="' + encodeURIComponent(curScore.scoreName) + '.' + ((fileTypes[k] === "musicxml")?("xml"):(fileTypes[k])) + '"') prefBuf.push('Content-Type: application/binary') prefBuf.push('') var startBuf = prefBuf.join(CRLF) + CRLF var rawFile = new XMLHttpRequest() rawFile.responseType = "arraybuffer" rawFile.onreadystatechange = function () { if(rawFile.readyState === 4) { if(rawFile.status === 200 || rawFile.status === 0) { var arrayBuffer = rawFile.response var uint8Array = new Uint8Array(arrayBuffer) var bodyArray = new Uint8Array(startBuf.length + uint8Array.byteLength + endBuf.length) var j = 0; for (; j < startBuf.length; j++) { bodyArray[j] = startBuf.charCodeAt(j) } for (var i = 0; i < uint8Array.byteLength; i++, j++) { bodyArray[j] = uint8Array[i] } for (i = 0; i < endBuf.length; i++, j++) { bodyArray[j] = endBuf.charCodeAt(i) } var request = new XMLHttpRequest() request.open('POST', uploadUrl, true, encodeURIComponent(loginIn.text), encodeURIComponent(passwordIn.text)) request.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary) request.setRequestHeader("Content-length", bodyArray.byteLength) request.setRequestHeader("MusicalionClientType", "MusescorePlugin"); request.onreadystatechange = function() { if (request.readyState === XMLHttpRequest.DONE) { if (request.status && request.status === 200) { if (request.responseText.toLowerCase().indexOf("error") >= 0) { logMd.insert(0, {record: "--- *** ---"}) logMd.insert(0, {record: qsTr1("File") + " [" + curScore.scoreName + "." + fileTypes[k] + "] " + qsTr1("uploading error") + ":" + " " + request.responseText}) return; } logMd.insert(0, {record: "--- *** ---"}) logMd.insert(0, {record: qsTr1("File") + " [" + curScore.scoreName + "." + fileTypes[k] + "] " + qsTr1("successfully uploaded.")}) } else { logMd.insert(0, {record: "--- *** ---"}) logMd.insert(0, {record: qsTr1("File") + " [" + curScore.scoreName + "." + fileTypes[k] + "] " + qsTr1("uploading error") + ":" + " " + request.responseText}) return } //-- recursion -- fileUpload() } } request.send(bodyArray.buffer) } } } rawFile.open("GET", "file:///" + scoreFl.tempPath() + "/" + curScore.scoreName + "." + fileTypes[k], true) rawFile.setRequestHeader("MusicalionClientType", "MusescorePlugin"); rawFile.send(null); } //-- function readIniFile() { var flIni = scoreFl.read(); if (flIni === "") { iniFileExist = false; return } } //-- function saveIniFile() { var iniXml = "" + loginIn.text + "" + passwordIn.text + ""; scoreFl.write(iniXml) console.log(scoreFl.source) } }