diff --git a/Modules/ControlCenter/BuiltinPlugins/CupsWidget.qml b/Modules/ControlCenter/BuiltinPlugins/CupsWidget.qml new file mode 100644 index 00000000..c64db32f --- /dev/null +++ b/Modules/ControlCenter/BuiltinPlugins/CupsWidget.qml @@ -0,0 +1,287 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import qs.Common +import qs.Services +import qs.Widgets +import qs.Modules.Plugins + +PluginComponent { + id: root + + Ref { + service: CupsService + } + + ccWidgetIcon: CupsService.cupsAvailable && CupsService.getPrintersNum() > 0 ? "print" : "print_disabled" + ccWidgetPrimaryText: I18n.tr("Printers") + ccWidgetSecondaryText: { + if (CupsService.cupsAvailable && CupsService.getPrintersNum() > 0) { + return I18n.tr("Printers: ") + CupsService.getPrintersNum() + " - " + I18n.tr("Jobs: ") + CupsService.getTotalJobsNum() + } else { + if (!CupsService.cupsAvailable) { + return I18n.tr("Print Server not available") + } else { + return I18n.tr("No printer found") + } + } + } + ccWidgetIsActive: CupsService.cupsAvailable && CupsService.getTotalJobsNum() > 0 + + onCcWidgetToggled: {} + + ccDetailContent: Component { + Rectangle { + id: detailRoot + implicitHeight: detailColumn.implicitHeight + Theme.spacingM * 2 + radius: Theme.cornerRadius + color: Theme.surfaceContainerHigh + + Column { + id: detailColumn + anchors.fill: parent + anchors.margins: Theme.spacingM + spacing: Theme.spacingS + visible: CupsService.cupsAvailable && CupsService.getPrintersNum() > 0 + height: visible ? 120 : 0 + + RowLayout { + spacing: Theme.spacingS + width: parent.width + + DankDropdown { + id: printerDropdown + text: "" + Layout.fillWidth: true + Layout.maximumWidth: parent.width - 180 + description: "" + currentValue: { + CupsService.getSelectedPrinter() + } + options: CupsService.getPrintersNames() + onValueChanged: value => { + CupsService.setSelectedPrinter(value) + } + } + + Column { + spacing: Theme.spacingS + + StyledText { + text: CupsService.getCurrentPrinterStatePrettyShort() + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + font.weight: Font.Medium + anchors.horizontalCenter: parent.horizontalCenter + } + + Row { + spacing: Theme.spacingM + + Rectangle { + height: 24 + width: 80 + radius: 14 + color: printerStatusToggle.containsMouse ? Theme.errorHover : Theme.surfaceLight + visible: true + opacity: 1.0 + + Row { + anchors.centerIn: parent + spacing: Theme.spacingXS + + DankIcon { + anchors.verticalCenter: parent.verticalCenter + name: CupsService.getCurrentPrinterState() === "stopped" ? "play_arrow" : "pause" + size: Theme.fontSizeSmall + 4 + color: Theme.surfaceText + } + + StyledText { + anchors.verticalCenter: parent.verticalCenter + text: CupsService.getCurrentPrinterState() === "stopped" ? I18n.tr("Resume") : I18n.tr("Pause") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + font.weight: Font.Medium + } + } + + MouseArea { + id: printerStatusToggle + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + enabled: true + onClicked: { + const selected = CupsService.getSelectedPrinter() + if (CupsService.getCurrentPrinterState() === "stopped") { + CupsService.resumePrinter(selected) + } else { + CupsService.pausePrinter(selected) + } + } + } + } + + Rectangle { + height: 24 + width: 80 + radius: 14 + color: clearJobsToggle.containsMouse ? Theme.errorHover : Theme.surfaceLight + visible: true + opacity: 1.0 + + Row { + anchors.centerIn: parent + spacing: Theme.spacingXS + + DankIcon { + anchors.verticalCenter: parent.verticalCenter + name: "delete_forever" + size: Theme.fontSizeSmall + 4 + color: Theme.surfaceText + } + + StyledText { + anchors.verticalCenter: parent.verticalCenter + text: I18n.tr("Jobs") + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceText + font.weight: Font.Medium + } + } + + MouseArea { + id: clearJobsToggle + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + enabled: true + onClicked: { + const selected = CupsService.getSelectedPrinter() + CupsService.purgeJobs(selected) + } + } + } + } + } + } + + Rectangle { + height: 1 + width: parent.width + color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) + } + + DankFlickable { + width: parent.width + height: 160 + contentHeight: listCol.height + clip: true + + Column { + id: listCol + width: parent.width + spacing: Theme.spacingXS + + Item { + width: parent.width + height: 120 + visible: CupsService.getCurrentPrinterJobs().length === 0 + + Column { + anchors.centerIn: parent + spacing: Theme.spacingS + + DankIcon { + name: "work" + size: 36 + color: Theme.surfaceVariantText + anchors.horizontalCenter: parent.horizontalCenter + } + + StyledText { + text: I18n.tr("The job queue of this printer is empty") + font.pixelSize: Theme.fontSizeMedium + color: Theme.surfaceVariantText + anchors.horizontalCenter: parent.horizontalCenter + } + } + } + + Repeater { + model: CupsService.getCurrentPrinterJobs() + + delegate: Rectangle { + required property var modelData + + width: parent ? parent.width : 300 + height: 50 + radius: Theme.cornerRadius + color: Theme.surfaceContainerHighest + border.width: 1 + border.color: Theme.outlineLight + opacity: 1.0 + + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.margins: Theme.spacingM + spacing: Theme.spacingM + + DankIcon { + name: "docs" + size: Theme.iconSize + 2 + color: Theme.surfaceText + Layout.alignment: Qt.AlignVCenter + } + + Column { + spacing: 2 + Layout.alignment: Qt.AlignVCenter + Layout.fillWidth: true + + StyledText { + text: "[" + modelData.id + "] " + modelData.state + " (" + (modelData.size / 1024) + "kb)" + font.pixelSize: Theme.fontSizeMedium + color: Theme.surfaceText + elide: Text.ElideRight + wrapMode: Text.NoWrap + width: parent.width + } + + StyledText { + text: { + var date = new Date(modelData.timeCreated) + return date.toLocaleString(Qt.locale(), Locale.ShortFormat) + } + font.pixelSize: Theme.fontSizeSmall + color: Theme.surfaceTextMedium + } + } + + Item { + Layout.fillWidth: true + } + } + + DankActionButton { + id: cancelJobButton + anchors.right: parent.right + anchors.rightMargin: Theme.spacingM + anchors.verticalCenter: parent.verticalCenter + iconName: "delete" + buttonSize: 36 + onClicked: { + CupsService.cancelJob(modelData.id) + } + } + } + } + } + } + } + } + } +} diff --git a/Modules/ControlCenter/Components/DetailHost.qml b/Modules/ControlCenter/Components/DetailHost.qml index 92bc945e..61b114fa 100644 --- a/Modules/ControlCenter/Components/DetailHost.qml +++ b/Modules/ControlCenter/Components/DetailHost.qml @@ -104,6 +104,12 @@ Item { } builtinInstance = widgetModel.vpnBuiltinInstance } + if (builtinId === "builtin_cups") { + if (widgetModel?.cupsLoader) { + widgetModel.cupsLoader.active = true + } + builtinInstance = widgetModel.cupsBuiltinInstance + } if (!builtinInstance || !builtinInstance.ccDetailContent) { return diff --git a/Modules/ControlCenter/Components/DragDropGrid.qml b/Modules/ControlCenter/Components/DragDropGrid.qml index e8175531..9a75adeb 100644 --- a/Modules/ControlCenter/Components/DragDropGrid.qml +++ b/Modules/ControlCenter/Components/DragDropGrid.qml @@ -794,6 +794,12 @@ Column { } builtinInstance = Qt.binding(() => root.model?.vpnBuiltinInstance) } + if (id === "builtin_cups") { + if (root.model?.cupsLoader) { + root.model.cupsLoader.active = true + } + builtinInstance = Qt.binding(() => root.model?.cupsBuiltinInstance) + } } sourceComponent: { diff --git a/Modules/ControlCenter/Models/WidgetModel.qml b/Modules/ControlCenter/Models/WidgetModel.qml index 2b2a7601..51e8b62f 100644 --- a/Modules/ControlCenter/Models/WidgetModel.qml +++ b/Modules/ControlCenter/Models/WidgetModel.qml @@ -8,6 +8,7 @@ QtObject { id: root property var vpnBuiltinInstance: null + property var cupsBuiltinInstance: null property var vpnLoader: Loader { active: false @@ -32,6 +33,29 @@ QtObject { } } + property var cupsLoader: Loader { + active: false + sourceComponent: Component { + CupsWidget {} + } + + onItemChanged: { + root.cupsBuiltinInstance = item + } + + Connections { + target: SettingsData + function onControlCenterWidgetsChanged() { + const widgets = SettingsData.controlCenterWidgets || [] + const hasCupsWidget = widgets.some(w => w.id === "builtin_cups") + if (!hasCupsWidget && cupsLoader.active) { + console.log("CupsWidget: No CUPS widget in control center, deactivating loader") + cupsLoader.active = false + } + } + } + } + readonly property var coreWidgetDefinitions: [{ "id": "nightMode", "text": "Night Mode", @@ -146,6 +170,15 @@ QtObject { "enabled": DMSNetworkService.available, "warning": !DMSNetworkService.available ? "VPN not available" : undefined, "isBuiltinPlugin": true + }, { + "id": "builtin_cups", + "text": "Printers", + "description": "Print Server Management", + "icon": "Print", + "type": "builtin_plugin", + "enabled": CupsService.available, + "warning": !CupsService.available ? "CUPS not available" : undefined, + "isBuiltinPlugin": true }] function getPluginWidgets() { diff --git a/Services/CupsService.qml b/Services/CupsService.qml new file mode 100644 index 00000000..2b5ef1b3 --- /dev/null +++ b/Services/CupsService.qml @@ -0,0 +1,326 @@ +pragma Singleton + +pragma ComponentBehavior: Bound + +import QtQuick +import Quickshell +import Quickshell.Io +import qs.Common + +Singleton { + id: root + + property int refCount: 0 + + property var printerNames: [] + property var printers: [] + property string selectedPrinter: "" + + property bool cupsAvailable: false + property bool stateInitialized: false + + signal cupsStateUpdate + + readonly property string socketPath: Quickshell.env("DMS_SOCKET") + + Component.onCompleted: { + if (socketPath && socketPath.length > 0) { + checkDMSCapabilities() + } + } + + Connections { + target: DMSService + + function onConnectionStateChanged() { + if (DMSService.isConnected) { + checkDMSCapabilities() + } + } + } + + Connections { + target: DMSService + enabled: DMSService.isConnected + + function onCupsStateUpdate(data) { + console.log("CupsService: Subscription update received") + updateState(data) + } + + function onCapabilitiesChanged() { + checkDMSCapabilities() + } + } + + function checkDMSCapabilities() { + if (!DMSService.isConnected) { + return + } + + if (DMSService.capabilities.length === 0) { + return + } + + cupsAvailable = DMSService.capabilities.includes("cups") + + if (cupsAvailable && !stateInitialized) { + stateInitialized = true + getState() + } + } + + function getState() { + if (!cupsAvailable) return + + DMSService.sendRequest("cups.getState", null, response => { + if (response.result) { + updateState(response.result) + } + }) + } + + function updateState(state) { + printerNames = Object.keys(state.printers) + if (printerNames.length > 0) { + if (selectedPrinter.length > 0) { + if (!printerNames.includes(selectedPrinter)) { + selectedPrinter = printerNames[0] + } + } else { + selectedPrinter = printerNames[0] + } + } + printers = state.printers + } + + function getSelectedPrinter() { + return selectedPrinter + } + + function setSelectedPrinter(printerName) { + if (printerNames.length > 0) { + if (printerNames.includes(printerName)) { + selectedPrinter = printerName + } else { + selectedPrinter = printerNames[0] + } + } + } + + function getPrintersNum() { + if (!cupsAvailable) return 0 + + return printerNames.length + } + + function getPrintersNames() { + if (!cupsAvailable) return [] + + return printerNames + } + + function getTotalJobsNum() { + if (!cupsAvailable) return 0 + + var result = 0 + for (var i = 0; i < printerNames.length; i++) { + var printerName = printerNames[i] + if (printers[printerName] && printers[printerName].jobs) { + result += printers[printerName].jobs.length + } + } + return result + } + + function getCurrentPrinterState() { + if (!cupsAvailable || !selectedPrinter) return "" + + var printer = printers[selectedPrinter] + return printer.state + } + + function getCurrentPrinterStatePrettyShort() { + if (!cupsAvailable || !selectedPrinter) return "" + + var printer = printers[selectedPrinter] + return getPrinterStateTranslation(printer.state) + + " (" + getPrinterStateReasonTranslation(printer.stateReason) + ")" + } + + function getCurrentPrinterStatePretty() { + if (!cupsAvailable || !selectedPrinter) return "" + + var printer = printers[selectedPrinter] + return getPrinterStateTranslation(printer.state) + + " (" + I18n.tr("Reason") + ": " + getPrinterStateReasonTranslation(printer.stateReason) + ")" + } + + function getCurrentPrinterJobs() { + if (!cupsAvailable || !selectedPrinter) return [] + + return getJobs(selectedPrinter) + } + + function getJobs(printerName) { + if (!cupsAvailable) return "" + + var printer = printers[printerName] + return printer.jobs + } + + function getJobsNum(printerName) { + if (!cupsAvailable) return 0 + + var printer = printers[printerName] + return printer.jobs.length + } + + function pausePrinter(printerName) { + if (!cupsAvailable) return + + const params = { + printerName: printerName + } + + DMSService.sendRequest("cups.pausePrinter", params, response => { + if (response.error) { + ToastService.showError(I18n.tr("Failed to pause printer") + " - " + response.error) + } + }) + } + + function resumePrinter(printerName) { + if (!cupsAvailable) return + + const params = { + printerName: printerName + } + + DMSService.sendRequest("cups.resumePrinter", params, response => { + if (response.error) { + ToastService.showError(I18n.tr("Failed to resume printer") + " - " + response.error) + } + }) + } + + function cancelJob(jobid) { + if (!cupsAvailable) return + + const params = { + jobid: jobid + } + + DMSService.sendRequest("cups.cancelJob", params, response => { + if (response.error) { + ToastService.showError(I18n.tr("Failed to cancel selected job") + " - " + response.error) + } + }) + } + + function purgeJobs(printerName) { + if (!cupsAvailable) return + + const params = { + printerName: printerName + } + + DMSService.sendRequest("cups.purgeJobs", params, response => { + if (response.error) { + ToastService.showError(I18n.tr("Failed to cancel all jobs") + " - " + response.error) + } + }) + } + + readonly property var states: ({ + "idle": I18n.tr("Idle"), + "processing": I18n.tr("Processing"), + "stopped": I18n.tr("Stopped") + }) + + readonly property var reasonsGeneral: ({ + "none": I18n.tr("None"), + "other": I18n.tr("Other") + }) + + readonly property var reasonsSupplies: ({ + "toner-low": I18n.tr("Toner Low"), + "toner-empty": I18n.tr("Toner Empty"), + "marker-supply-low": I18n.tr("Marker Supply Low"), + "marker-supply-empty": I18n.tr("Marker Supply Empty"), + "marker-waste-almost-full": I18n.tr("Marker Waste Almost Full"), + "marker-waste-full": I18n.tr("Marker Waste Full") + }) + + readonly property var reasonsMedia: ({ + "media-low": I18n.tr("Media Low"), + "media-empty": I18n.tr("Media Empty"), + "media-needed": I18n.tr("Media Needed"), + "media-jam": I18n.tr("Media Jam") + }) + + readonly property var reasonsParts: ({ + "cover-open": I18n.tr("Cover Open"), + "door-open": I18n.tr("Door Open"), + "interlock-open": I18n.tr("Interlock Open"), + "output-tray-missing": I18n.tr("Output Tray Missing"), + "output-area-almost-full": I18n.tr("Output Area Almost Full"), + "output-area-full": I18n.tr("Output Area Full") + }) + + readonly property var reasonsErrors: ({ + "paused": I18n.tr("Paused"), + "shutdown": I18n.tr("Shutdown"), + "connecting-to-device": I18n.tr("Connecting to Device"), + "timed-out": I18n.tr("Timed Out"), + "stopping": I18n.tr("Stopping"), + "stopped-partly": I18n.tr("Stopped Partly") + }) + + readonly property var reasonsService: ({ + "spool-area-full": I18n.tr("Spool Area Full"), + "cups-missing-filter-warning": I18n.tr("CUPS Missing Filter Warning"), + "cups-insecure-filter-warning": I18n.tr("CUPS Insecure Filter Warning") + }) + + readonly property var reasonsConnectivity: ({ + "offline-report": I18n.tr("Offline Report"), + "moving-to-paused": I18n.tr("Moving to Paused") + }) + + readonly property var severitySuffixes: ({ + "-error": I18n.tr("Error"), + "-warning": I18n.tr("Warning"), + "-report": I18n.tr("Report") + }) + + function getPrinterStateTranslation(state) { + return states[state] || state + } + + function getPrinterStateReasonTranslation(reason) { + let allReasons = Object.assign({}, + reasonsGeneral, + reasonsSupplies, + reasonsMedia, + reasonsParts, + reasonsErrors, + reasonsService, + reasonsConnectivity + ) + + let basReason = reason + let suffix = "" + + for (let s in severitySuffixes) { + if (reason.endsWith(s)) { + basReason = reason.slice(0, -s.length) + suffix = severitySuffixes[s] + break + } + } + + let translation = allReasons[basReason] || basReason + return suffix ? translation + " (" + suffix + ")" : translation + } +} diff --git a/translations/en.json b/translations/en.json index 6cb360d5..8976dd82 100644 --- a/translations/en.json +++ b/translations/en.json @@ -587,6 +587,18 @@ "reference": "Modules/Settings/DankBarTab.qml:74", "comment": "" }, + { + "term": "CUPS Insecure Filter Warning", + "context": "CUPS Insecure Filter Warning", + "reference": "Services/CupsService.qml:283", + "comment": "" + }, + { + "term": "CUPS Missing Filter Warning", + "context": "CUPS Missing Filter Warning", + "reference": "Services/CupsService.qml:282", + "comment": "" + }, { "term": "Cancel", "context": "Cancel", @@ -827,6 +839,12 @@ "reference": "Modules/Settings/DisplaysTab.qml:525", "comment": "" }, + { + "term": "Connecting to Device", + "context": "Connecting to Device", + "reference": "Services/CupsService.qml:274", + "comment": "" + }, { "term": "Contrast", "context": "Contrast", @@ -899,6 +917,12 @@ "reference": "Modules/Settings/ThemeColorsTab.qml:910", "comment": "" }, + { + "term": "Cover Open", + "context": "Cover Open", + "reference": "Services/CupsService.qml:263", + "comment": "" + }, { "term": "Create Dir", "context": "Create Dir", @@ -1229,6 +1253,12 @@ "reference": "Modules/Settings/AboutTab.qml:598", "comment": "" }, + { + "term": "Door Open", + "context": "Door Open", + "reference": "Services/CupsService.qml:264", + "comment": "" + }, { "term": "Drag widgets to reorder within sections. Use the eye icon to hide/show widgets (maintains spacing), or X to remove them completely.", "context": "Drag widgets to reorder within sections. Use the eye icon to hide/show widgets (maintains spacing), or X to remove them completely.", @@ -1379,6 +1409,12 @@ "reference": "Modals/WifiPasswordModal.qml:200, Modals/WifiPasswordModal.qml:202", "comment": "" }, + { + "term": "Error", + "context": "Error", + "reference": "Services/CupsService.qml:292", + "comment": "" + }, { "term": "Exclusive Zone Offset", "context": "Exclusive Zone Offset", @@ -1403,6 +1439,18 @@ "reference": "Services/DMSNetworkService.qml:370", "comment": "" }, + { + "term": "Failed to cancel all jobs", + "context": "Failed to cancel all jobs", + "reference": "Services/CupsService.qml:230", + "comment": "" + }, + { + "term": "Failed to cancel selected job", + "context": "Failed to cancel selected job", + "reference": "Services/CupsService.qml:216", + "comment": "" + }, { "term": "Failed to connect VPN", "context": "Failed to connect VPN", @@ -1439,12 +1487,24 @@ "reference": "Services/DMSNetworkService.qml:548", "comment": "" }, + { + "term": "Failed to pause printer", + "context": "Failed to pause printer", + "reference": "Services/CupsService.qml:188", + "comment": "" + }, { "term": "Failed to remove device", "context": "Failed to remove device", "reference": "Modules/ControlCenter/Details/BluetoothDetail.qml:548", "comment": "" }, + { + "term": "Failed to resume printer", + "context": "Failed to resume printer", + "reference": "Services/CupsService.qml:202", + "comment": "" + }, { "term": "Failed to set profile image", "context": "Failed to set profile image", @@ -1721,6 +1781,12 @@ "reference": "Modules/Settings/ThemeColorsTab.qml:1331", "comment": "" }, + { + "term": "Idle", + "context": "Idle", + "reference": "Services/CupsService.qml:236", + "comment": "" + }, { "term": "Idle Inhibitor", "context": "Idle Inhibitor", @@ -1781,6 +1847,12 @@ "reference": "Modules/Settings/PluginBrowser.qml:230", "comment": "" }, + { + "term": "Interlock Open", + "context": "Interlock Open", + "reference": "Services/CupsService.qml:265", + "comment": "" + }, { "term": "Internet", "context": "Internet", @@ -1799,6 +1871,18 @@ "reference": "Modules/Settings/LauncherTab.qml:384", "comment": "" }, + { + "term": "Jobs", + "context": "Jobs", + "reference": "Modules/ControlCenter/BuiltinPlugins/CupsWidget.qml:147", + "comment": "" + }, + { + "term": "Jobs: ", + "context": "Jobs: ", + "reference": "Modules/ControlCenter/BuiltinPlugins/CupsWidget.qml:20", + "comment": "" + }, { "term": "Keyboard Layout Name", "context": "Keyboard Layout Name", @@ -1985,6 +2069,30 @@ "reference": "Modules/Settings/DankBarTab.qml:875", "comment": "" }, + { + "term": "Marker Supply Empty", + "context": "Marker Supply Empty", + "reference": "Services/CupsService.qml:250", + "comment": "" + }, + { + "term": "Marker Supply Low", + "context": "Marker Supply Low", + "reference": "Services/CupsService.qml:249", + "comment": "" + }, + { + "term": "Marker Waste Almost Full", + "context": "Marker Waste Almost Full", + "reference": "Services/CupsService.qml:251", + "comment": "" + }, + { + "term": "Marker Waste Full", + "context": "Marker Waste Full", + "reference": "Services/CupsService.qml:252", + "comment": "" + }, { "term": "Material Colors", "context": "Material Colors", @@ -2027,6 +2135,30 @@ "reference": "Modules/Settings/DankBarTab.qml:61", "comment": "" }, + { + "term": "Media Empty", + "context": "Media Empty", + "reference": "Services/CupsService.qml:257", + "comment": "" + }, + { + "term": "Media Jam", + "context": "Media Jam", + "reference": "Services/CupsService.qml:259", + "comment": "" + }, + { + "term": "Media Low", + "context": "Media Low", + "reference": "Services/CupsService.qml:256", + "comment": "" + }, + { + "term": "Media Needed", + "context": "Media Needed", + "reference": "Services/CupsService.qml:258", + "comment": "" + }, { "term": "Media Player Settings", "context": "Media Player Settings", @@ -2099,6 +2231,12 @@ "reference": "Modules/ProcessList/SystemTab.qml:445", "comment": "" }, + { + "term": "Moving to Paused", + "context": "Moving to Paused", + "reference": "Services/CupsService.qml:288", + "comment": "" + }, { "term": "Muted palette with subdued, calming tones.", "context": "Muted palette with subdued, calming tones.", @@ -2267,6 +2405,18 @@ "reference": "Modules/Settings/PluginsTab.qml:245", "comment": "" }, + { + "term": "No printer found", + "context": "No printer found", + "reference": "Modules/ControlCenter/BuiltinPlugins/CupsWidget.qml:25", + "comment": "" + }, + { + "term": "None", + "context": "None", + "reference": "Services/CupsService.qml:242", + "comment": "" + }, { "term": "Normal Priority", "context": "Normal Priority", @@ -2357,6 +2507,12 @@ "reference": "Services/AppSearchService.qml:171, Services/AppSearchService.qml:172, Services/AppSearchService.qml:173, Services/AppSearchService.qml:174", "comment": "" }, + { + "term": "Offline Report", + "context": "Offline Report", + "reference": "Services/CupsService.qml:287", + "comment": "" + }, { "term": "On-Screen Displays", "context": "On-Screen Displays", @@ -2393,6 +2549,30 @@ "reference": "Modules/Notepad/NotepadSettings.qml:201", "comment": "" }, + { + "term": "Other", + "context": "Other", + "reference": "Services/CupsService.qml:243", + "comment": "" + }, + { + "term": "Output Area Almost Full", + "context": "Output Area Almost Full", + "reference": "Services/CupsService.qml:267", + "comment": "" + }, + { + "term": "Output Area Full", + "context": "Output Area Full", + "reference": "Services/CupsService.qml:268", + "comment": "" + }, + { + "term": "Output Tray Missing", + "context": "Output Tray Missing", + "reference": "Services/CupsService.qml:266", + "comment": "" + }, { "term": "Overview", "context": "Overview", @@ -2441,6 +2621,18 @@ "reference": "Modals/WifiPasswordModal.qml:298", "comment": "" }, + { + "term": "Pause", + "context": "Pause", + "reference": "Modules/ControlCenter/BuiltinPlugins/CupsWidget.qml:102", + "comment": "" + }, + { + "term": "Paused", + "context": "Paused", + "reference": "Services/CupsService.qml:272", + "comment": "" + }, { "term": "Per-Mode Wallpapers", "context": "Per-Mode Wallpapers", @@ -2621,6 +2813,24 @@ "reference": "Modules/Settings/LauncherTab.qml:202", "comment": "" }, + { + "term": "Print Server not available", + "context": "Print Server not available", + "reference": "Modules/ControlCenter/BuiltinPlugins/CupsWidget.qml:23", + "comment": "" + }, + { + "term": "Printers", + "context": "Printers", + "reference": "Modules/ControlCenter/BuiltinPlugins/CupsWidget.qml:17", + "comment": "" + }, + { + "term": "Printers: ", + "context": "Printers: ", + "reference": "Modules/ControlCenter/BuiltinPlugins/CupsWidget.qml:20", + "comment": "" + }, { "term": "Privacy Indicator", "context": "Privacy Indicator", @@ -2633,6 +2843,12 @@ "reference": "Modules/ProcessList/ProcessListView.qml:41", "comment": "" }, + { + "term": "Processing", + "context": "Processing", + "reference": "Services/CupsService.qml:237", + "comment": "" + }, { "term": "Profile Image Error", "context": "Profile Image Error", @@ -2675,6 +2891,12 @@ "reference": "Modules/DankDash/WeatherTab.qml:448, Modules/Settings/TimeWeatherTab.qml:1275", "comment": "" }, + { + "term": "Reason", + "context": "Reason", + "reference": "Services/CupsService.qml:156", + "comment": "" + }, { "term": "Reboot", "context": "Reboot", @@ -2711,6 +2933,12 @@ "reference": "Modules/Plugins/ListSetting.qml:114, Modules/Plugins/ListSettingWithInput.qml:230", "comment": "" }, + { + "term": "Report", + "context": "Report", + "reference": "Services/CupsService.qml:294", + "comment": "" + }, { "term": "Request confirmation on power off, restart, suspend, hibernate and logout actions", "context": "Request confirmation on power off, restart, suspend, hibernate and logout actions", @@ -2729,6 +2957,12 @@ "reference": "Modules/Settings/AboutTab.qml:421", "comment": "" }, + { + "term": "Resume", + "context": "Resume", + "reference": "Modules/ControlCenter/BuiltinPlugins/CupsWidget.qml:102", + "comment": "" + }, { "term": "Right", "context": "Right", @@ -3083,6 +3317,12 @@ "reference": "Modules/Settings/DankBarTab.qml:115", "comment": "" }, + { + "term": "Shutdown", + "context": "Shutdown", + "reference": "Services/CupsService.qml:273", + "comment": "" + }, { "term": "Size", "context": "Size", @@ -3119,6 +3359,12 @@ "reference": "Modules/Settings/DockTab.qml:492, Modules/Settings/DankBarTab.qml:988", "comment": "" }, + { + "term": "Spool Area Full", + "context": "Spool Area Full", + "reference": "Services/CupsService.qml:281", + "comment": "" + }, { "term": "Square Corners", "context": "Square Corners", @@ -3143,6 +3389,24 @@ "reference": "Widgets/DankIconPicker.qml:49", "comment": "" }, + { + "term": "Stopped", + "context": "Stopped", + "reference": "Services/CupsService.qml:238", + "comment": "" + }, + { + "term": "Stopped Partly", + "context": "Stopped Partly", + "reference": "Services/CupsService.qml:277", + "comment": "" + }, + { + "term": "Stopping", + "context": "Stopping", + "reference": "Services/CupsService.qml:276", + "comment": "" + }, { "term": "Storage & Disks", "context": "Storage & Disks", @@ -3317,6 +3581,12 @@ "reference": "Modules/Settings/ThemeColorsTab.qml:1292", "comment": "" }, + { + "term": "The job queue of this printer is empty", + "context": "The job queue of this printer is empty", + "reference": "Modules/ControlCenter/BuiltinPlugins/CupsWidget.qml:204", + "comment": "" + }, { "term": "Theme & Colors", "context": "Theme & Colors", @@ -3359,6 +3629,12 @@ "reference": "Modals/Settings/SettingsSidebar.qml:17", "comment": "" }, + { + "term": "Timed Out", + "context": "Timed Out", + "reference": "Services/CupsService.qml:275", + "comment": "" + }, { "term": "To Full", "context": "To Full", @@ -3395,6 +3671,18 @@ "reference": "Services/WeatherService.qml:170", "comment": "" }, + { + "term": "Toner Empty", + "context": "Toner Empty", + "reference": "Services/CupsService.qml:248", + "comment": "" + }, + { + "term": "Toner Low", + "context": "Toner Low", + "reference": "Services/CupsService.qml:247", + "comment": "" + }, { "term": "Top", "context": "Top", @@ -3647,6 +3935,12 @@ "reference": "Modules/DankDash/DankDashPopout.qml:237", "comment": "" }, + { + "term": "Warning", + "context": "Warning", + "reference": "Services/CupsService.qml:293", + "comment": "" + }, { "term": "Wave Progress Bars", "context": "Wave Progress Bars", diff --git a/translations/template.json b/translations/template.json index 15c316ee..791c4769 100644 --- a/translations/template.json +++ b/translations/template.json @@ -685,6 +685,20 @@ "reference": "", "comment": "" }, + { + "term": "CUPS Insecure Filter Warning", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "CUPS Missing Filter Warning", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Cancel", "translation": "", @@ -965,6 +979,13 @@ "reference": "", "comment": "" }, + { + "term": "Connecting to Device", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Contrast", "translation": "", @@ -1049,6 +1070,13 @@ "reference": "", "comment": "" }, + { + "term": "Cover Open", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Create Dir", "translation": "", @@ -1434,6 +1462,13 @@ "reference": "", "comment": "" }, + { + "term": "Door Open", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Drag widgets to reorder within sections. Use the eye icon to hide/show widgets (maintains spacing), or X to remove them completely.", "translation": "", @@ -1609,6 +1644,13 @@ "reference": "", "comment": "" }, + { + "term": "Error", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Exclusive Zone Offset", "translation": "", @@ -1637,6 +1679,20 @@ "reference": "", "comment": "" }, + { + "term": "Failed to cancel all jobs", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Failed to cancel selected job", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Failed to connect VPN", "translation": "", @@ -1679,6 +1735,13 @@ "reference": "", "comment": "" }, + { + "term": "Failed to pause printer", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Failed to remove device", "translation": "", @@ -1686,6 +1749,13 @@ "reference": "", "comment": "" }, + { + "term": "Failed to resume printer", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Failed to set profile image", "translation": "", @@ -2008,6 +2078,13 @@ "reference": "", "comment": "" }, + { + "term": "Idle", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Idle Inhibitor", "translation": "", @@ -2078,6 +2155,13 @@ "reference": "", "comment": "" }, + { + "term": "Interlock Open", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Internet", "translation": "", @@ -2099,6 +2183,20 @@ "reference": "", "comment": "" }, + { + "term": "Jobs", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Jobs: ", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Keyboard Layout Name", "translation": "", @@ -2316,6 +2414,34 @@ "reference": "", "comment": "" }, + { + "term": "Marker Supply Empty", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Marker Supply Low", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Marker Waste Almost Full", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Marker Waste Full", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Material Colors", "translation": "", @@ -2365,6 +2491,34 @@ "reference": "", "comment": "" }, + { + "term": "Media Empty", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Media Jam", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Media Low", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Media Needed", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Media Player Settings", "translation": "", @@ -2449,6 +2603,13 @@ "reference": "", "comment": "" }, + { + "term": "Moving to Paused", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Muted palette with subdued, calming tones.", "translation": "", @@ -2645,6 +2806,20 @@ "reference": "", "comment": "" }, + { + "term": "No printer found", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "None", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Normal Priority", "translation": "", @@ -2750,6 +2925,13 @@ "reference": "", "comment": "" }, + { + "term": "Offline Report", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "On-Screen Displays", "translation": "", @@ -2792,6 +2974,34 @@ "reference": "", "comment": "" }, + { + "term": "Other", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Output Area Almost Full", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Output Area Full", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Output Tray Missing", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Overview", "translation": "", @@ -2848,6 +3058,20 @@ "reference": "", "comment": "" }, + { + "term": "Pause", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Paused", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Per-Mode Wallpapers", "translation": "", @@ -3058,6 +3282,27 @@ "reference": "", "comment": "" }, + { + "term": "Print Server not available", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Printers", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Printers: ", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Privacy Indicator", "translation": "", @@ -3072,6 +3317,13 @@ "reference": "", "comment": "" }, + { + "term": "Processing", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Profile Image Error", "translation": "", @@ -3121,6 +3373,13 @@ "reference": "", "comment": "" }, + { + "term": "Reason", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Reboot", "translation": "", @@ -3163,6 +3422,13 @@ "reference": "", "comment": "" }, + { + "term": "Report", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Request confirmation on power off, restart, suspend, hibernate and logout actions", "translation": "", @@ -3184,6 +3450,13 @@ "reference": "", "comment": "" }, + { + "term": "Resume", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Right", "translation": "", @@ -3597,6 +3870,13 @@ "reference": "", "comment": "" }, + { + "term": "Shutdown", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Size", "translation": "", @@ -3639,6 +3919,13 @@ "reference": "", "comment": "" }, + { + "term": "Spool Area Full", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Square Corners", "translation": "", @@ -3667,6 +3954,27 @@ "reference": "", "comment": "" }, + { + "term": "Stopped", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Stopped Partly", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Stopping", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Storage & Disks", "translation": "", @@ -3870,6 +4178,13 @@ "reference": "", "comment": "" }, + { + "term": "The job queue of this printer is empty", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Theme & Colors", "translation": "", @@ -3919,6 +4234,13 @@ "reference": "", "comment": "" }, + { + "term": "Timed Out", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "To Full", "translation": "", @@ -3961,6 +4283,20 @@ "reference": "", "comment": "" }, + { + "term": "Toner Empty", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, + { + "term": "Toner Low", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Top", "translation": "", @@ -4255,6 +4591,13 @@ "reference": "", "comment": "" }, + { + "term": "Warning", + "translation": "", + "context": "", + "reference": "", + "comment": "" + }, { "term": "Wave Progress Bars", "translation": "",