741 lines
25 KiB
QML
741 lines
25 KiB
QML
/*
|
|
* Komplex Wallpaper Engine
|
|
* Copyright (C) 2025 @DigitalArtifex | github.com/DigitalArtifex
|
|
*
|
|
* config.qml
|
|
*
|
|
* This component provides a configuration interface for the Komplex Wallpaper Engine,
|
|
* allowing users to customize shader settings, channel configurations, and other
|
|
* parameters related to the wallpaper engine.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
*/
|
|
// pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Dialogs
|
|
import QtQuick.Layouts
|
|
import org.kde.kirigami as Kirigami
|
|
import org.kde.plasma.core as PlasmaCore
|
|
import QtCore
|
|
import Qt.labs.folderlistmodel 2.15
|
|
|
|
import com.github.digitalartifex.komplex 1.0 as Komplex
|
|
|
|
Kirigami.FormLayout
|
|
{
|
|
id: root
|
|
twinFormLayouts: parentLayout // required by parent
|
|
property alias formLayout: root // required by parent
|
|
property alias cfg_pauseMode: pauseModeCombo.currentIndex
|
|
property alias cfg_isPaused: runningCombo.checked
|
|
property alias cfg_selectedShaderIndex: selectedShader.currentIndex
|
|
property alias cfg_selectedShaderPath: selectedShader.shader
|
|
property alias cfg_iChannel0: shaderChannelConfig0.source
|
|
property alias cfg_iChannel1: shaderChannelConfig1.source
|
|
property alias cfg_iChannel2: shaderChannelConfig2.source
|
|
property alias cfg_iChannel3: shaderChannelConfig3.source
|
|
property alias cfg_iChannel0_flag: shaderChannelConfig0.enabled
|
|
property alias cfg_iChannel1_flag: shaderChannelConfig1.enabled
|
|
property alias cfg_iChannel2_flag: shaderChannelConfig2.enabled
|
|
property alias cfg_iChannel3_flag: shaderChannelConfig3.enabled
|
|
property alias cfg_iChannel0_type: shaderChannelConfig0.type
|
|
property alias cfg_iChannel1_type: shaderChannelConfig1.type
|
|
property alias cfg_iChannel2_type: shaderChannelConfig2.type
|
|
property alias cfg_iChannel3_type: shaderChannelConfig3.type
|
|
property alias cfg_iChannel0_timeScale: shaderChannelConfig0.timeScale
|
|
property alias cfg_iChannel1_timeScale: shaderChannelConfig1.timeScale
|
|
property alias cfg_iChannel2_timeScale: shaderChannelConfig2.timeScale
|
|
property alias cfg_iChannel3_timeScale: shaderChannelConfig3.timeScale
|
|
property alias cfg_iChannel0_resolution_scale: shaderChannelConfig0.resolution_scale
|
|
property alias cfg_iChannel1_resolution_scale: shaderChannelConfig1.resolution_scale
|
|
property alias cfg_iChannel2_resolution_scale: shaderChannelConfig2.resolution_scale
|
|
property alias cfg_iChannel3_resolution_scale: shaderChannelConfig3.resolution_scale
|
|
property alias cfg_iChannel0_resolution_x: shaderChannelConfig0.resolution_x
|
|
property alias cfg_iChannel0_resolution_y: shaderChannelConfig0.resolution_y
|
|
property alias cfg_iChannel1_resolution_x: shaderChannelConfig1.resolution_x
|
|
property alias cfg_iChannel1_resolution_y: shaderChannelConfig1.resolution_y
|
|
property alias cfg_iChannel2_resolution_x: shaderChannelConfig2.resolution_x
|
|
property alias cfg_iChannel2_resolution_y: shaderChannelConfig2.resolution_y
|
|
property alias cfg_iChannel3_resolution_x: shaderChannelConfig3.resolution_x
|
|
property alias cfg_iChannel3_resolution_y: shaderChannelConfig3.resolution_y
|
|
property alias cfg_shaderSpeed: speedSlider.value
|
|
property alias cfg_mouseSpeedBias: mouseBiasSlider.value
|
|
property alias cfg_mouseAllowed: mouseEnableButton.checked
|
|
property bool cfg_infoPlasma6Preview_dismissed
|
|
property bool cfg_warningResources_dismissed
|
|
property bool cfg_emergencyHelp_dismissed
|
|
property bool cfg_infoiChannelSettings_dismissed
|
|
property alias cfg_checkActiveScreen: activeScreenOnlyCheckbox.checked
|
|
property alias cfg_excludeWindows: excludeWindows.windows
|
|
property alias cfg_running: runningCombo.checked
|
|
|
|
property alias cfg_shader_package: selectedShaderPack.shader
|
|
property alias cfg_shader_package_index: selectedShaderPack.currentIndex
|
|
property alias cfg_komplex_mode: engineModeSelect.currentIndex
|
|
|
|
Palette
|
|
{
|
|
id: palette
|
|
}
|
|
|
|
Komplex.ShaderPackModel
|
|
{
|
|
id: shaderPackModel
|
|
onJsonChanged:
|
|
{
|
|
// Handle the JSON change if needed
|
|
console.log("Shader pack JSON changed:", shaderPackModel.json);
|
|
root.cfg_shader_package = shaderPackModel.shaderPackPath + "/" + shaderPackModel.shaderPackName + "/pack.json"
|
|
}
|
|
}
|
|
|
|
// Engine Mode Selection
|
|
|
|
RowLayout
|
|
{
|
|
Kirigami.FormData.label: i18nd("com.github.digitalartifex.komplex", "Engine Mode:")
|
|
ComboBox
|
|
{
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 11
|
|
id: engineModeSelect
|
|
currentIndex: root.cfg_komplex_mode
|
|
onCurrentIndexChanged: root.cfg_komplex_mode = currentIndex
|
|
textRole: "label"
|
|
model: [
|
|
{ "label": i18nd("@option:komplex_mode", "ShaderToys") },
|
|
{ "label": i18nd("@option:komplex_mode", "Komplex") }
|
|
]
|
|
}
|
|
}
|
|
TabBar
|
|
{
|
|
Layout.fillWidth: true
|
|
id: navBar
|
|
width: parent.width
|
|
TabButton {
|
|
text: qsTr("Shader")
|
|
}
|
|
TabButton {
|
|
text: qsTr("Shader Settings")
|
|
}
|
|
TabButton {
|
|
text: qsTr("Extra Settings")
|
|
}
|
|
}
|
|
RowLayout
|
|
{
|
|
Layout.fillWidth: true
|
|
Kirigami.InlineMessage
|
|
{
|
|
id: warningResources
|
|
Layout.fillWidth: true
|
|
type: Kirigami.MessageType.Warning
|
|
text: qsTr("Some shaders might consume more power and resources than others, beware!")
|
|
showCloseButton: true
|
|
visible: !root.cfg_warningResources_dismissed
|
|
onVisibleChanged: () =>
|
|
{
|
|
root.cfg_warningResources_dismissed = true;
|
|
}
|
|
}
|
|
}
|
|
RowLayout
|
|
{
|
|
visible: root.cfg_komplex_mode === 0 && navBar.currentIndex === 0
|
|
|
|
id: shaderOutputLayout
|
|
spacing: Kirigami.Units.smallSpacing
|
|
Kirigami.FormData.label: i18nd("com.github.digitalartifex.komplex", "Output Shader:")
|
|
|
|
ComboBox
|
|
{
|
|
property string shader
|
|
|
|
id: selectedShader
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 11
|
|
model: FolderListModel
|
|
{
|
|
id: folderListModel
|
|
showDirs: false
|
|
showFiles: true
|
|
showHidden: true
|
|
nameFilters: ["*.frag.qsb"]
|
|
folder: "file://" + shaderPackModel.shadersPath + "/generative"
|
|
}
|
|
delegate: Component
|
|
{
|
|
id: folderListDelegate
|
|
ItemDelegate
|
|
{
|
|
width: parent ? parent.width : 0
|
|
text: fileBaseName.replace("_", " ").charAt(0).toUpperCase() + fileBaseName.replace("_", " ").slice(1)
|
|
}
|
|
}
|
|
|
|
textRole: "fileBaseName"
|
|
currentIndex: root.cfg_selectedShaderIndex
|
|
displayText: currentIndex === -1 ? "Custom File" : currentText.replace("_", " ").charAt(0).toUpperCase() + currentText.replace("_", " ").slice(1)
|
|
|
|
onCurrentTextChanged:
|
|
{
|
|
root.cfg_selectedShaderIndex = currentIndex;
|
|
|
|
if (root.cfg_selectedShaderIndex === -1)
|
|
return;
|
|
|
|
var source = model.get(currentIndex, "fileUrl");
|
|
shader = source;
|
|
}
|
|
}
|
|
|
|
Button
|
|
{
|
|
id: shaderFileButton
|
|
icon.name: "folder-symbolic"
|
|
text: i18nd("@button:toggle_select_shader", "Select File")
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 9
|
|
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
|
|
onClicked:
|
|
{
|
|
fileDialog.currentFolder = "file://" + shaderPackModel.shadersPath + "/generative";
|
|
fileDialog.open();
|
|
}
|
|
}
|
|
|
|
FileDialog
|
|
{
|
|
id: fileDialog
|
|
fileMode: FileDialog.OpenFile
|
|
title: i18nd("@dialog_title:choose_shader", "Choose a shader")
|
|
// will accept and auto convert .frag in the near future
|
|
nameFilters: ["Shader files (*.frag.qsb)", "All files (*)"]
|
|
visible: false
|
|
currentFolder: `${StandardPaths.writableLocation(StandardPaths.HomeLocation)}/.local/share/komplex/shaders/`
|
|
onAccepted:
|
|
{
|
|
root.cfg_selectedShaderIndex = -1;
|
|
root.cfg_selectedShaderPath = selectedFile;
|
|
}
|
|
}
|
|
}
|
|
|
|
// iChannel0 Configuration
|
|
RowLayout
|
|
{
|
|
visible: root.cfg_komplex_mode === 0 && navBar.currentIndex === 0
|
|
id: channel0ConfigLayout
|
|
Kirigami.FormData.label: i18nd("com.github.digitalartifex.komplex", "Channel 1:")
|
|
|
|
spacing: Kirigami.Units.smallSpacing
|
|
|
|
Text
|
|
{
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 11
|
|
|
|
color: palette.text
|
|
text: i18nd("@iChannel0_source", root.cfg_iChannel0 ? root.cfg_iChannel0 : "No source selected")
|
|
verticalAlignment: Text.AlignVCenter
|
|
elide: Text.ElideLeft
|
|
}
|
|
|
|
Button
|
|
{
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 2
|
|
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
|
|
icon.name: "configure-symbolic"
|
|
onClicked: () =>
|
|
{
|
|
shaderChannelConfig0.configureChannel();
|
|
shaderChannelOverlay0.open();
|
|
}
|
|
}
|
|
}
|
|
|
|
Kirigami.OverlaySheet
|
|
{
|
|
id: shaderChannelOverlay0
|
|
parent: applicationWindow().overlay
|
|
implicitHeight: 400
|
|
|
|
ShaderChannelConfiguration
|
|
{
|
|
id: shaderChannelConfig0
|
|
palette: palette
|
|
height: 350
|
|
onAccepted: shaderChannelOverlay0.close(); // Close the overlay after configuration
|
|
onRejected: shaderChannelOverlay0.close();
|
|
}
|
|
}
|
|
|
|
// iChannel1 Configuration
|
|
RowLayout
|
|
{
|
|
visible: root.cfg_komplex_mode === 0 && navBar.currentIndex === 0
|
|
id: channel1ConfigLayout
|
|
|
|
Kirigami.FormData.label: i18nd("com.github.digitalartifex.komplex", "Channel 2:")
|
|
|
|
Text
|
|
{
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 11
|
|
color: palette.text
|
|
text: i18nd("@iChannel1_source", root.cfg_iChannel1 ? root.cfg_iChannel1 : "No source selected")
|
|
verticalAlignment: Text.AlignVCenter
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
Button
|
|
{
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 2
|
|
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
|
|
icon.name: "configure-symbolic"
|
|
onClicked: () =>
|
|
{
|
|
shaderChannelConfig1.configureChannel();
|
|
shaderChannelOverlay1.open();
|
|
}
|
|
}
|
|
}
|
|
|
|
Kirigami.OverlaySheet
|
|
{
|
|
id: shaderChannelOverlay1
|
|
parent: applicationWindow().overlay
|
|
implicitHeight: 400
|
|
|
|
ShaderChannelConfiguration
|
|
{
|
|
id: shaderChannelConfig1
|
|
height: 350
|
|
onAccepted: shaderChannelOverlay1.close(); // Close the overlay after configuration
|
|
onRejected: shaderChannelOverlay1.close();
|
|
}
|
|
}
|
|
|
|
// iChannel2 Configuration
|
|
RowLayout
|
|
{
|
|
visible: root.cfg_komplex_mode === 0 && navBar.currentIndex === 0
|
|
id: channel2ConfigLayout
|
|
|
|
Kirigami.FormData.label: i18nd("com.github.digitalartifex.komplex", "Channel 3:")
|
|
|
|
Text
|
|
{
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 11
|
|
color: palette.text
|
|
text: i18nd("@iChannel2_source", root.cfg_iChannel2 ? root.cfg_iChannel2 : "No source selected")
|
|
verticalAlignment: Text.AlignVCenter
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
Button
|
|
{
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 2
|
|
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
|
|
icon.name: "configure-symbolic"
|
|
onClicked: () =>
|
|
{
|
|
shaderChannelConfig2.configureChannel();
|
|
shaderChannelOverlay2.open();
|
|
}
|
|
}
|
|
}
|
|
|
|
Kirigami.OverlaySheet
|
|
{
|
|
id: shaderChannelOverlay2
|
|
parent: applicationWindow().overlay
|
|
implicitHeight: 400
|
|
|
|
ShaderChannelConfiguration
|
|
{
|
|
id: shaderChannelConfig2
|
|
height: 350
|
|
onAccepted: shaderChannelOverlay2.close(); // Close the overlay after configuration
|
|
onRejected: shaderChannelOverlay2.close();
|
|
}
|
|
}
|
|
|
|
// iChannel3 Configuration
|
|
RowLayout
|
|
{
|
|
visible: root.cfg_komplex_mode === 0 && navBar.currentIndex === 0
|
|
Layout.fillWidth: true
|
|
Kirigami.FormData.label: i18nd("com.github.digitalartifex.komplex", "Channel 4:")
|
|
|
|
Text
|
|
{
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 11
|
|
color: palette.text
|
|
text: i18nd("@iChannel0_source", root.cfg_iChannel3 ? root.cfg_iChannel3 : "No source selected")
|
|
verticalAlignment: Text.AlignVCenter
|
|
elide: Text.ElideLeft
|
|
}
|
|
|
|
Button
|
|
{
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 2
|
|
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
|
|
icon.name: "configure-symbolic"
|
|
onClicked: () =>
|
|
{
|
|
shaderChannelConfig3.configureChannel();
|
|
shaderChannelOverlay3.open();
|
|
}
|
|
}
|
|
}
|
|
|
|
Kirigami.OverlaySheet
|
|
{
|
|
id: shaderChannelOverlay3
|
|
parent: applicationWindow().overlay
|
|
implicitHeight: 400
|
|
|
|
ShaderChannelConfiguration
|
|
{
|
|
id: shaderChannelConfig3
|
|
height: 350
|
|
onAccepted: shaderChannelOverlay3.close(); // Close the overlay after configuration
|
|
onRejected: shaderChannelOverlay3.close();
|
|
}
|
|
}
|
|
|
|
RowLayout
|
|
{
|
|
visible: navBar.currentIndex === 1
|
|
id: speedLayout
|
|
Layout.fillWidth: true
|
|
|
|
Kirigami.FormData.label: i18nd("com.github.digitalartifex.komplex", "Shader speed:")
|
|
|
|
Slider
|
|
{
|
|
id: speedSlider
|
|
Layout.fillWidth: true
|
|
from: -10.0
|
|
to: 10.0
|
|
stepSize: 0.01
|
|
onValueChanged: shaderSpeedField.text = String(value.toFixed(2));
|
|
}
|
|
|
|
TextField
|
|
{
|
|
id: shaderSpeedField
|
|
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
|
horizontalAlignment: Text.AlignRight
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 4
|
|
onEditingFinished: () =>
|
|
{
|
|
let inputValue = parseFloat(text);
|
|
|
|
if (isNaN(inputValue) || inputValue < speedSlider.from)
|
|
inputValue = speedSlider.from;
|
|
else if (inputValue > speedSlider.to)
|
|
inputValue = speedSlider.to;
|
|
|
|
text = inputValue.toFixed(2);
|
|
speedSlider.value = inputValue;
|
|
}
|
|
Keys.onPressed: (event) =>
|
|
{
|
|
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter)
|
|
{
|
|
shaderSpeedField.focus = false; // Unfocus the TextField
|
|
event.accepted = true; // Prevent further propagation of the key event
|
|
}
|
|
}
|
|
background: Rectangle
|
|
{
|
|
color: shaderSpeedField.activeFocus ? palette.base : "transparent"
|
|
border.color: shaderSpeedField.activeFocus ? palette.highlight : "transparent"
|
|
border.width: 1
|
|
radius: 4
|
|
anchors.fill: shaderSpeedField
|
|
anchors.margins: -2
|
|
}
|
|
}
|
|
|
|
}
|
|
ComboBox
|
|
{
|
|
visible: navBar.currentIndex === 1
|
|
id: pauseModeCombo
|
|
|
|
Kirigami.FormData.label: i18nd("@buttonGroup:pause_mode", "Pause:")
|
|
model: [
|
|
{
|
|
'label': i18nd("@option:pause_mode", "Maximized or full-screen windows")
|
|
},
|
|
{
|
|
'label': i18nd("@option:pause_mode", "Active window is present")
|
|
},
|
|
{
|
|
'label': i18nd("@option:pause_mode", "At least one window is shown")
|
|
},
|
|
{
|
|
'label': i18nd("@option:pause_mode", "Never")
|
|
}
|
|
]
|
|
textRole: "label"
|
|
onCurrentIndexChanged: root.cfg_pauseMode = currentIndex
|
|
currentIndex: root.cfg_pauseMode
|
|
}
|
|
|
|
CheckBox
|
|
{
|
|
visible: navBar.currentIndex === 1
|
|
id: activeScreenOnlyCheckbox
|
|
|
|
Kirigami.FormData.label: i18nd("@checkbox:screen_filter", "Filter:")
|
|
text: i18n("Only check for windows in active screen")
|
|
}
|
|
|
|
TextField
|
|
{
|
|
visible: navBar.currentIndex === 1
|
|
id: excludeWindows
|
|
property var windows: []
|
|
width: Kirigami.Units.gridUnit * 11
|
|
|
|
Kirigami.FormData.label: i18nd("com.github.digitalartifex.komplex", "Exclude windows:")
|
|
text: windows.join(",")
|
|
onEditingFinished: () =>
|
|
{
|
|
windows = excludeWindows.text.trim().replace(/\s+/g, "").split(",");
|
|
}
|
|
ToolTip.visible: hovered
|
|
ToolTip.text: qsTr("A comma-separated list of fully-qualified App-IDs to exclude their windows from triggering pause mode.")
|
|
}
|
|
|
|
CheckBox
|
|
{
|
|
visible: navBar.currentIndex === 1
|
|
Kirigami.FormData.label: i18nd("com.github.digitalartifex.komplex", cfg_isPaused ? "Playing" : "Paused")
|
|
|
|
id: runningCombo
|
|
checked: root.cfg_running
|
|
text: i18n("Play/Pause the shader")
|
|
onCheckedChanged: () =>
|
|
{
|
|
wallpaper.configuration.running = checked;
|
|
root.cfg_running = checked;
|
|
}
|
|
}
|
|
|
|
RowLayout
|
|
{
|
|
visible: navBar.currentIndex === 1
|
|
id: mouseLayout
|
|
|
|
Kirigami.FormData.label: i18nd("com.github.digitalartifex.komplex", "Mouse allowed:")
|
|
Button
|
|
{
|
|
id: mouseEnableButton
|
|
icon.name: checked ? "followmouse-symbolic" : "hidemouse-symbolic"
|
|
text: i18nd("@button:toggle_use_mouse", checked ? "Enabled" : "Disabled")
|
|
checkable: true
|
|
ToolTip.visible: hovered
|
|
ToolTip.text: qsTr("Enabling this will allow the shader to interact with the cursor but will prevent interaction with desktop elements")
|
|
}
|
|
}
|
|
|
|
RowLayout
|
|
{
|
|
id: mouseBiasLayout
|
|
visible: root.cfg_mouseAllowed && navBar.currentIndex === 1
|
|
|
|
Kirigami.FormData.label: i18nd("com.github.digitalartifex.komplex", "Mouse bias:")
|
|
ColumnLayout
|
|
{
|
|
Slider
|
|
{
|
|
id: mouseBiasSlider
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 16
|
|
from: -10.0
|
|
to: 10.0
|
|
stepSize: 0.01
|
|
value: root.cfg_mouseSpeedBias ? root.cfg_mouseSpeedBias : 1.0
|
|
onValueChanged: () =>
|
|
{
|
|
mouseBiasField.text = String(value.toFixed(2));
|
|
wallpaper.configuration.mouseBias = mouseBiasField.text;
|
|
root.cfg_mouseSpeedBias = mouseBiasField.text;
|
|
}
|
|
}
|
|
}
|
|
ColumnLayout
|
|
{
|
|
visible: navBar.currentIndex === 1
|
|
TextField
|
|
{
|
|
id: mouseBiasField
|
|
text: root.cfg_mouseSpeedBias ? String(root.cfg_mouseSpeedBias.toFixed(2)) : "1.00"
|
|
inputMethodHints: Qt.ImhFormattedNumbersOnly
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 3
|
|
onEditingFinished: () =>
|
|
{
|
|
let inputValue = parseFloat(text);
|
|
|
|
if (isNaN(inputValue) || inputValue < mouseBiasSlider.from)
|
|
inputValue = mouseBiasSlider.from;
|
|
else if (inputValue > mouseBiasSlider.to)
|
|
inputValue = mouseBiasSlider.to;
|
|
|
|
text = inputValue.toFixed(2);
|
|
mouseBiasSlider.value = inputValue;
|
|
wallpaper.configuration.mouseBias = inputValue;
|
|
root.cfg_mouseSpeedBias = inputValue;
|
|
}
|
|
Keys.onPressed: (event) =>
|
|
{
|
|
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter)
|
|
{
|
|
mouseBiasField.focus = false; // Unfocus the TextField
|
|
event.accepted = true; // Prevent further propagation of the key event
|
|
}
|
|
}
|
|
background: Rectangle
|
|
{
|
|
color: mouseBiasField.activeFocus ? palette.base : "transparent"
|
|
border.color: mouseBiasField.activeFocus ? palette.highlight : "transparent"
|
|
border.width: 1
|
|
radius: 4
|
|
anchors.fill: mouseBiasField
|
|
anchors.margins: -2
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Button
|
|
{
|
|
visible: navBar.currentIndex === 1
|
|
id: kofiButton
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 5
|
|
Layout.preferredHeight: Kirigami.Units.gridUnit * 3
|
|
|
|
contentItem: RowLayout
|
|
{
|
|
AnimatedImage
|
|
{
|
|
source: "icons/kofi.gif"
|
|
sourceSize.width: 36
|
|
sourceSize.height: 36
|
|
fillMode: Image.Pad
|
|
horizontalAlignment: Image.AlignLeft
|
|
transform: Translate
|
|
{
|
|
x: 8
|
|
}
|
|
}
|
|
Text
|
|
{
|
|
text: i18nd("@button:kofi", "Kofi")
|
|
horizontalAlignment: Text.AlignHCenter
|
|
color: palette.text
|
|
transform: Translate
|
|
{
|
|
x: -8
|
|
}
|
|
}
|
|
}
|
|
onClicked: () =>
|
|
{
|
|
Qt.openUrlExternally("https://ko-fi.com/digitalartifex");
|
|
}
|
|
}
|
|
|
|
RowLayout
|
|
{
|
|
visible: root.cfg_komplex_mode === 1 && navBar.currentIndex === 0
|
|
|
|
spacing: Kirigami.Units.smallSpacing
|
|
Kirigami.FormData.label: i18nd("com.github.digitalartifex.komplex", "Shader Pack:")
|
|
|
|
ComboBox
|
|
{
|
|
property string shader
|
|
|
|
id: selectedShaderPack
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 11
|
|
model: FolderListModel
|
|
{
|
|
id: packListModel
|
|
showDirs: true
|
|
showFiles: false
|
|
showHidden: false
|
|
nameFilters: ["*.frag.qsb"]
|
|
folder: "file://" + shaderPackModel.shadersPath + "/generative"
|
|
}
|
|
delegate: Component
|
|
{
|
|
id: packListDelegate
|
|
ItemDelegate
|
|
{
|
|
width: parent ? parent.width : 0
|
|
text: fileBaseName.replace("_", " ").charAt(0).toUpperCase() + fileBaseName.replace("_", " ").slice(1)
|
|
}
|
|
}
|
|
|
|
textRole: "fileBaseName"
|
|
currentIndex: root.cfg_shader_package
|
|
displayText: currentIndex === -1 ? "Custom File" : currentText.replace("_", " ").charAt(0).toUpperCase() + currentText.replace("_", " ").slice(1)
|
|
|
|
onCurrentTextChanged:
|
|
{
|
|
root.cfg_selectedShaderIndex = currentIndex;
|
|
|
|
if (root.cfg_selectedShaderIndex === -1)
|
|
return;
|
|
|
|
var source = model.get(currentIndex, "fileUrl");
|
|
shader = source;
|
|
}
|
|
}
|
|
|
|
Button
|
|
{
|
|
id: packFileButton
|
|
icon.name: "folder-symbolic"
|
|
text: i18nd("@button:toggle_select_shader", "Select File")
|
|
Layout.preferredWidth: Kirigami.Units.gridUnit * 9
|
|
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
|
|
onClicked:
|
|
{
|
|
packDialog.currentFolder = "file://" + shaderPackModel.shaderPackInstallPath;
|
|
packDialog.open();
|
|
}
|
|
}
|
|
|
|
FileDialog
|
|
{
|
|
id: packDialog
|
|
fileMode: FileDialog.OpenFile
|
|
title: i18nd("@dialog_title:choose_shader", "Choose a shader")
|
|
// will accept and auto convert .frag in the near future
|
|
nameFilters: ["Shader Package files (*.json)", "All files (*)"]
|
|
visible: false
|
|
currentFolder: "file://" + shaderPackModel.shaderPackInstallPath
|
|
onAccepted:
|
|
{
|
|
root.cfg_shader_package_index = -1;
|
|
root.cfg_shader_package = selectedFile;
|
|
}
|
|
}
|
|
}
|
|
}
|