import QtQuick 2.7 import QtQuick.Layouts 1.3 import QtMultimedia 5.0 import Lomiri.Components 1.3 import Lomiri.Components.Popups 1.3 import io.thp.pyotherside 1.4 MainView { id: root applicationName: "fortunecookie.darklithium" width: units.gu(45) height: units.gu(75) theme.name: "Lomiri.Components.Themes.SuruDark" // ==================================================================== // PROPERTIES (am Anfang definieren!) // ==================================================================== property bool fortuneOpened: false property string currentFortune: "" property bool musicPlaying: false property bool appInitialized: false Python { id: py Component.onCompleted: { addImportPath(Qt.resolvedUrl("../src")); importModule("fortunecookie", function() { console.log("Python-Modul fortunecookie geladen"); }); } } property real musicVolume: 0.5 property real crackVolume: 1.0 // Funktionen zum Setzen der Lautstärke function setMusicVolume(volume) { root.musicVolume = volume; py.call("fortunecookie.set_music_volume", [volume]); } function setCrackVolume(volume) { root.crackVolume = volume; py.call("fortunecookie.set_crack_volume", [volume]); } function reloadFortune() { currentFortune = py.call_sync("fortunecookie.get_current_fortune", []); currentFortuneLabel.text = currentFortune; if (fortuneOpened) { currentFortuneLabel.visible = true; } } MediaPlayer { id: mediaPlayer objectName: "mediaPlayer" source: Qt.resolvedUrl("../assets/chinese_music.mp3") loops: MediaPlayer.Infinite volume: root.musicVolume } MediaPlayer { id: crackMediaPlayer objectName: "crackMediaPlayer" source: Qt.resolvedUrl("../assets/cookie_crack.mp3") volume: root.crackVolume } // ==================================================================== // STACK LAYOUT FÜR NAVIGATION // ==================================================================== StackLayout { id: mainStack anchors.fill: parent currentIndex: 0 // SEITE 1: EINSTELLUNGEN // ================================================================ Settings { id: settingsPage } ======= // ================================================================ // SEITE 1: EINSTELLUNGEN (Inline-Komponente) // ================================================================ Component { id: settingsComponent Page { id: settingsPage objectName: 'settingsPage' property bool settingsInitialized: false property var currentFortuneList: "classic" property real musicVolume: 0.5 property real crackVolume: 1.0 header: PageHeader { title: "Einstellungen" } // Timer für PyOtherSide Initialisierung Timer { id: initTimer interval: 1000 running: true repeat: false onTriggered: { try { // Einstellungen laden currentFortuneList = py.call_sync("fortunecookie.get_current_fortune_list", []); musicVolume = py.call_sync("fortunecookie.get_music_volume", []); crackVolume = py.call_sync("fortunecookie.get_crack_volume", []); // Slider Werte setzen musicVolumeSlider.value = musicVolume; crackVolumeSlider.value = crackVolume; // Spruchlisten ComboBox füllen var lists = py.call_sync("fortunecookie.get_fortune_lists_with_description", []); fortuneListCombo.model = lists; // Aktuelle Liste auswählen (vergleiche nur den Listennamen, nicht die Beschreibung) for (var i = 0; i < fortuneListCombo.count; i++) { var text = fortuneListCombo.textAt(i); var listName = text.split(" - ")[0]; if (listName === currentFortuneList) { fortuneListCombo.currentIndex = i; break; } } settingsInitialized = true; } catch (e) { console.log("ERROR: Einstellungen nicht geladen: " + e); } } } ColumnLayout { anchors.fill: parent anchors.margins: units.gu(2) spacing: units.gu(2) // Spacer für Header Item { Layout.fillWidth: true Layout.preferredHeight: units.gu(2) } // ============================================================ // SPRUCHLISTEN-AUSWAHL // ============================================================ Label { text: "Spruchliste:" Layout.fillWidth: true fontSize: "large" } ComboBox { id: fortuneListCombo Layout.fillWidth: true Layout.preferredHeight: units.gu(8) onActivated: { var newListFull = fortuneListCombo.currentText; // Extrahiere den Listennamen (Teil vor " - ") var newList = newListFull.split(" - ")[0]; py.call("fortunecookie.set_fortune_list", [newList], function() { console.log("Spruchliste gewaehlt: " + newList); }); } } // ============================================================ // LAUTSTÄRKE - MUSIK // ============================================================ Label { text: "Musik-Lautstärke:" Layout.fillWidth: true fontSize: "large" } RowLayout { Layout.fillWidth: true spacing: units.gu(2) Slider { id: musicVolumeSlider Layout.fillWidth: true minimumValue: 0.0 maximumValue: 1.0 stepSize: 0.1 value: 0.5 onValueChanged: { var volume = musicVolumeSlider.value; py.call("fortunecookie.set_music_volume", [volume]); musicVolumeLabel.text = Math.round(volume * 100) + "%"; } } Label { id: musicVolumeLabel text: Math.round(musicVolumeSlider.value * 100) + "%" width: units.gu(10) horizontalAlignment: Text.AlignHCenter fontSize: "medium" } } // ============================================================ // LAUTSTÄRKE - KNACK-GERÄUSCH // ============================================================ Label { text: "Knack-Lautstärke:" Layout.fillWidth: true fontSize: "large" } RowLayout { Layout.fillWidth: true spacing: units.gu(2) Slider { id: crackVolumeSlider Layout.fillWidth: true minimumValue: 0.0 maximumValue: 1.0 stepSize: 0.1 value: 1.0 onValueChanged: { var volume = crackVolumeSlider.value; py.call("fortunecookie.set_crack_volume", [volume]); crackVolumeLabel.text = Math.round(volume * 100) + "%"; } } Label { id: crackVolumeLabel text: Math.round(crackVolumeSlider.value * 100) + "%" width: units.gu(10) horizontalAlignment: Text.AlignHCenter fontSize: "medium" } } // ============================================================ // ZURÜCK-BUTTON // ============================================================ Item { Layout.fillWidth: true Layout.preferredHeight: units.gu(10) } Button { text: "Zurück" Layout.fillWidth: false Layout.preferredWidth: units.gu(20) Layout.preferredHeight: units.gu(8) Layout.alignment: Qt.AlignHCenter onClicked: { mainStack.currentIndex = 0; } } } } } // Settings-Page erstellen Component.onCompleted: { var comp = settingsComponent.createObject(mainStack); mainStack.insert(1, comp); }================================================================ // SEITE 0: HAUPTSPIELBILDSCHIRM // ================================================================ Page { id: mainPage objectName: "mainPage" header: PageHeader { title: "Fortune Cookie" trailingActionBar.actions: [ Action { iconName: "settings" text: "Einstellungen" onTriggered: { mainStack.currentIndex = 1; } } ] } // ============================================================ // INITIALISIERUNGS-TIMER // ============================================================ Timer { id: initTimer interval: 1000 running: true repeat: false onTriggered: { try { currentFortune = py.call_sync("fortunecookie.get_initial_fortune", []); currentFortuneLabel.text = currentFortune; cookieImage.source = Qt.resolvedUrl("../assets/cookie_closed2.png"); // Musik-Status laden musicPlaying = py.call_sync("fortunecookie.get_music_enabled", []); console.log("DEBUG QML: musicPlaying geladen: " + musicPlaying); // MediaPlayer Zustand synchronisieren if (musicPlaying) { mediaPlayer.play(); } // Volumes laden und Properties setzen var musicVol = py.call_sync("fortunecookie.get_music_volume", []); var crackVol = py.call_sync("fortunecookie.get_crack_volume", []); root.musicVolume = musicVol; root.crackVolume = crackVol; appInitialized = true; } catch (e) { console.log("ERROR QML: Initialisierung fehlgeschlagen: " + e); } } } // Timer zum regelmäßigen Prüfen der Lautstärke-Einstellungen Timer { id: volumeCheckTimer interval: 200 // Prüfen alle 200ms running: true repeat: true onTriggered: { var musicVol = py.call_sync("fortunecookie.get_music_volume", []); var crackVol = py.call_sync("fortunecookie.get_crack_volume", []); if (musicVol !== root.musicVolume) { root.musicVolume = musicVol; } if (crackVol !== root.crackVolume) { root.crackVolume = crackVol; } } } Image { id: cookieImage anchors.centerIn: parent width: fortuneOpened ? units.gu(36) : units.gu(32) height: fortuneOpened ? units.gu(28) : units.gu(24) source: fortuneOpened ? Qt.resolvedUrl("../assets/cookie_open2.png") : Qt.resolvedUrl("../assets/cookie_closed2.png") fillMode: Image.PreserveAspectFit MouseArea { anchors.fill: parent property real startY: 0 onPressed: startY = mouseY onReleased: { if (mouseY < startY - units.gu(2)) { py.call("fortunecookie.open_fortune", [], function() { crackMediaPlayer.play(); fortuneOpened = true; currentFortune = py.call_sync("fortunecookie.get_current_fortune", []); currentFortuneLabel.text = currentFortune; currentFortuneLabel.visible = true; cookieImage.source = Qt.resolvedUrl("../assets/cookie_open2.png"); }); } } } MouseArea { anchors.fill: parent hoverEnabled: true onClicked: { if (!fortuneOpened) { py.call("fortunecookie.open_fortune", [], function() { crackMediaPlayer.play(); fortuneOpened = true; currentFortune = py.call_sync("fortunecookie.get_current_fortune", []); currentFortuneLabel.text = currentFortune; currentFortuneLabel.visible = true; cookieImage.source = Qt.resolvedUrl("../assets/cookie_open2.png"); }); } else { fortuneOpened = false; currentFortuneLabel.text = ""; currentFortuneLabel.visible = false; cookieImage.source = Qt.resolvedUrl("../assets/cookie_closed2.png"); } } } } Label { id: currentFortuneLabel anchors { top: cookieImage.bottom topMargin: units.gu(2) left: parent.left right: parent.right leftMargin: units.gu(2) rightMargin: units.gu(2) } text: "" fontSize: "large" horizontalAlignment: Text.AlignHCenter visible: false wrapMode: Text.WordWrap MouseArea { anchors.fill: parent onClicked: { py.call("fortunecookie.get_new_fortune", [], function() { fortuneOpened = false; currentFortune = py.call_sync("fortunecookie.get_current_fortune", []); currentFortuneLabel.text = currentFortune; cookieImage.source = Qt.resolvedUrl("../assets/cookie_closed2.png"); }); } } } // ================================================================ // MUSIK-BUTTON // ================================================================ Label { id: musicButton anchors { right: parent.right bottom: parent.bottom margins: units.gu(2) } width: units.gu(10) height: units.gu(10) text: musicPlaying ? "\uD83D\uDD0A" : "\uD83D\uDD07" fontSize: "xxx-large" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter color: theme.palette.normalText visible: true MouseArea { anchors.fill: parent hoverEnabled: true onClicked: { console.log("DEBUG QML: Music button clicked, current musicPlaying: " + musicPlaying); if (musicPlaying) { mediaPlayer.stop(); } else { mediaPlayer.play(); } musicPlaying = !musicPlaying; console.log("DEBUG QML: Setting music enabled to: " + musicPlaying); py.call("fortunecookie.set_music_enabled", [musicPlaying]); } } } } // ================================================================ // SEITE 1: EINSTELLUNGEN // ================================================================ Settings { id: settingsPage } } }