393 lines
13 KiB
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;
|
|
}
|
|
}
|
|
}
|