// Copyright (C) 2026 Danilo M. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. import QtQuick import ".." import "Logic.js" as Logic // At rest a record dot, with the elapsed time while recording. A click // morphs the capsule into the controls panel, as the status pill does for // sound: record, pause, webcam, and the scene list. Capsule { id: pill property string panel: "" signal openPanel() expanded: panel === "obs" restWidth: rest.implicitWidth + 24 panelWidth: 260 panelHeight: controls.implicitHeight + 28 Row { id: rest anchors.centerIn: parent spacing: 6 opacity: pill.expanded ? 0 : 1 visible: opacity > 0 Behavior on opacity { NumberAnimation { duration: 120 } } Text { anchors.verticalCenter: parent.verticalCenter text: "\uf111" color: Obs.recording ? Theme.red : Theme.subtext opacity: Obs.paused ? 0.5 : 1 font { family: Theme.iconFamily; pixelSize: 14 } } Text { anchors.verticalCenter: parent.verticalCenter visible: Obs.recording text: Logic.obsElapsed(Obs.duration) color: Theme.text font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } } } MouseArea { anchors.fill: parent enabled: !pill.expanded cursorShape: Qt.PointingHandCursor onClicked: pill.openPanel() } Column { id: controls x: 14 y: 14 width: pill.panelWidth - 28 spacing: 10 opacity: pill.expanded ? 1 : 0 visible: opacity > 0 Behavior on opacity { NumberAnimation { duration: 160 } } Text { text: Obs.recording ? (Obs.paused ? "Paused " : "Recording ") + Logic.obsElapsed(Obs.duration) : "Not recording" color: Obs.recording ? Theme.red : Theme.subtext font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } } Row { spacing: 8 Button { text: Obs.recording ? "Stop" : "Record" danger: Obs.recording onClicked: Obs.toggleRecord() } Button { visible: Obs.recording text: Obs.paused ? "Resume" : "Pause" onClicked: Obs.togglePause() } Button { visible: Obs.camId >= 0 text: Obs.camOn ? "Hide webcam" : "Show webcam" onClicked: Obs.toggleCam() } } // ponytail: a plain Column, no scrolling; about ten scenes fit the // island's 480px window. A ListView if a scene collection outgrows it. Repeater { model: Obs.scenes delegate: Rectangle { required property string modelData readonly property bool current: modelData === Obs.scene width: controls.width height: 30 radius: 7 color: current ? Qt.alpha(Theme.accent, 0.25) : area.containsMouse ? Qt.alpha(Theme.surface, 0.8) : "transparent" Text { anchors { left: parent.left; leftMargin: 10; verticalCenter: parent.verticalCenter } text: modelData color: current ? Theme.text : Theme.subtext font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } } MouseArea { id: area anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: Obs.setScene(modelData) } } } } }