mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
Abstract away plugin dev a little more
This commit is contained in:
@@ -9,6 +9,10 @@ Item {
|
||||
property var components: null
|
||||
property bool noBackground: false
|
||||
required property var axis
|
||||
property string section: "center"
|
||||
property var parentScreen: null
|
||||
property real widgetThickness: 30
|
||||
property real barThickness: 48
|
||||
|
||||
readonly property bool isVertical: axis?.isVertical ?? false
|
||||
readonly property real spacing: noBackground ? 2 : Theme.spacingXS
|
||||
@@ -371,7 +375,24 @@ Item {
|
||||
item.axis = root.axis
|
||||
}
|
||||
if (root.axis && "isVertical" in item) {
|
||||
item.isVertical = root.axis.isVertical
|
||||
try {
|
||||
item.isVertical = root.axis.isVertical
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
// Inject properties for plugin widgets
|
||||
if ("section" in item) {
|
||||
item.section = root.section
|
||||
}
|
||||
if ("parentScreen" in item) {
|
||||
item.parentScreen = root.parentScreen
|
||||
}
|
||||
if ("widgetThickness" in item) {
|
||||
item.widgetThickness = root.widgetThickness
|
||||
}
|
||||
if ("barThickness" in item) {
|
||||
item.barThickness = root.barThickness
|
||||
}
|
||||
|
||||
// Inject PluginService for plugin widgets
|
||||
|
||||
@@ -537,6 +537,9 @@ Item {
|
||||
widgetsModel: SettingsData.dankBarLeftWidgetsModel
|
||||
components: topBarContent.allComponents
|
||||
noBackground: SettingsData.dankBarNoBackground
|
||||
parentScreen: barWindow.screen
|
||||
widgetThickness: barWindow.widgetThickness
|
||||
barThickness: barWindow.effectiveBarThickness
|
||||
}
|
||||
|
||||
RightSection {
|
||||
@@ -549,6 +552,9 @@ Item {
|
||||
widgetsModel: SettingsData.dankBarRightWidgetsModel
|
||||
components: topBarContent.allComponents
|
||||
noBackground: SettingsData.dankBarNoBackground
|
||||
parentScreen: barWindow.screen
|
||||
widgetThickness: barWindow.widgetThickness
|
||||
barThickness: barWindow.effectiveBarThickness
|
||||
}
|
||||
|
||||
CenterSection {
|
||||
@@ -561,6 +567,9 @@ Item {
|
||||
widgetsModel: SettingsData.dankBarCenterWidgetsModel
|
||||
components: topBarContent.allComponents
|
||||
noBackground: SettingsData.dankBarNoBackground
|
||||
parentScreen: barWindow.screen
|
||||
widgetThickness: barWindow.widgetThickness
|
||||
barThickness: barWindow.effectiveBarThickness
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,6 +589,9 @@ Item {
|
||||
widgetsModel: SettingsData.dankBarLeftWidgetsModel
|
||||
components: topBarContent.allComponents
|
||||
noBackground: SettingsData.dankBarNoBackground
|
||||
parentScreen: barWindow.screen
|
||||
widgetThickness: barWindow.widgetThickness
|
||||
barThickness: barWindow.effectiveBarThickness
|
||||
}
|
||||
|
||||
CenterSection {
|
||||
@@ -593,6 +605,9 @@ Item {
|
||||
widgetsModel: SettingsData.dankBarCenterWidgetsModel
|
||||
components: topBarContent.allComponents
|
||||
noBackground: SettingsData.dankBarNoBackground
|
||||
parentScreen: barWindow.screen
|
||||
widgetThickness: barWindow.widgetThickness
|
||||
barThickness: barWindow.effectiveBarThickness
|
||||
}
|
||||
|
||||
RightSection {
|
||||
|
||||
@@ -8,6 +8,9 @@ Item {
|
||||
property var components: null
|
||||
property bool noBackground: false
|
||||
required property var axis
|
||||
property var parentScreen: null
|
||||
property real widgetThickness: 30
|
||||
property real barThickness: 48
|
||||
|
||||
readonly property bool isVertical: axis?.isVertical ?? false
|
||||
|
||||
@@ -38,6 +41,10 @@ Item {
|
||||
components: root.components
|
||||
isInColumn: false
|
||||
axis: root.axis
|
||||
section: "left"
|
||||
parentScreen: root.parentScreen
|
||||
widgetThickness: root.widgetThickness
|
||||
barThickness: root.barThickness
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,6 +70,10 @@ Item {
|
||||
components: root.components
|
||||
isInColumn: true
|
||||
axis: root.axis
|
||||
section: "left"
|
||||
parentScreen: root.parentScreen
|
||||
widgetThickness: root.widgetThickness
|
||||
barThickness: root.barThickness
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ Item {
|
||||
property var components: null
|
||||
property bool noBackground: false
|
||||
required property var axis
|
||||
property var parentScreen: null
|
||||
property real widgetThickness: 30
|
||||
property real barThickness: 48
|
||||
|
||||
readonly property bool isVertical: axis?.isVertical ?? false
|
||||
|
||||
@@ -40,6 +43,10 @@ Item {
|
||||
components: root.components
|
||||
isInColumn: false
|
||||
axis: root.axis
|
||||
section: "right"
|
||||
parentScreen: root.parentScreen
|
||||
widgetThickness: root.widgetThickness
|
||||
barThickness: root.barThickness
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,6 +72,10 @@ Item {
|
||||
components: root.components
|
||||
isInColumn: true
|
||||
axis: root.axis
|
||||
section: "right"
|
||||
parentScreen: root.parentScreen
|
||||
widgetThickness: root.widgetThickness
|
||||
barThickness: root.barThickness
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@ Loader {
|
||||
property var components: null
|
||||
property bool isInColumn: false
|
||||
property var axis: null
|
||||
property string section: "center"
|
||||
property var parentScreen: null
|
||||
property real widgetThickness: 30
|
||||
property real barThickness: 48
|
||||
|
||||
asynchronous: false
|
||||
|
||||
@@ -21,20 +25,59 @@ Loader {
|
||||
|
||||
signal contentItemReady(var item)
|
||||
|
||||
Binding {
|
||||
target: root.item
|
||||
when: root.item && "parentScreen" in root.item
|
||||
property: "parentScreen"
|
||||
value: root.parentScreen
|
||||
restoreMode: Binding.RestoreNone
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: root.item
|
||||
when: root.item && "section" in root.item
|
||||
property: "section"
|
||||
value: root.section
|
||||
restoreMode: Binding.RestoreNone
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: root.item
|
||||
when: root.item && "widgetThickness" in root.item
|
||||
property: "widgetThickness"
|
||||
value: root.widgetThickness
|
||||
restoreMode: Binding.RestoreNone
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: root.item
|
||||
when: root.item && "barThickness" in root.item
|
||||
property: "barThickness"
|
||||
value: root.barThickness
|
||||
restoreMode: Binding.RestoreNone
|
||||
}
|
||||
|
||||
Binding {
|
||||
target: root.item
|
||||
when: root.item && "axis" in root.item
|
||||
property: "axis"
|
||||
value: root.axis
|
||||
restoreMode: Binding.RestoreNone
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
if (item) {
|
||||
contentItemReady(item)
|
||||
if (widgetId === "spacer") {
|
||||
item.spacerSize = Qt.binding(() => spacerSize)
|
||||
}
|
||||
if (axis && "axis" in item) {
|
||||
item.axis = axis
|
||||
}
|
||||
if (axis && "isVertical" in item) {
|
||||
item.isVertical = axis.isVertical
|
||||
try {
|
||||
item.isVertical = axis.isVertical
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
// Inject PluginService for plugin widgets
|
||||
if (item.pluginService !== undefined) {
|
||||
console.log("WidgetHost: Injecting PluginService into plugin widget:", widgetId)
|
||||
item.pluginService = PluginService
|
||||
|
||||
53
Modules/Plugins/BaseHorizontalPill.qml
Normal file
53
Modules/Plugins/BaseHorizontalPill.qml
Normal file
@@ -0,0 +1,53 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property var axis: null
|
||||
property string section: "center"
|
||||
property var popoutTarget: null
|
||||
property var parentScreen: null
|
||||
property real widgetThickness: 30
|
||||
property real barThickness: 48
|
||||
property alias content: contentLoader.sourceComponent
|
||||
|
||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||
|
||||
signal clicked()
|
||||
|
||||
width: contentLoader.item ? (contentLoader.item.implicitWidth + horizontalPadding * 2) : 0
|
||||
height: widgetThickness
|
||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
||||
color: {
|
||||
if (SettingsData.dankBarNoBackground) {
|
||||
return "transparent"
|
||||
}
|
||||
|
||||
const baseColor = mouseArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: contentLoader
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onPressed: {
|
||||
if (popoutTarget && popoutTarget.setTriggerPosition) {
|
||||
const globalPos = mapToGlobal(0, 0)
|
||||
const currentScreen = parentScreen || Screen
|
||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, width)
|
||||
popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen)
|
||||
}
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Modules/Plugins/BaseVerticalPill.qml
Normal file
53
Modules/Plugins/BaseVerticalPill.qml
Normal file
@@ -0,0 +1,53 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property var axis: null
|
||||
property string section: "center"
|
||||
property var popoutTarget: null
|
||||
property var parentScreen: null
|
||||
property real widgetThickness: 30
|
||||
property real barThickness: 48
|
||||
property alias content: contentLoader.sourceComponent
|
||||
|
||||
readonly property real horizontalPadding: SettingsData.dankBarNoBackground ? 0 : Math.max(Theme.spacingXS, Theme.spacingS * (widgetThickness / 30))
|
||||
|
||||
signal clicked()
|
||||
|
||||
width: widgetThickness
|
||||
height: contentLoader.item ? (contentLoader.item.implicitHeight + horizontalPadding * 2) : 0
|
||||
radius: SettingsData.dankBarNoBackground ? 0 : Theme.cornerRadius
|
||||
color: {
|
||||
if (SettingsData.dankBarNoBackground) {
|
||||
return "transparent"
|
||||
}
|
||||
|
||||
const baseColor = mouseArea.containsMouse ? Theme.widgetBaseHoverColor : Theme.widgetBaseBackgroundColor
|
||||
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, baseColor.a * Theme.widgetTransparency)
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: contentLoader
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onPressed: {
|
||||
if (popoutTarget && popoutTarget.setTriggerPosition) {
|
||||
const globalPos = mapToGlobal(0, 0)
|
||||
const currentScreen = parentScreen || Screen
|
||||
const pos = SettingsData.getPopupTriggerPosition(globalPos, currentScreen, barThickness, height)
|
||||
popoutTarget.setTriggerPosition(pos.x, pos.y, pos.width, section, currentScreen)
|
||||
}
|
||||
root.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
131
Modules/Plugins/ListSetting.qml
Normal file
131
Modules/Plugins/ListSetting.qml
Normal file
@@ -0,0 +1,131 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
||||
required property string settingKey
|
||||
required property string label
|
||||
property string description: ""
|
||||
property var items: []
|
||||
property Component delegate: null
|
||||
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Component.onCompleted: {
|
||||
const settings = findSettings()
|
||||
if (settings) {
|
||||
items = settings.loadValue(settingKey, [])
|
||||
}
|
||||
}
|
||||
|
||||
onItemsChanged: {
|
||||
const settings = findSettings()
|
||||
if (settings) {
|
||||
settings.saveValue(settingKey, items)
|
||||
}
|
||||
}
|
||||
|
||||
function findSettings() {
|
||||
let item = parent
|
||||
while (item) {
|
||||
if (item.saveValue !== undefined && item.loadValue !== undefined) {
|
||||
return item
|
||||
}
|
||||
item = item.parent
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function addItem(item) {
|
||||
items = items.concat([item])
|
||||
}
|
||||
|
||||
function removeItem(index) {
|
||||
const newItems = items.slice()
|
||||
newItems.splice(index, 1)
|
||||
items = newItems
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: root.label
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: root.description
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
visible: root.description !== ""
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Repeater {
|
||||
model: root.items
|
||||
delegate: root.delegate ? root.delegate : defaultDelegate
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "No items added yet"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
visible: root.items.length === 0
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: defaultDelegate
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: 40
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceContainerHigh
|
||||
border.width: 0
|
||||
|
||||
StyledText {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Theme.spacingM
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: modelData
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.spacingM
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 60
|
||||
height: 28
|
||||
color: removeArea.containsMouse ? Theme.errorHover : Theme.error
|
||||
radius: Theme.cornerRadius
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: "Remove"
|
||||
color: Theme.errorText
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: removeArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
root.removeItem(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
230
Modules/Plugins/ListSettingWithInput.qml
Normal file
230
Modules/Plugins/ListSettingWithInput.qml
Normal file
@@ -0,0 +1,230 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
||||
required property string settingKey
|
||||
required property string label
|
||||
property string description: ""
|
||||
property var fields: []
|
||||
property var items: []
|
||||
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Component.onCompleted: {
|
||||
const settings = findSettings()
|
||||
if (settings) {
|
||||
items = settings.loadValue(settingKey, [])
|
||||
}
|
||||
}
|
||||
|
||||
onItemsChanged: {
|
||||
const settings = findSettings()
|
||||
if (settings) {
|
||||
settings.saveValue(settingKey, items)
|
||||
}
|
||||
}
|
||||
|
||||
function findSettings() {
|
||||
let item = parent
|
||||
while (item) {
|
||||
if (item.saveValue !== undefined && item.loadValue !== undefined) {
|
||||
return item
|
||||
}
|
||||
item = item.parent
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function addItem(item) {
|
||||
items = items.concat([item])
|
||||
}
|
||||
|
||||
function removeItem(index) {
|
||||
const newItems = items.slice()
|
||||
newItems.splice(index, 1)
|
||||
items = newItems
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: root.label
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: root.description
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
visible: root.description !== ""
|
||||
}
|
||||
|
||||
Flow {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Repeater {
|
||||
model: root.fields
|
||||
|
||||
StyledText {
|
||||
text: modelData.label
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
width: modelData.width || 200
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Flow {
|
||||
id: inputRow
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
property var inputFields: []
|
||||
|
||||
Repeater {
|
||||
id: inputRepeater
|
||||
model: root.fields
|
||||
|
||||
DankTextField {
|
||||
width: modelData.width || 200
|
||||
placeholderText: modelData.placeholder || ""
|
||||
|
||||
Component.onCompleted: {
|
||||
inputRow.inputFields.push(this)
|
||||
}
|
||||
|
||||
Keys.onReturnPressed: {
|
||||
addButton.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DankButton {
|
||||
id: addButton
|
||||
width: 50
|
||||
height: 36
|
||||
text: "Add"
|
||||
|
||||
onClicked: {
|
||||
let newItem = {}
|
||||
let hasValue = false
|
||||
|
||||
for (let i = 0; i < root.fields.length; i++) {
|
||||
const field = root.fields[i]
|
||||
const input = inputRow.inputFields[i]
|
||||
const value = input.text.trim()
|
||||
|
||||
if (value !== "") {
|
||||
hasValue = true
|
||||
}
|
||||
|
||||
if (field.required && value === "") {
|
||||
return
|
||||
}
|
||||
|
||||
newItem[field.id] = value || (field.default || "")
|
||||
}
|
||||
|
||||
if (hasValue) {
|
||||
root.addItem(newItem)
|
||||
for (let i = 0; i < inputRow.inputFields.length; i++) {
|
||||
inputRow.inputFields[i].text = ""
|
||||
}
|
||||
if (inputRow.inputFields.length > 0) {
|
||||
inputRow.inputFields[0].forceActiveFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "Current Items"
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
visible: root.items.length > 0
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Repeater {
|
||||
model: root.items
|
||||
|
||||
StyledRect {
|
||||
width: parent.width
|
||||
height: 40
|
||||
radius: Theme.cornerRadius
|
||||
color: Theme.surfaceContainerHigh
|
||||
border.width: 0
|
||||
|
||||
Row {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Theme.spacingM
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Repeater {
|
||||
model: root.fields
|
||||
|
||||
StyledText {
|
||||
text: {
|
||||
const value = root.items[index][modelData.id]
|
||||
return value || ""
|
||||
}
|
||||
color: Theme.surfaceText
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
width: modelData.width || 200
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: Theme.spacingM
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 60
|
||||
height: 28
|
||||
color: removeArea.containsMouse ? Theme.errorHover : Theme.error
|
||||
radius: Theme.cornerRadius
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
text: "Remove"
|
||||
color: Theme.errorText
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: removeArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
root.removeItem(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: "No items added yet"
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
visible: root.items.length === 0
|
||||
}
|
||||
}
|
||||
}
|
||||
69
Modules/Plugins/PluginComponent.qml
Normal file
69
Modules/Plugins/PluginComponent.qml
Normal file
@@ -0,0 +1,69 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
import qs.Widgets
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property var axis: null
|
||||
property string section: "center"
|
||||
property var parentScreen: null
|
||||
property real widgetThickness: 30
|
||||
property real barThickness: 48
|
||||
|
||||
property Component horizontalBarPill: null
|
||||
property Component verticalBarPill: null
|
||||
property Component popoutContent: null
|
||||
property real popoutWidth: 400
|
||||
property real popoutHeight: 400
|
||||
|
||||
readonly property bool isVertical: axis?.isVertical ?? false
|
||||
readonly property bool hasHorizontalPill: horizontalBarPill !== null
|
||||
readonly property bool hasVerticalPill: verticalBarPill !== null
|
||||
readonly property bool hasPopout: popoutContent !== null
|
||||
|
||||
width: isVertical ? (hasVerticalPill ? verticalPill.width : 0) : (hasHorizontalPill ? horizontalPill.width : 0)
|
||||
height: isVertical ? (hasVerticalPill ? verticalPill.height : 0) : (hasHorizontalPill ? horizontalPill.height : 0)
|
||||
|
||||
BaseHorizontalPill {
|
||||
id: horizontalPill
|
||||
visible: !isVertical && hasHorizontalPill
|
||||
axis: root.axis
|
||||
section: root.section
|
||||
popoutTarget: hasPopout ? pluginPopout : null
|
||||
parentScreen: root.parentScreen
|
||||
widgetThickness: root.widgetThickness
|
||||
barThickness: root.barThickness
|
||||
content: root.horizontalBarPill
|
||||
onClicked: {
|
||||
if (hasPopout) {
|
||||
pluginPopout.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BaseVerticalPill {
|
||||
id: verticalPill
|
||||
visible: isVertical && hasVerticalPill
|
||||
axis: root.axis
|
||||
section: root.section
|
||||
popoutTarget: hasPopout ? pluginPopout : null
|
||||
parentScreen: root.parentScreen
|
||||
widgetThickness: root.widgetThickness
|
||||
barThickness: root.barThickness
|
||||
content: root.verticalBarPill
|
||||
onClicked: {
|
||||
if (hasPopout) {
|
||||
pluginPopout.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PluginPopout {
|
||||
id: pluginPopout
|
||||
contentWidth: root.popoutWidth
|
||||
contentHeight: root.popoutHeight
|
||||
pluginContent: root.popoutContent
|
||||
}
|
||||
}
|
||||
116
Modules/Plugins/PluginPopout.qml
Normal file
116
Modules/Plugins/PluginPopout.qml
Normal file
@@ -0,0 +1,116 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
DankPopout {
|
||||
id: root
|
||||
|
||||
property var triggerScreen: null
|
||||
property Component pluginContent: null
|
||||
property real contentWidth: 400
|
||||
property real contentHeight: 400
|
||||
|
||||
function setTriggerPosition(x, y, width, section, screen) {
|
||||
triggerX = x
|
||||
triggerY = y
|
||||
triggerWidth = width
|
||||
triggerSection = section
|
||||
triggerScreen = screen
|
||||
}
|
||||
|
||||
popupWidth: contentWidth
|
||||
popupHeight: popoutContent.item ? popoutContent.item.implicitHeight : contentHeight
|
||||
screen: triggerScreen
|
||||
shouldBeVisible: false
|
||||
visible: shouldBeVisible
|
||||
|
||||
content: Component {
|
||||
Rectangle {
|
||||
id: popoutContainer
|
||||
|
||||
implicitHeight: popoutColumn.implicitHeight + Theme.spacingL * 2
|
||||
color: Theme.popupBackground()
|
||||
radius: Theme.cornerRadius
|
||||
border.width: 0
|
||||
antialiasing: true
|
||||
smooth: true
|
||||
focus: true
|
||||
|
||||
Component.onCompleted: {
|
||||
if (root.shouldBeVisible) {
|
||||
forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: event => {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
root.close()
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
function onShouldBeVisibleChanged() {
|
||||
if (root.shouldBeVisible) {
|
||||
Qt.callLater(() => {
|
||||
popoutContainer.forceActiveFocus()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: popoutColumn
|
||||
width: parent.width - Theme.spacingL * 2
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.margins: Theme.spacingL
|
||||
spacing: Theme.spacingL
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
height: 32
|
||||
visible: closeButton.visible
|
||||
|
||||
Item {
|
||||
width: parent.width - 32
|
||||
height: 32
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: closeButton
|
||||
width: 32
|
||||
height: 32
|
||||
radius: 16
|
||||
color: closeArea.containsMouse ? Theme.errorHover : "transparent"
|
||||
visible: true
|
||||
|
||||
DankIcon {
|
||||
anchors.centerIn: parent
|
||||
name: "close"
|
||||
size: Theme.iconSize - 4
|
||||
color: closeArea.containsMouse ? Theme.error : Theme.surfaceText
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: closeArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onPressed: {
|
||||
root.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: popoutContent
|
||||
width: parent.width
|
||||
sourceComponent: root.pluginContent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Modules/Plugins/PluginSettings.qml
Normal file
33
Modules/Plugins/PluginSettings.qml
Normal file
@@ -0,0 +1,33 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Services
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property string pluginId
|
||||
property var pluginService: null
|
||||
default property alias content: settingsColumn.children
|
||||
|
||||
implicitHeight: settingsColumn.implicitHeight
|
||||
height: implicitHeight
|
||||
|
||||
function saveValue(key, value) {
|
||||
if (pluginService && pluginService.savePluginData) {
|
||||
pluginService.savePluginData(pluginId, key, value)
|
||||
}
|
||||
}
|
||||
|
||||
function loadValue(key, defaultValue) {
|
||||
if (pluginService && pluginService.loadPluginData) {
|
||||
return pluginService.loadPluginData(pluginId, key, defaultValue)
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
Column {
|
||||
id: settingsColumn
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
}
|
||||
}
|
||||
113
Modules/Plugins/SelectionSetting.qml
Normal file
113
Modules/Plugins/SelectionSetting.qml
Normal file
@@ -0,0 +1,113 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
||||
required property string settingKey
|
||||
required property string label
|
||||
property string description: ""
|
||||
required property var options
|
||||
property string defaultValue: ""
|
||||
property string value: defaultValue
|
||||
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
readonly property var optionLabels: {
|
||||
const labels = []
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
labels.push(options[i].label || options[i])
|
||||
}
|
||||
return labels
|
||||
}
|
||||
|
||||
readonly property var valueToLabel: {
|
||||
const map = {}
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
const opt = options[i]
|
||||
if (typeof opt === 'object') {
|
||||
map[opt.value] = opt.label
|
||||
} else {
|
||||
map[opt] = opt
|
||||
}
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
readonly property var labelToValue: {
|
||||
const map = {}
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
const opt = options[i]
|
||||
if (typeof opt === 'object') {
|
||||
map[opt.label] = opt.value
|
||||
} else {
|
||||
map[opt] = opt
|
||||
}
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
const settings = findSettings()
|
||||
if (settings) {
|
||||
value = settings.loadValue(settingKey, defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
onValueChanged: {
|
||||
const settings = findSettings()
|
||||
if (settings) {
|
||||
settings.saveValue(settingKey, value)
|
||||
}
|
||||
}
|
||||
|
||||
function findSettings() {
|
||||
let item = parent
|
||||
while (item) {
|
||||
if (item.saveValue !== undefined && item.loadValue !== undefined) {
|
||||
return item
|
||||
}
|
||||
item = item.parent
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Column {
|
||||
width: parent.width * 0.4
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StyledText {
|
||||
text: root.label
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: root.description
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
visible: root.description !== ""
|
||||
}
|
||||
}
|
||||
|
||||
DankDropdown {
|
||||
width: parent.width * 0.6 - Theme.spacingM
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
currentValue: root.valueToLabel[root.value] || root.value
|
||||
options: root.optionLabels
|
||||
onValueChanged: newValue => {
|
||||
root.value = root.labelToValue[newValue] || newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
65
Modules/Plugins/StringSetting.qml
Normal file
65
Modules/Plugins/StringSetting.qml
Normal file
@@ -0,0 +1,65 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
||||
required property string settingKey
|
||||
required property string label
|
||||
property string description: ""
|
||||
property string placeholder: ""
|
||||
property string defaultValue: ""
|
||||
property string value: defaultValue
|
||||
|
||||
width: parent.width
|
||||
spacing: Theme.spacingS
|
||||
|
||||
Component.onCompleted: {
|
||||
const settings = findSettings()
|
||||
if (settings) {
|
||||
value = settings.loadValue(settingKey, defaultValue)
|
||||
textField.text = value
|
||||
}
|
||||
}
|
||||
|
||||
function findSettings() {
|
||||
let item = parent
|
||||
while (item) {
|
||||
if (item.saveValue !== undefined && item.loadValue !== undefined) {
|
||||
return item
|
||||
}
|
||||
item = item.parent
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: root.label
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: root.description
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
visible: root.description !== ""
|
||||
}
|
||||
|
||||
DankTextField {
|
||||
id: textField
|
||||
width: parent.width
|
||||
placeholderText: root.placeholder
|
||||
onEditingFinished: {
|
||||
root.value = text
|
||||
const settings = findSettings()
|
||||
if (settings) {
|
||||
settings.saveValue(settingKey, text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
72
Modules/Plugins/ToggleSetting.qml
Normal file
72
Modules/Plugins/ToggleSetting.qml
Normal file
@@ -0,0 +1,72 @@
|
||||
import QtQuick
|
||||
import qs.Common
|
||||
import qs.Widgets
|
||||
|
||||
Row {
|
||||
id: root
|
||||
|
||||
required property string settingKey
|
||||
required property string label
|
||||
property string description: ""
|
||||
property bool defaultValue: false
|
||||
property bool value: defaultValue
|
||||
|
||||
width: parent.width
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Component.onCompleted: {
|
||||
const settings = findSettings()
|
||||
if (settings) {
|
||||
value = settings.loadValue(settingKey, defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
onValueChanged: {
|
||||
const settings = findSettings()
|
||||
if (settings) {
|
||||
settings.saveValue(settingKey, value)
|
||||
}
|
||||
}
|
||||
|
||||
function findSettings() {
|
||||
let item = parent
|
||||
while (item) {
|
||||
if (item.saveValue !== undefined && item.loadValue !== undefined) {
|
||||
return item
|
||||
}
|
||||
item = item.parent
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width - toggle.width - Theme.spacingM
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StyledText {
|
||||
text: root.label
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.weight: Font.Medium
|
||||
color: Theme.surfaceText
|
||||
}
|
||||
|
||||
StyledText {
|
||||
text: root.description
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
width: parent.width
|
||||
wrapMode: Text.WordWrap
|
||||
visible: root.description !== ""
|
||||
}
|
||||
}
|
||||
|
||||
DankToggle {
|
||||
id: toggle
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
checked: root.value
|
||||
onToggled: isChecked => {
|
||||
root.value = isChecked
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,21 +160,17 @@ Item {
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
Item {
|
||||
Column {
|
||||
width: parent.width
|
||||
height: Math.max(150, pluginListView.contentHeight)
|
||||
spacing: Theme.spacingM
|
||||
|
||||
ListView {
|
||||
id: pluginListView
|
||||
|
||||
anchors.fill: parent
|
||||
Repeater {
|
||||
id: pluginRepeater
|
||||
model: PluginService.getAvailablePlugins()
|
||||
spacing: Theme.spacingM
|
||||
clip: true
|
||||
|
||||
delegate: StyledRect {
|
||||
StyledRect {
|
||||
id: pluginDelegate
|
||||
width: pluginListView.width
|
||||
width: parent.width
|
||||
height: pluginItemColumn.implicitHeight + Theme.spacingM * 2 + settingsContainer.height
|
||||
radius: Theme.cornerRadius
|
||||
|
||||
@@ -194,23 +190,9 @@ Item {
|
||||
console.log("Plugin", pluginId, "isExpanded changed to:", isExpanded)
|
||||
}
|
||||
|
||||
color: pluginMouseArea.containsMouse ? Theme.surfacePressed : (isExpanded ? Theme.surfaceContainerHighest : Theme.surfaceContainer)
|
||||
color: pluginMouseArea.containsMouse ? Theme.surfacePressed : (isExpanded ? Theme.surfaceContainerHighest : Theme.surfaceContainerHigh)
|
||||
border.width: 0
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: pluginMouseArea
|
||||
anchors.fill: parent
|
||||
@@ -238,7 +220,7 @@ Item {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.margins: Theme.spacingM
|
||||
spacing: Theme.spacingS
|
||||
spacing: Theme.spacingM
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
@@ -252,9 +234,9 @@ Item {
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width - Theme.iconSize - Theme.spacingM - pluginToggle.width - Theme.spacingM
|
||||
spacing: Theme.spacingXS
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 2
|
||||
width: parent.width - 250
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacingXS
|
||||
@@ -262,7 +244,7 @@ Item {
|
||||
|
||||
StyledText {
|
||||
text: pluginDelegate.pluginName
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
color: Theme.surfaceText
|
||||
font.weight: Font.Medium
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -274,13 +256,6 @@ Item {
|
||||
color: pluginDelegate.hasSettings ? Theme.primary : "transparent"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: pluginDelegate.hasSettings
|
||||
|
||||
Behavior on rotation {
|
||||
NumberAnimation {
|
||||
duration: Theme.shortDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,16 +264,11 @@ Item {
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.surfaceVariantText
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 10
|
||||
height: 1
|
||||
}
|
||||
|
||||
DankToggle {
|
||||
id: pluginToggle
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
checked: PluginService.isPluginLoaded(pluginDelegate.pluginId)
|
||||
onToggled: (isChecked) => {
|
||||
@@ -367,20 +337,9 @@ Item {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: pluginDelegate.isExpanded && pluginDelegate.hasSettings ? Math.min(500, settingsLoader.item ? settingsLoader.item.implicitHeight + Theme.spacingL * 2 : 200) : 0
|
||||
height: pluginDelegate.isExpanded && pluginDelegate.hasSettings ? (settingsLoader.item ? settingsLoader.item.implicitHeight + Theme.spacingL * 2 : 0) : 0
|
||||
clip: true
|
||||
|
||||
onHeightChanged: {
|
||||
console.log("Settings container height changed:", height, "for plugin:", pluginDelegate.pluginId)
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation {
|
||||
duration: Theme.mediumDuration
|
||||
easing.type: Theme.standardEasing
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: Theme.surfaceContainerHighest
|
||||
@@ -389,78 +348,61 @@ Item {
|
||||
border.width: 0
|
||||
}
|
||||
|
||||
DankFlickable {
|
||||
Loader {
|
||||
id: settingsLoader
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.spacingL
|
||||
contentHeight: settingsLoader.height
|
||||
contentWidth: width
|
||||
clip: true
|
||||
active: pluginDelegate.isExpanded && pluginDelegate.hasSettings && PluginService.isPluginLoaded(pluginDelegate.pluginId)
|
||||
asynchronous: false
|
||||
|
||||
Loader {
|
||||
id: settingsLoader
|
||||
width: parent.width
|
||||
active: pluginDelegate.isExpanded && pluginDelegate.hasSettings && PluginService.isPluginLoaded(pluginDelegate.pluginId)
|
||||
asynchronous: false
|
||||
onActiveChanged: {
|
||||
console.log("Settings loader active changed to:", active, "for plugin:", pluginDelegate.pluginId,
|
||||
"isExpanded:", pluginDelegate.isExpanded, "hasSettings:", pluginDelegate.hasSettings,
|
||||
"isLoaded:", PluginService.isPluginLoaded(pluginDelegate.pluginId))
|
||||
}
|
||||
|
||||
onActiveChanged: {
|
||||
console.log("Settings loader active changed to:", active, "for plugin:", pluginDelegate.pluginId,
|
||||
"isExpanded:", pluginDelegate.isExpanded, "hasSettings:", pluginDelegate.hasSettings,
|
||||
"isLoaded:", PluginService.isPluginLoaded(pluginDelegate.pluginId))
|
||||
}
|
||||
|
||||
source: {
|
||||
if (active && pluginDelegate.pluginSettingsPath) {
|
||||
console.log("Loading plugin settings from:", pluginDelegate.pluginSettingsPath)
|
||||
var path = pluginDelegate.pluginSettingsPath
|
||||
if (!path.startsWith("file://")) {
|
||||
path = "file://" + path
|
||||
}
|
||||
return path
|
||||
source: {
|
||||
if (active && pluginDelegate.pluginSettingsPath) {
|
||||
console.log("Loading plugin settings from:", pluginDelegate.pluginSettingsPath)
|
||||
var path = pluginDelegate.pluginSettingsPath
|
||||
if (!path.startsWith("file://")) {
|
||||
path = "file://" + path
|
||||
}
|
||||
return ""
|
||||
return path
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
onStatusChanged: {
|
||||
console.log("Settings loader status changed:", status, "for plugin:", pluginDelegate.pluginId)
|
||||
if (status === Loader.Error) {
|
||||
console.error("Failed to load plugin settings:", pluginDelegate.pluginSettingsPath)
|
||||
} else if (status === Loader.Ready) {
|
||||
console.log("Settings successfully loaded for plugin:", pluginDelegate.pluginId)
|
||||
onStatusChanged: {
|
||||
console.log("Settings loader status changed:", status, "for plugin:", pluginDelegate.pluginId)
|
||||
if (status === Loader.Error) {
|
||||
console.error("Failed to load plugin settings:", pluginDelegate.pluginSettingsPath)
|
||||
} else if (status === Loader.Ready) {
|
||||
console.log("Settings successfully loaded for plugin:", pluginDelegate.pluginId)
|
||||
}
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
if (item) {
|
||||
console.log("Plugin settings loaded for:", pluginDelegate.pluginId)
|
||||
|
||||
if (typeof PluginService !== "undefined") {
|
||||
console.log("Making PluginService available to plugin settings")
|
||||
console.log("PluginService functions available:",
|
||||
"savePluginData" in PluginService,
|
||||
"loadPluginData" in PluginService)
|
||||
item.pluginService = PluginService
|
||||
console.log("PluginService assignment completed, item.pluginService:", item.pluginService !== null)
|
||||
} else {
|
||||
console.error("PluginService not available in PluginsTab context")
|
||||
}
|
||||
}
|
||||
|
||||
onLoaded: {
|
||||
if (item) {
|
||||
console.log("Plugin settings loaded for:", pluginDelegate.pluginId)
|
||||
|
||||
// Make PluginService available to the loaded component
|
||||
if (typeof PluginService !== "undefined") {
|
||||
console.log("Making PluginService available to plugin settings")
|
||||
console.log("PluginService functions available:",
|
||||
"savePluginData" in PluginService,
|
||||
"loadPluginData" in PluginService)
|
||||
item.pluginService = PluginService
|
||||
console.log("PluginService assignment completed, item.pluginService:", item.pluginService !== null)
|
||||
} else {
|
||||
console.error("PluginService not available in PluginsTab context")
|
||||
}
|
||||
|
||||
// Connect to height changes for dynamic resizing
|
||||
if (item.implicitHeightChanged) {
|
||||
item.implicitHeightChanged.connect(function() {
|
||||
console.log("Plugin settings height changed:", item.implicitHeight)
|
||||
})
|
||||
}
|
||||
|
||||
// Force load timezones for WorldClock plugin
|
||||
if (item.loadTimezones) {
|
||||
console.log("Calling loadTimezones for WorldClock plugin")
|
||||
item.loadTimezones()
|
||||
}
|
||||
// Generic initialization for any plugin
|
||||
if (item.initializeSettings) {
|
||||
item.initializeSettings()
|
||||
}
|
||||
if (item.loadTimezones) {
|
||||
console.log("Calling loadTimezones for WorldClock plugin")
|
||||
item.loadTimezones()
|
||||
}
|
||||
if (item.initializeSettings) {
|
||||
item.initializeSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -482,12 +424,12 @@ Item {
|
||||
}
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
text: "No plugins found.\nPlace plugins in " + PluginService.pluginDirectory
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.surfaceVariantText
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
visible: pluginListView.model.length === 0
|
||||
visible: pluginRepeater.model.length === 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -498,10 +440,10 @@ Item {
|
||||
Connections {
|
||||
target: PluginService
|
||||
function onPluginLoaded() {
|
||||
pluginListView.model = PluginService.getAvailablePlugins()
|
||||
pluginRepeater.model = PluginService.getAvailablePlugins()
|
||||
}
|
||||
function onPluginUnloaded() {
|
||||
pluginListView.model = PluginService.getAvailablePlugins()
|
||||
pluginRepeater.model = PluginService.getAvailablePlugins()
|
||||
if (pluginsTab.expandedPluginId !== "" && !PluginService.isPluginLoaded(pluginsTab.expandedPluginId)) {
|
||||
pluginsTab.expandedPluginId = ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user