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)
}
}