542 lines
20 KiB
QML
542 lines
20 KiB
QML
import QtQuick 2.15
|
|
import QtQuick.Controls 2.15 as Controls
|
|
import QtQuick.Window 2.15
|
|
import QtQuick.Layouts 1.15
|
|
import QtMultimedia
|
|
/* import QtAudioEngine 1.15 */
|
|
import org.kde.kirigami 2.13 as Kirigami
|
|
import "./" as Presenter
|
|
import org.presenter 1.0
|
|
|
|
FocusScope {
|
|
id: root
|
|
|
|
/* height: parent.height */
|
|
|
|
property var text
|
|
property int textIndex: 0
|
|
property string itemType: SlideObject.ty
|
|
property url imagebackground: SlideObject.imageBackground
|
|
property url vidbackground: SlideObject.videoBackground
|
|
|
|
property Item slide: previewSlide
|
|
|
|
property bool focusTimer: true
|
|
|
|
/* Component.onCompleted: nextSlideAction() */
|
|
|
|
ColumnLayout {
|
|
id: mainGrid
|
|
anchors.fill: parent
|
|
/* anchors.bottomMargin: Kirigami.Units.largeSpacing * 2 */
|
|
/* columns: 3 */
|
|
/* rowSpacing: 5 */
|
|
/* columnSpacing: 0 */
|
|
|
|
Controls.ToolBar {
|
|
Layout.fillWidth: true
|
|
/* Layout.columnSpan: 3 */
|
|
Layout.alignment: Qt.AlignTop
|
|
id: toolbar
|
|
RowLayout {
|
|
anchors.fill: parent
|
|
|
|
Controls.ToolButton {
|
|
text: "Solo"
|
|
icon.name: "viewimage"
|
|
hoverEnabled: true
|
|
onClicked: {
|
|
stack.replace(presenterView)
|
|
}
|
|
}
|
|
Controls.ToolButton {
|
|
text: "Grid"
|
|
icon.name: "view-app-grid-symbolic"
|
|
hoverEnabled: true
|
|
onClicked: {
|
|
stack.replace(gridView)
|
|
}
|
|
}
|
|
Controls.ToolButton {
|
|
text: "Details"
|
|
icon.name: "view-list-details"
|
|
hoverEnabled: true
|
|
onClicked: stack.replace(detailsView);
|
|
}
|
|
Controls.ToolSeparator {}
|
|
Item { Layout.fillWidth: true }
|
|
Controls.ToolSeparator {}
|
|
Controls.ToolButton {
|
|
text: "Effects"
|
|
icon.name: "image-auto-adjust"
|
|
hoverEnabled: true
|
|
onClicked: {}
|
|
}
|
|
Controls.ToolButton {
|
|
text: "Wah!"
|
|
icon.name: "audio-volume-high"
|
|
hoverEnabled: true
|
|
onClicked: {
|
|
audio.loadFile("/home/chris/nextcloud/tfcstaff/Lessons/2022-2023 Lessons/Unit 4/4.1/Wah Wahh Wahhh Sound Effect.m4a");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Controls.StackView {
|
|
id: stack
|
|
Layout.fillHeight: true
|
|
Layout.fillWidth: true
|
|
initialItem: presenterView
|
|
|
|
}
|
|
|
|
Item {
|
|
id: presenterView
|
|
Item {
|
|
id: slideArea
|
|
implicitWidth: stack.width
|
|
implicitHeight: stack.height - previewSlideList.height
|
|
/* anchors.bottomMargin: previewSlidesList.height */
|
|
|
|
Kirigami.Icon {
|
|
source: "arrow-left"
|
|
implicitWidth: Kirigami.Units.gridUnit * 7
|
|
implicitHeight: Kirigami.Units.gridUnit * 10
|
|
anchors.right: previewSlide.left
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
color: "white"
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onPressed: previousSlideAction()
|
|
cursorShape: Qt.PointingHandCursor
|
|
}
|
|
}
|
|
|
|
Presenter.Slide {
|
|
id: previewSlide
|
|
implicitWidth: root.width - 400 > 200 ? root.width - 400 : 200
|
|
implicitHeight: width / 16 * 9
|
|
anchors.centerIn: parent
|
|
itemType: SlideObject.ty
|
|
imageSource: SlideObject.html ? "" : SlideObject.imageBackground
|
|
webSource: SlideObject.html ? SlideObject.imageBackground : ""
|
|
htmlVisible: SlideObject.html
|
|
videoSource: SlideObject.videoBackground
|
|
audioSource: SlideObject.audio
|
|
chosenFont: SlideObject.font
|
|
textSize: SlideObject.fontSize
|
|
text: SlideObject.text
|
|
pdfIndex: SlideObject.innerSlideIndex
|
|
vidLoop: SlideObject.looping
|
|
vidStartTime: SlideObject.videoStartTime
|
|
vidEndTime: SlideObject.videoEndTime
|
|
preview: true
|
|
}
|
|
|
|
Kirigami.Icon {
|
|
source: "arrow-right"
|
|
implicitWidth: Kirigami.Units.gridUnit * 7
|
|
implicitHeight: Kirigami.Units.gridUnit * 10
|
|
anchors.left: previewSlide.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
color: Kirigami.Theme.textColor
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onPressed: nextSlideAction()
|
|
cursorShape: Qt.PointingHandCursor
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
id: videoControls
|
|
spacing: 2
|
|
width: previewSlide.width
|
|
/* Layout.alignment: Qt.AlignHCenter, Qt.AlignTop */
|
|
anchors.top: previewSlide.bottom
|
|
anchors.topMargin: 10
|
|
anchors.horizontalCenter: previewSlide.horizontalCenter
|
|
/* Layout.columnSpan: 3 */
|
|
visible: itemType === "video";
|
|
Controls.ToolButton {
|
|
Layout.preferredWidth: 25
|
|
Layout.preferredHeight: 25
|
|
icon.name: previewSlide.mpvIsPlaying ? "media-pause" : "media-play"
|
|
hoverEnabled: true
|
|
onClicked: SlideObject.playPause();
|
|
}
|
|
Controls.Slider {
|
|
id: videoSlider
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 25
|
|
from: 0
|
|
to: previewSlide.mpvDuration
|
|
value: previewSlide.mpvPosition
|
|
live: true
|
|
onMoved: changeVidPos(value);
|
|
}
|
|
|
|
Controls.Switch {
|
|
id: loopSwitch
|
|
text: "Loop"
|
|
checked: SlideObject.looping
|
|
onToggled: SlideObject.setLooping(!SlideObject.looping)
|
|
Keys.onLeftPressed: previousSlideAction()
|
|
Keys.onRightPressed: nextSlideAction()
|
|
Keys.onUpPressed: previousSlideAction()
|
|
Keys.onDownPressed: nextSlideAction()
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
id: htmlControls
|
|
spacing: 2
|
|
width: previewSlide.width
|
|
/* Layout.alignment: Qt.AlignHCenter, Qt.AlignTop */
|
|
anchors.top: previewSlide.bottom
|
|
anchors.topMargin: 10
|
|
anchors.horizontalCenter: previewSlide.horizontalCenter
|
|
/* Layout.columnSpan: 3 */
|
|
visible: SlideObject.imageBackground.startsWith("html");
|
|
Controls.Label {
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 25
|
|
text: SlideObject.innerSlideIndex + "/" + SlideObject.slideSize
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
Presenter.SlidesListView {
|
|
id: previewSlideList
|
|
highlight: highlightBar
|
|
}
|
|
|
|
Component {
|
|
id: highlightBar
|
|
Rectangle {
|
|
id: activeHighlightBar
|
|
width: previewSlideList.currentItem.width
|
|
height: Kirigami.Units.gridUnit / 4
|
|
y: Kirigami.Units.gridUnit * 7.35
|
|
x: previewSlideList.currentItem.x
|
|
radius: 5
|
|
color: Kirigami.Theme.negativeTextColor
|
|
|
|
Behavior on x { PropertyAnimation {
|
|
properties: "x"
|
|
easing.type: Easing.InOutElastic;
|
|
easing.period: 1.5
|
|
duration: 150
|
|
}}
|
|
}
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: gridView
|
|
/* Layout.fillHeight: true */
|
|
/* Layout.fillWidth: true */
|
|
/* Layout.alignment: Qt.AlignTop */
|
|
/* visible: false */
|
|
|
|
GridView {
|
|
// The active items X value from root
|
|
property int activeX
|
|
id: previewSlidesGrid
|
|
anchors.fill: stack
|
|
cellWidth: Kirigami.Units.gridUnit * 11
|
|
cellHeight: Kirigami.Units.gridUnit * 8
|
|
/* spacing: Kirigami.Units.smallSpacing * 2 */
|
|
cacheBuffer: 800
|
|
reuseItems: true
|
|
clip: true
|
|
model: SlideModel
|
|
delegate: Presenter.PreviewSlideListDelegate { showVidBG: false }
|
|
|
|
Kirigami.WheelHandler {
|
|
id: gridWheelHandler
|
|
target: previewSlidesGrid
|
|
filterMouseEvents: true
|
|
}
|
|
|
|
Controls.ScrollBar.vertical: Controls.ScrollBar {
|
|
active: hovered || pressed
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
Component {
|
|
id: detailsView
|
|
Item {
|
|
id: detailsWrapper
|
|
implicitWidth: stack.width
|
|
implicitHeight: stack.height
|
|
|
|
Item {
|
|
id: detailsSlide
|
|
implicitWidth: parent.width / 2
|
|
implicitHeight: parent.height - detailsSlideList.height
|
|
anchors.left: parent.horizontalCenter
|
|
/* anchors.bottomMargin: previewSlidesList.height */
|
|
|
|
Kirigami.Icon {
|
|
source: "arrow-left"
|
|
implicitWidth: Kirigami.Units.gridUnit * 7
|
|
implicitHeight: Kirigami.Units.gridUnit * 10
|
|
anchors.right: detailsPreviewSlide.left
|
|
anchors.verticalCenter: detailsPreviewSlide.verticalCenter
|
|
color: "white"
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onPressed: previousSlideAction()
|
|
cursorShape: Qt.PointingHandCursor
|
|
}
|
|
}
|
|
|
|
Presenter.Slide {
|
|
id: detailsPreviewSlide
|
|
implicitWidth: parent.width - 400 > 200 ? parent.width - 400 : 200
|
|
implicitHeight: width / 16 * 9
|
|
anchors.top: parent.top
|
|
anchors.topMargin: 10
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
itemType: SlideObject.ty
|
|
imageSource: SlideObject.imageBackground.endsWith(".html") ? "" : SlideObject.imageBackground
|
|
webSource: SlideObject.imageBackground.endsWith(".html") ? SlideObject.imageBackground : ""
|
|
htmlVisible: SlideObject.imageBackground.endsWith(".html")
|
|
videoSource: SlideObject.videoBackground
|
|
audioSource: SlideObject.audio
|
|
chosenFont: SlideObject.font
|
|
textSize: SlideObject.fontSize
|
|
text: SlideObject.text
|
|
pdfIndex: SlideObject.slideIndex
|
|
vidLoop: SlideObject.looping
|
|
vidStartTime: SlideObject.videoStartTime
|
|
vidEndTime: SlideObject.videoEndTime
|
|
preview: true
|
|
}
|
|
|
|
Kirigami.Icon {
|
|
source: "arrow-right"
|
|
implicitWidth: Kirigami.Units.gridUnit * 7
|
|
implicitHeight: Kirigami.Units.gridUnit * 10
|
|
anchors.left: detailsPreviewSlide.right
|
|
anchors.verticalCenter: detailsPreviewSlide.verticalCenter
|
|
color: Kirigami.Theme.textColor
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onPressed: nextSlideAction()
|
|
cursorShape: Qt.PointingHandCursor
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
spacing: 2
|
|
width: detailsPreviewSlide.width
|
|
/* Layout.alignment: Qt.AlignHCenter, Qt.AlignTop */
|
|
anchors.top: detailsPreviewSlide.bottom
|
|
anchors.topMargin: 10
|
|
anchors.horizontalCenter: detailsPreviewSlide.horizontalCenter
|
|
/* Layout.columnSpan: 3 */
|
|
visible: itemType === "video";
|
|
Controls.ToolButton {
|
|
Layout.preferredWidth: 25
|
|
Layout.preferredHeight: 25
|
|
icon.name: detailsPreviewSlide.mpvIsPlaying ? "media-pause" : "media-play"
|
|
hoverEnabled: true
|
|
onClicked: SlideObject.playPause();
|
|
}
|
|
Controls.Slider {
|
|
id: detailsVideoSlider
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: 25
|
|
from: 0
|
|
to: detailsPreviewSlide.mpvDuration
|
|
value: detailsPreviewSlide.mpvPosition
|
|
live: true
|
|
onMoved: changeVidPos(value);
|
|
}
|
|
|
|
Controls.Switch {
|
|
id: detailsLoopSwitch
|
|
text: "Loop"
|
|
checked: SlideObject.looping
|
|
onToggled: SlideObject.setLooping(!SlideObject.looping)
|
|
Keys.onLeftPressed: previousSlideAction()
|
|
Keys.onRightPressed: nextSlideAction()
|
|
Keys.onUpPressed: previousSlideAction()
|
|
Keys.onDownPressed: nextSlideAction()
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
Presenter.SlidesListView {
|
|
id: detailsSlideList
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
Item {
|
|
id: keyHandler
|
|
/* anchors.fill: parent */
|
|
focus: true
|
|
Keys.onPressed: {
|
|
if (event.key == Qt.Key_J)
|
|
nextSlideAction();
|
|
if (event.key == Qt.Key_L)
|
|
nextSlideAction();
|
|
if (event.key == Qt.Key_Right)
|
|
nextSlideAction();
|
|
if (event.key == Qt.Key_Down)
|
|
nextSlideAction();
|
|
if (event.key == Qt.Key_K)
|
|
previousSlideAction();
|
|
if (event.key == Qt.Key_H)
|
|
previousSlideAction();
|
|
if (event.key == Qt.Key_Up)
|
|
previousSlideAction();
|
|
if (event.key == Qt.Key_Left)
|
|
previousSlideAction();
|
|
if (event.key == Qt.Key_P)
|
|
SlideObject.playPause();
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: SlideObject
|
|
function onVideoBackgroundChanged() {
|
|
if (SlideObject.videoBackground === "")
|
|
stopVideo();
|
|
else {
|
|
loadVideo();
|
|
}
|
|
playVideo();
|
|
}
|
|
function onLoopingChanged() {
|
|
if(SlideObject.looping)
|
|
previewSlide.loopVideo();
|
|
}
|
|
function onIsPlayingChanged() {
|
|
if(SlideObject.isPlaying)
|
|
previewSlide.playVideo();
|
|
pauseVideo();
|
|
}
|
|
function onRevealNext() {
|
|
previewSlide.revealNext();
|
|
}
|
|
function onRevealPrev() {
|
|
previewSlide.revealPrev();
|
|
}
|
|
}
|
|
|
|
/* Connections { */
|
|
/* target: ServiceItemModel */
|
|
/* function onActivateChanged(index) { */
|
|
/* console.log("$$$$$$$$$$$$$$$$$$$$"); */
|
|
/* const slide = SlideMod.getSlideFromService(index); */
|
|
/* SlideModel.activate(slide); */
|
|
/* } */
|
|
/* } */
|
|
|
|
Timer {
|
|
interval: 500
|
|
running: false
|
|
repeat: focusTimer
|
|
onTriggered: root.visible ? keyHandler.forceActiveFocus() : null
|
|
}
|
|
|
|
MediaPlayer {
|
|
id: audio
|
|
audioOutput: AudioOutput {}
|
|
// embeded mpv allows to set commandline propertys using the options/<name>
|
|
// syntax. This could be abstracted later, but for now this works.
|
|
/* Component.onCompleted: audio.setProperty("options/audio-display", "no"); */
|
|
}
|
|
|
|
function pauseVideo() {
|
|
previewSlide.pauseVideo();
|
|
}
|
|
|
|
function loadVideo() {
|
|
/* showPassiveNotification("Loading Video " + vidbackground) */
|
|
previewSlide.loadVideo();
|
|
}
|
|
|
|
function loopVideo() {
|
|
previewSlide.loopVideo();
|
|
}
|
|
|
|
function stopVideo() {
|
|
/* showPassiveNotification("Stopping Video") */
|
|
previewSlide.stopVideo()
|
|
}
|
|
|
|
function nextSlideAction() {
|
|
keyHandler.forceActiveFocus();
|
|
const nextSlideIdx = SlideObject.html && (SlideObject.innerSlideIndex + 1 < SlideObject.slideSize) ? currentSlide : currentSlide + 1;
|
|
const nextSlide = SlideModel.getItem(nextSlideIdx);
|
|
if (nextSlideIdx > totalSlides || nextSlideIdx < 0)
|
|
return;
|
|
console.log("currentServiceItem " + currentServiceItem);
|
|
console.log("totalSlides " + totalSlides);
|
|
console.log("currentSlide " + currentSlide);
|
|
console.log("nextSlideIdx " + nextSlideIdx);
|
|
for (var prop in nextSlide)
|
|
console.log(prop += " (" + typeof(nextSlide[prop]) + ") = " + nextSlide[prop]);
|
|
/* changeSlide(nextSlideIdx); */
|
|
if (SlideObject.next(nextSlide)) {
|
|
currentSlide = nextSlideIdx;
|
|
currentServiceItem = nextSlide.serviceItemId;
|
|
}
|
|
}
|
|
|
|
function nextSlide() {
|
|
changeServiceItem(currentServiceItem++);
|
|
console.log(slideItem);
|
|
}
|
|
|
|
function previousSlideAction() {
|
|
keyHandler.forceActiveFocus();
|
|
const prevSlideIdx = currentSlide - 1;
|
|
const prevSlide = SlideModel.getItem(prevSlideIdx);
|
|
if (prevSlideIdx > totalSlides || prevSlideIdx < 0)
|
|
return;
|
|
console.log("currentServiceItem " + currentServiceItem);
|
|
console.log("totalSlides " + totalSlides);
|
|
console.log("currentSlide " + currentSlide);
|
|
console.log("prevSlideIdx " + prevSlideIdx);
|
|
/* changeSlide(prevSlideIdx); */
|
|
if (SlideObject.previous(prevSlide)) {
|
|
currentSlide = prevSlideIdx;
|
|
currentServiceItem = prevSlide.serviceItemId;
|
|
}
|
|
}
|
|
|
|
function previousSlide() {
|
|
changeServiceItem(--currentServiceItem);
|
|
console.log(slideItem);
|
|
}
|
|
|
|
function clearText() {
|
|
SlideObject.setText("");
|
|
}
|
|
|
|
function playAudio() {
|
|
}
|
|
|
|
function revealNext() {
|
|
previewSlide.revealNext();
|
|
}
|
|
|
|
function revealPrev() {
|
|
previewSlide.revealPrev();
|
|
}
|
|
}
|