lumina/src/qml/presenter/SongEditor.qml

393 lines
13 KiB
QML

import QtQuick 2.13
import QtQuick.Controls 2.15 as Controls
import Qt.labs.platform 1.1 as Labs
import QtQuick.Dialogs 1.3
import QtQuick.Layouts 1.2
import org.kde.kirigami 2.13 as Kirigami
import "./" as Presenter
Item {
id: root
property int songIndex
property string songTitle
property string songLyrics
property string songAuthor
property string songCcli
property string songAudio
property string songVorder
property string songBackground
property string songBackgroundType
property string songHAlignment
property string songVAlignment
GridLayout {
id: mainLayout
anchors.fill: parent
columns: 2
rowSpacing: 5
columnSpacing: 0
Controls.ToolBar {
Layout.fillWidth: true
Layout.columnSpan: 2
id: toolbar
RowLayout {
anchors.fill: parent
Controls.ComboBox {
model: Qt.fontFamilies()
implicitWidth: 300
editable: true
hoverEnabled: true
/* onCurrentTextChanged: showPassiveNotification(currentText) */
}
Controls.SpinBox {
editable: true
from: 5
to: 72
hoverEnabled: true
}
Controls.ComboBox {
id: hAlignmentBox
model: ["Left", "Center", "Right", "Justify"]
implicitWidth: 100
hoverEnabled: true
onActivated: updateHorizontalTextAlignment(currentText.toLowerCase());
}
Controls.ComboBox {
id: vAlignmentBox
model: ["Top", "Center", "Bottom"]
implicitWidth: 100
hoverEnabled: true
onActivated: updateVerticalTextAlignment(currentText.toLowerCase());
}
Controls.ToolButton {
text: "B"
hoverEnabled: true
visible: false
}
Controls.ToolButton {
text: "I"
hoverEnabled: true
visible: false
}
Controls.ToolButton {
text: "U"
hoverEnabled: true
visible: false
}
Controls.ToolSeparator {}
Item { Layout.fillWidth: true }
Controls.ToolSeparator {}
Controls.ToolButton {
text: "Effects"
icon.name: "image-auto-adjust"
hoverEnabled: true
onClicked: {}
}
Controls.ToolButton {
id: backgroundButton
text: "Background"
icon.name: "fileopen"
hoverEnabled: true
onClicked: backgroundTypePopup.open()
}
Controls.Popup {
id: backgroundTypePopup
x: backgroundButton.x
y: backgroundButton.y + backgroundButton.height + 20
modal: true
focus: true
dim: false
background: Rectangle {
Kirigami.Theme.colorSet: Kirigami.Theme.Tooltip
color: Kirigami.Theme.backgroundColor
radius: 10
border.color: Kirigami.Theme.activeBackgroundColor
border.width: 2
}
closePolicy: Controls.Popup.CloseOnEscape | Controls.Popup.CloseOnPressOutsideParent
ColumnLayout {
anchors.fill: parent
Controls.ToolButton {
Layout.fillHeight: true
Layout.fillWidth: true
text: "Video"
icon.name: "emblem-videos-symbolic"
onClicked: videoFileDialog.open() & backgroundTypePopup.close()
}
Controls.ToolButton {
Layout.fillWidth: true
Layout.fillHeight: true
text: "Image"
icon.name: "folder-pictures-symbolic"
onClicked: imageFileDialog.open() & backgroundTypePopup.close()
}
}
}
}
}
Controls.SplitView {
Layout.fillHeight: true
Layout.fillWidth: true
Layout.columnSpan: 2
handle: Item{
implicitWidth: 6
Rectangle {
height: parent.height
anchors.horizontalCenter: parent.horizontalCenter
width: 1
color: Controls.SplitHandle.hovered ? Kirigami.Theme.hoverColor : Kirigami.Theme.backgroundColor
}
}
ColumnLayout {
Controls.SplitView.fillHeight: true
Controls.SplitView.preferredWidth: 500
Controls.SplitView.minimumWidth: 500
Controls.TextField {
id: songTitleField
Layout.preferredWidth: 300
Layout.fillWidth: true
Layout.leftMargin: 20
Layout.rightMargin: 20
placeholderText: "Song Title..."
text: songTitle
padding: 10
onEditingFinished: updateTitle(text);
}
Controls.TextField {
id: songVorderField
Layout.preferredWidth: 300
Layout.fillWidth: true
Layout.leftMargin: 20
Layout.rightMargin: 20
placeholderText: "verse order..."
text: songVorder
padding: 10
onEditingFinished: updateVerseOrder(text);
}
Controls.ScrollView {
id: songLyricsField
Layout.preferredHeight: 3000
Layout.fillWidth: true
Layout.fillHeight: true
Layout.leftMargin: 20
rightPadding: 20
Controls.TextArea {
id: lyricsEditor
width: parent.width
placeholderText: "Put lyrics here..."
persistentSelection: true
text: songLyrics
textFormat: TextEdit.PlainText
padding: 10
onEditingFinished: {
updateLyrics(text);
editorTimer.running = false;
}
onPressed: editorTimer.running = true
}
}
Controls.TextField {
id: songAuthorField
Layout.fillWidth: true
Layout.preferredWidth: 300
Layout.leftMargin: 20
Layout.rightMargin: 20
placeholderText: "Author..."
text: songAuthor
padding: 10
onEditingFinished: updateAuthor(text)
}
}
ColumnLayout {
Controls.SplitView.fillHeight: true
Controls.SplitView.preferredWidth: 700
Controls.SplitView.minimumWidth: 300
Presenter.SlideEditor {
id: slideEditor
Layout.preferredWidth: 500
Layout.fillWidth: true
Layout.preferredHeight: slideEditor.width / 16 * 9
Layout.bottomMargin: 30
Layout.rightMargin: 20
Layout.leftMargin: 20
}
}
}
}
Timer {
id: editorTimer
interval: 1000
repeat: true
running: false
onTriggered: {
updateLyrics(lyricsEditor.text);
}
}
FileDialog {
id: videoFileDialog
title: "Please choose a background"
folder: shortcuts.home
selectMultiple: false
nameFilters: ["Video files (*.mp4 *.mkv *.mov *.wmv *.avi *.MP4 *.MOV *.MKV)"]
onAccepted: {
updateBackground(videoFileDialog.fileUrls[0], "video");
print("video background = " + videoFileDialog.fileUrls[0]);
}
onRejected: {
print("Canceled")
}
}
FileDialog {
id: imageFileDialog
title: "Please choose a background"
folder: shortcuts.home
selectMultiple: false
nameFilters: ["Image files (*.jpg *.jpeg *.png *.JPG *.JPEG *.PNG)"]
onAccepted: {
updateBackground(imageFileDialog.fileUrls[0], "image");
print("image background = " + imageFileDialog.fileUrls[0]);
}
onRejected: {
print("Canceled")
}
}
function changeSong(index) {
const song = songsqlmodel.getSong(index);
songIndex = index;
songTitle = song.title;
songLyrics = song.lyrics;
songAuthor = song.author;
songCcli = song.ccli;
songAudio = song.audio;
songVorder = song.vorder;
songBackground = song.background;
songBackgroundType = song.backgroundType;
songHAlignment = song.horizontalTextAlignment;
songVAlignment = song.verticalTextAlignment;
alignmentSetTimer.restart();
if (songBackgroundType == "image") {
slideEditor.videoBackground = "";
slideEditor.imageBackground = songBackground;
} else {
slideEditor.imageBackground = "";
slideEditor.videoBackground = songBackground;
slideEditor.loadVideo();
}
changeSlideHAlignment(songHAlignment);
changeSlideVAlignment(songVAlignment);
print(song);
}
function updateLyrics(lyrics) {
songsqlmodel.updateLyrics(songIndex, lyrics);
print(lyrics);
}
function updateTitle(title) {
songsqlmodel.updateTitle(songIndex, title)
}
function updateAuthor(author) {
songsqlmodel.updateAuthor(songIndex, author)
}
function updateAudio(audio) {
songsqlmodel.updateAudio(songIndex, audio)
}
function updateCcli(ccli) {
songsqlmodel.updateCcli(songIndex, ccli)
}
function updateVerseOrder(vorder) {
songsqlmodel.updateVerseOrder(songIndex, vorder)
}
function updateBackground(background, backgroundType) {
songsqlmodel.updateBackground(songIndex, background);
songsqlmodel.updateBackgroundType(songIndex, backgroundType);
print("changed background");
}
function updateHorizontalTextAlignment(textAlignment) {
if (alignmentSetTimer.running)
return;
changeSlideHAlignment(textAlignment);
songsqlmodel.updateHorizontalTextAlignment(songIndex, textAlignment);
}
function updateVerticalTextAlignment(textAlignment) {
if (alignmentSetTimer.running)
return;
changeSlideVAlignment(textAlignment);
songsqlmodel.updateVerticalTextAlignment(songIndex, textAlignment)
}
function changeSlideHAlignment(alignment) {
switch (alignment) {
case "left" :
hAlignmentBox.currentIndex = 0;
slideEditor.hTextAlignment = Text.AlignLeft;
break;
case "center" :
hAlignmentBox.currentIndex = 1;
slideEditor.hTextAlignment = Text.AlignHCenter;
break;
case "right" :
hAlignmentBox.currentIndex = 2;
slideEditor.hTextAlignment = Text.AlignRight;
break;
case "justify" :
hAlignmentBox.currentIndex = 3;
slideEditor.hTextAlignment = Text.AlignJustify;
break;
}
}
function changeSlideVAlignment(alignment) {
switch (alignment) {
case "top" :
vAlignmentBox.currentIndex = 0;
slideEditor.vTextAlignment = Text.AlignTop;
break;
case "center" :
vAlignmentBox.currentIndex = 1;
slideEditor.vTextAlignment = Text.AlignVCenter;
break;
case "bottom" :
vAlignmentBox.currentIndex = 2;
slideEditor.vTextAlignment = Text.AlignBottom;
break;
}
}
}