662 lines
27 KiB
QML
662 lines
27 KiB
QML
import QtQuick
|
|
import QtQuick.Effects
|
|
import QtQuick.Controls as Controls
|
|
/* import QtQuick.Window 2.15 */
|
|
import QtQuick.Layouts
|
|
import QtQuick.Shapes
|
|
import QtQml.Models
|
|
/* import QtQml.Models 2.12 */
|
|
/* import QtMultimedia 5.15 */
|
|
/* import QtAudioEngine 1.15 */
|
|
import Qt5Compat.GraphicalEffects
|
|
import org.kde.kirigami as Kirigami
|
|
import "./" as Presenter
|
|
import org.presenter 1.0
|
|
|
|
Item {
|
|
id: root
|
|
property var selectedItem: serviceItemList.selected
|
|
property var hlItem
|
|
property var parentItem
|
|
|
|
Rectangle {
|
|
id: bg
|
|
color: Kirigami.Theme.backgroundColor
|
|
anchors.fill: parent
|
|
opacity: 1.0
|
|
}
|
|
|
|
/* ShaderEffectSource { */
|
|
/* id: shaderArea */
|
|
/* sourceItem: parentItem */
|
|
/* sourceRect: Qt.rect(0, 0, parent.width, parent.height) */
|
|
/* width: parent.width */
|
|
/* height: parent.height */
|
|
/* } */
|
|
|
|
/* MultiEffect { */
|
|
/* id: backgroundBlur */
|
|
/* source: shaderArea */
|
|
/* anchors.fill: parent */
|
|
/* autoPaddingEnabled: true */
|
|
/* blur: 0.1 */
|
|
/* /\* blurMultiplier: 2 *\/ */
|
|
/* blurEnabled: true */
|
|
/* } */
|
|
|
|
ColumnLayout {
|
|
id: layout
|
|
anchors.fill: parent
|
|
|
|
Rectangle {
|
|
id: headerBackground
|
|
color: Kirigami.Theme.backgroundColor
|
|
height: 40
|
|
opacity: 1.0
|
|
Layout.fillWidth: true
|
|
|
|
Kirigami.Heading {
|
|
id: serviceTitle
|
|
text: "Service List"
|
|
anchors.centerIn: headerBackground
|
|
padding: 5
|
|
level: 3
|
|
}
|
|
}
|
|
|
|
DropArea {
|
|
id: serviceDropEnd
|
|
Layout.fillHeight: true
|
|
Layout.fillWidth: true
|
|
onDropped: (drag) => {
|
|
console.log("DROPPED AT END");
|
|
loadingItem.visible = true;
|
|
appendItem(dragItemType,
|
|
dragItemIndex);
|
|
dropHighlightLine.visible = false;
|
|
loadingItem.visible = false;
|
|
}
|
|
|
|
keys: ["library"]
|
|
|
|
onEntered: (drag) => {
|
|
if (drag.keys[0] === "library") {
|
|
dropHighlightLine.visible = true;
|
|
var lastItem = serviceItemList.itemAtIndex(ServiceItemModel.count - 1);
|
|
dropHighlightLine.y = lastItem.y + lastItem.height;
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: serviceListDelegate
|
|
Controls.ItemDelegate {
|
|
id: serviceListItem
|
|
implicitWidth: serviceItemList.width
|
|
height: Kirigami.Units.gridUnit * 2
|
|
Component.onCompleted: Utils.dbg("HELLLLLOOOOOO: " + ServiceItemModel.getItem(0).name)
|
|
|
|
property var selectedItems
|
|
|
|
contentItem: DropArea {
|
|
id: serviceDrop
|
|
anchors.fill: parent
|
|
|
|
onEntered: (drag) => {
|
|
console.log("here");
|
|
if (drag.keys[0] === "library") {
|
|
dropHighlightLine.visible = true;
|
|
dropHighlightLine.y = serviceDrop.mapToItem(
|
|
serviceItemList,0,0).y - 2;
|
|
} else {
|
|
console.log("here");
|
|
let from = drag.source.DelegateModel.itemsIndex;
|
|
let to = serviceListItem.DelegateModel.itemsIndex;
|
|
console.log("from = " + from);
|
|
console.log("to = " + to);
|
|
if (from != to && to > -1 && to <= ServiceItemModel.count - 1)
|
|
ServiceItemModel.moveRows(from, to, 1);
|
|
}
|
|
}
|
|
|
|
onDropped: (drag) => {
|
|
if (drag.keys[0] === "library") {
|
|
loadingItem.visible = true;
|
|
console.log("DROPPED IN ITEM AREA: " + drag.keys);
|
|
console.log(dragItemIndex + " " + index);
|
|
const hlIndex = serviceItemList.currentIndex;
|
|
addItem(index,
|
|
dragItemType,
|
|
dragItemIndex);
|
|
}
|
|
dropHighlightLine.visible = false;
|
|
loadingItem.visible = false;
|
|
}
|
|
|
|
keys: ["library","serviceitem"]
|
|
|
|
Rectangle {
|
|
id: visServiceItem
|
|
width: serviceDrop.width
|
|
height: serviceDrop.height
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
verticalCenter: parent.verticalCenter
|
|
}
|
|
color: {
|
|
if (active)
|
|
Kirigami.Theme.highlightColor;
|
|
else if (selected)
|
|
Kirigami.Theme.focusColor;
|
|
else if (mouseHandler.containsMouse)
|
|
Kirigami.Theme.hoverColor;
|
|
else
|
|
Kirigami.Theme.backgroundColor;
|
|
}
|
|
|
|
Controls.Label {
|
|
id: label
|
|
anchors.left: parent.left
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
anchors.leftMargin: 5
|
|
text: (index + 1) + ": " + name
|
|
elide: Text.ElideRight
|
|
width: parent.width - trailing.width - 25
|
|
color: {
|
|
if (selected ||
|
|
mouseHandler.containsMouse || active)
|
|
Kirigami.Theme.highlightedTextColor;
|
|
else
|
|
Kirigami.Theme.textColor;
|
|
}
|
|
Component.onCompleted: Utils.dbg("SERVICEMODEL: " + name)
|
|
}
|
|
|
|
Kirigami.Icon {
|
|
id: trailing
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
anchors.rightMargin: 5
|
|
implicitWidth: Kirigami.Units.gridUnit
|
|
source: {
|
|
switch (ty) {
|
|
case 'image': return "folder-pictures-symbolic";
|
|
case 'video': return "folder-videos-symbolic";
|
|
case 'song': return "folder-music-symbolic";
|
|
case 'presentation': return "x-office-presentation-symbolic";
|
|
default: return "slideshow-plugin";
|
|
}
|
|
}
|
|
color: {
|
|
if (selected ||
|
|
mouseHandler.containsMouse || active)
|
|
Kirigami.Theme.highlightedTextColor;
|
|
else
|
|
Kirigami.Theme.textColor;
|
|
}
|
|
}
|
|
|
|
/* onYChanged: serviceItemList.updateDrag(Math.round(y)); */
|
|
|
|
states: [
|
|
State {
|
|
when: mouseHandler.drag.active
|
|
ParentChange {
|
|
target: visServiceItem
|
|
parent: serviceItemList
|
|
}
|
|
|
|
PropertyChanges {
|
|
target: visServiceItem
|
|
/* backgroundColor: Kirigami.Theme.backgroundColor */
|
|
/* textColor: Kirigami.Theme.textColor */
|
|
anchors.verticalCenter: undefined
|
|
anchors.horizontalCenter: undefined
|
|
}
|
|
}
|
|
]
|
|
|
|
/* Drag.dragType: Drag.Automatic */
|
|
Drag.active: mouseHandler.drag.active
|
|
Drag.hotSpot.x: width / 2
|
|
Drag.hotSpot.y: height / 2
|
|
Drag.keys: ["serviceitem"]
|
|
|
|
MouseArea {
|
|
id: mouseHandler
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
|
|
drag {
|
|
target: visServiceItem
|
|
axis: Drag.YAxis
|
|
/* minimumY: root.y */
|
|
/* maximumY: serviceItemList.height - serviceDrop.height */
|
|
smoothed: false
|
|
onActiveChanged: {
|
|
serviceItemList.indexDragged = index;
|
|
}
|
|
}
|
|
|
|
|
|
/* onPositionChanged: { */
|
|
/* if (!pressed) { */
|
|
/* return; */
|
|
/* } */
|
|
/* mouseArea.arrangeItem(); */
|
|
/* } */
|
|
|
|
/* onPressAndHold: { */
|
|
/* serviceItemList.interactive = false; */
|
|
/* } */
|
|
|
|
onClicked: {
|
|
if (mouse.button === Qt.RightButton) {
|
|
if (!selected) {
|
|
serviceItemList.currentIndex = index;
|
|
ServiceItemModel.select(index);
|
|
}
|
|
rightClickMenu.popup(mouse);
|
|
}
|
|
else if ((mouse.button === Qt.LeftButton) &&
|
|
(mouse.modifiers === Qt.ShiftModifier)) {
|
|
ServiceItemModel.selectItems(index);
|
|
} else {
|
|
serviceItemList.currentIndex = index;
|
|
ServiceItemModel.select(index);
|
|
}
|
|
refocusPresentation();
|
|
}
|
|
|
|
onDoubleClicked: {
|
|
changeServiceItem(index);
|
|
}
|
|
|
|
onReleased: {
|
|
console.log("should drop");
|
|
visServiceItem.Drag.drop();
|
|
}
|
|
}
|
|
|
|
/* Kirigami.ListItemDragHandle { */
|
|
/* id: dragHandle */
|
|
/* anchors.left: parent.left */
|
|
/* anchors.verticalCenter: parent.verticalCenter */
|
|
/* anchors.leftMargin: 5 */
|
|
/* incrementalMoves: true */
|
|
/* /\* width: 20 *\/ */
|
|
/* listItem: serviceListItem */
|
|
/* listView: serviceItemList */
|
|
/* onMoveRequested: (oldIndex, newIndex) => { */
|
|
/* ServiceItemModel.moveRows(oldIndex, */
|
|
/* newIndex, */
|
|
/* 1) */
|
|
/* } */
|
|
/* } */
|
|
|
|
}
|
|
Controls.Menu {
|
|
id: rightClickMenu
|
|
Kirigami.Action {
|
|
text: "Copy"
|
|
}
|
|
Kirigami.Action {
|
|
text: "Paste"
|
|
}
|
|
Kirigami.Action {
|
|
text: "Delete"
|
|
onTriggered: removeItem(index)
|
|
}
|
|
|
|
Controls.MenuSeparator {}
|
|
|
|
|
|
Controls.Menu {
|
|
id: obsMenu
|
|
title: "Obs Scenes"
|
|
enabled: ObsModel.connected
|
|
Instantiator {
|
|
model: ObsModel.scenes
|
|
Kirigami.Action {
|
|
text: modelData
|
|
onTriggered: {
|
|
showPassiveNotification("setting: " + modelData)
|
|
ObsModel.setScene(modelData);
|
|
}
|
|
}
|
|
onObjectAdded: obsMenu.insertAction(index, object)
|
|
onObjectRemoved: obsMenu.removeAction(object)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
ListView {
|
|
id: serviceItemList
|
|
anchors.top: parent.top
|
|
anchors.bottom: parent.bottom
|
|
anchors.left: parent.left
|
|
width: serviceListScrollBar.visible ?
|
|
parent.width - serviceListScrollBar.width : parent.width
|
|
clip: true
|
|
spacing: 3
|
|
property int indexDragged
|
|
property int moveToIndex
|
|
property int draggedY
|
|
|
|
add: Transition {
|
|
NumberAnimation {properties: "width, height"; duration: 3000}
|
|
NumberAnimation { properties: "opacity"; duration: 3000 }
|
|
}
|
|
|
|
remove: Transition {
|
|
NumberAnimation { properties: "width, height"; duration: 3000 }
|
|
NumberAnimation { properties: "opacity"; duration: 3000 }
|
|
}
|
|
|
|
displaced: Transition {
|
|
NumberAnimation {properties: "x, y"; duration: 100}
|
|
}
|
|
|
|
model: ServiceItemModel
|
|
|
|
delegate: serviceListDelegate
|
|
|
|
Kirigami.WheelHandler {
|
|
id: wheelHandler
|
|
target: serviceItemList
|
|
filterMouseEvents: true
|
|
/* keyNavigationEnabled: true */
|
|
}
|
|
|
|
Controls.ScrollBar.vertical: Controls.ScrollBar {
|
|
id: serviceListScrollBar
|
|
parent: serviceItemList.parent
|
|
anchors.right: background.right
|
|
anchors.left: serviceItemList.right
|
|
anchors.top: serviceItemList.top
|
|
anchors.bottom: serviceItemList.bottom
|
|
active: hovered || pressed
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
id: dropHighlightLine
|
|
width: parent.width
|
|
height: 4
|
|
color: Kirigami.Theme.hoverColor
|
|
visible: false
|
|
Component.onCompleted: {
|
|
dragHighlightLine = dropHighlightLine;
|
|
}
|
|
}
|
|
Canvas {
|
|
x: dropHighlightLine.width - 8
|
|
y: dropHighlightLine.y - 17
|
|
z: 1
|
|
width: 100; height: 100;
|
|
contextType: "2d"
|
|
renderStrategy: Canvas.Threaded
|
|
onPaint: {
|
|
console.log(Kirigami.Theme.hoverColor);
|
|
var ctx = getContext("2d");
|
|
ctx.fillRule = Qt.OddEvenFill
|
|
ctx.fillStyle = Kirigami.Theme.hoverColor;
|
|
ctx.rotate(30);
|
|
ctx.transform(0.8, 0, 0, 0.8, 0, 30)
|
|
ctx.path = tearDropPath;
|
|
ctx.fill();
|
|
}
|
|
visible: dropHighlightLine.visible
|
|
}
|
|
Path {
|
|
id: tearDropPath
|
|
startX: dropHighlightLine.width
|
|
startY: dropHighlightLine.y + 4
|
|
PathSvg {
|
|
path: "M15 3
|
|
Q16.5 6.8 25 18
|
|
A12.8 12.8 0 1 1 5 18
|
|
Q13.5 6.8 15 3z"
|
|
}
|
|
}
|
|
|
|
/* Shape { */
|
|
/* x: dropHighlightLine.width - 8 */
|
|
/* y: dropHighlightLine.y - 17 */
|
|
/* z: 1 */
|
|
/* width: 100; height: 100; */
|
|
|
|
/* ShapePath { */
|
|
/* fillColor: Kirigami.Theme.hoverColor */
|
|
/* startX: 0; startY: 0 */
|
|
/* PathLine { x: 180; y: 130 } */
|
|
/* PathLine { x: 20; y: 130 } */
|
|
/* PathLine { x: 20; y: 20 } */
|
|
/* PathArc { */
|
|
/* x: 40; y: 200; */
|
|
/* radiusX: 200; */
|
|
/* radiusY: 200; */
|
|
/* useLargeArc: true */
|
|
/* } */
|
|
/* PathLine { x: 40; y: 120 } */
|
|
/* PathArc { */
|
|
/* x: -40; y: 120; */
|
|
/* radiusX: 120; */
|
|
/* radiusY: 120; */
|
|
/* useLargeArc: true; */
|
|
/* direction: PathArc.Counterclockwise */
|
|
/* } */
|
|
/* PathLine { x: -40; y: 200 } */
|
|
/* } */
|
|
/* } */
|
|
|
|
Rectangle {
|
|
id: loadingItem
|
|
anchors.fill: parent
|
|
color: Kirigami.Theme.backgroundColor
|
|
visible: false
|
|
|
|
Presenter.LoadingSpinner {
|
|
anchors.centerIn: parent
|
|
running: parent.visible
|
|
color: Kirigami.Theme.highlightColor
|
|
}
|
|
}
|
|
}
|
|
|
|
Kirigami.ActionToolBar {
|
|
id: serviceToolBar
|
|
Layout.fillWidth: true
|
|
opacity: 1.0
|
|
display: Controls.Button.IconOnly
|
|
actions: [
|
|
Kirigami.Action {
|
|
text: "Up"
|
|
icon.name: "arrow-up"
|
|
onTriggered: {
|
|
const oldid = serviceItemList.currentIndex;
|
|
if (oldid <= 0)
|
|
{
|
|
showPassiveNotification("wow stop trying to go nego");
|
|
return;
|
|
}
|
|
const newid = serviceItemList.currentIndex - 1;
|
|
showPassiveNotification(oldid + " " + newid);
|
|
showPassiveNotification("Up");
|
|
const ans = ServiceItemModel.moveRows(oldid, newid, 1);
|
|
if (ans)
|
|
{
|
|
serviceItemList.currentIndex = newid;
|
|
showPassiveNotification("move was successful, newid: "
|
|
+ serviceItemList.currentIndex);
|
|
}
|
|
else
|
|
showPassiveNotification("move was unsuccessful")
|
|
}
|
|
},
|
|
Kirigami.Action {
|
|
text: "Down"
|
|
icon.name: "arrow-down"
|
|
onTriggered: {
|
|
const id = serviceItemList.currentIndex;
|
|
if (id + 1 >= serviceItemList.count)
|
|
{
|
|
showPassiveNotification("wow you dummy you can't got further down");
|
|
return;
|
|
};
|
|
showPassiveNotification("moving ", id, " down");
|
|
const ans = ServiceItemModel.moveDown(id);
|
|
if (ans)
|
|
{
|
|
serviceItemList.currentIndex = id + 1;
|
|
showPassiveNotification("move was successful, newid: "
|
|
+ serviceItemList.currentIndex);
|
|
}
|
|
else
|
|
showPassiveNotification("move was unsuccessful, id: "
|
|
+ id);
|
|
}
|
|
},
|
|
Kirigami.Action {
|
|
text: "Remove"
|
|
icon.name: "delete"
|
|
onTriggered: {
|
|
showPassiveNotification("remove");
|
|
removeItems();
|
|
}
|
|
},
|
|
Kirigami.Action {
|
|
text: "Clear All"
|
|
icon.name: "list-remove-all"
|
|
onTriggered: {
|
|
showPassiveNotification("clearing all items");
|
|
ServiceItemModel.clearAll();
|
|
serviceItemList.forceLayout()
|
|
}
|
|
},
|
|
Kirigami.Action {
|
|
text: "Load"
|
|
icon.name: "fileopen"
|
|
onTriggered: {
|
|
loadingItem.visible = !loadingItem.visible;
|
|
}
|
|
}
|
|
]
|
|
}
|
|
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
/* totalServiceItems = serviceItemList.count; */
|
|
console.log("THE TOTAL SERVICE ITEMS: " + totalServiceItems);
|
|
activeServiceItem = serviceItemList.model.getItem(serviceItemList.currentIndex).name;
|
|
// TODO
|
|
// After getting the rust service_item_model setup let's add some properties that we can
|
|
// use to find the active serviceItem and other things that will need
|
|
// to see some global state of the model.
|
|
}
|
|
|
|
function removeItem(index) {
|
|
ServiceItemModel.removeItem(index);
|
|
serviceItemList.forceLayout()
|
|
/* totalServiceItems--; */
|
|
}
|
|
|
|
function removeItems() {
|
|
ServiceItemModel.removeItems();
|
|
serviceItemList.forceLayout()
|
|
}
|
|
|
|
function addItem(index, type, itemIndex) {
|
|
switch (type) {
|
|
case 'image': {
|
|
const image = imageModel.getItem(itemIndex);
|
|
console.log("adding: " + image.title + " of type " + type);
|
|
ServiceItemModel.insertItem(index, image.title,
|
|
type, image.id);
|
|
serviceItemList.forceLayout()
|
|
return;
|
|
}
|
|
case 'video': {
|
|
const video = videoModel.getItem(itemIndex);
|
|
console.log("adding: " + video.title + " of type " + type);
|
|
ServiceItemModel.insertItem(index, video.title,
|
|
type, video.id);
|
|
serviceItemList.forceLayout()
|
|
return;
|
|
}
|
|
case 'song': {
|
|
const lyrics = songModel.getLyricList(itemIndex);
|
|
const song = songModel.getItem(itemIndex);
|
|
/* showPassiveNotification(song.title); */
|
|
console.log("adding: " + song.title +
|
|
" of type " + type +
|
|
" with " + lyrics.length + " slides");
|
|
ServiceItemModel.insertItem(index, song.title,
|
|
type, song.id);
|
|
serviceItemList.forceLayout()
|
|
return;
|
|
}
|
|
case 'presentation': {
|
|
const pres = presentationModel.getItem(itemIndex);
|
|
console.log("adding: " + pres.title +
|
|
" of type " + type +
|
|
" with " + pres.pageCount + " slides");
|
|
ServiceItemModel.insertItem(index, pres.title, type, pres.id);
|
|
serviceItemList.forceLayout()
|
|
return;
|
|
}
|
|
default: return;
|
|
}
|
|
serviceItemList.forceLayout()
|
|
/* totalServiceItems++; */
|
|
}
|
|
|
|
function appendItem(type, itemIndex) {
|
|
switch (type) {
|
|
case 'image': {
|
|
const image = imageModel.getItem(itemIndex);
|
|
console.log("adding: " + image.title + " of type " + type);
|
|
ServiceItemModel.addItem(image.title,
|
|
type, image.id);
|
|
serviceItemList.forceLayout()
|
|
return;
|
|
}
|
|
case 'video': {
|
|
const video = videoModel.getItem(itemIndex);
|
|
console.log("adding: " + video.title + " of type " + type);
|
|
ServiceItemModel.addItem(video.title,
|
|
type, video.id);
|
|
serviceItemList.forceLayout()
|
|
return;
|
|
}
|
|
case 'song': {
|
|
const lyrics = songModel.getLyricList(itemIndex);
|
|
const song = songModel.getItem(itemIndex);
|
|
console.log("adding: " + song.title +
|
|
" of type " + type +
|
|
" with " + lyrics.length + " slides");
|
|
ServiceItemModel.addItem(song.title,
|
|
type, song.id);
|
|
serviceItemList.forceLayout()
|
|
return;
|
|
}
|
|
case 'presentation': {
|
|
const pres = presentationModel.getItem(itemIndex);
|
|
console.log("adding: " + pres.title +
|
|
" of type " + type +
|
|
" with " + pres.pageCount + " slides");
|
|
ServiceItemModel.addItem(pres.title,
|
|
type, pres.id);
|
|
serviceItemList.forceLayout()
|
|
return;
|
|
}
|
|
default: return;
|
|
}
|
|
serviceItemList.forceLayout()
|
|
}
|
|
|
|
}
|