mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
Compare commits
3 Commits
913bb2ff67
...
f163b97c17
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f163b97c17 | ||
|
|
436c99927e | ||
|
|
aa72eacae7 |
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -95,10 +96,14 @@ var doctorCmd = &cobra.Command{
|
|||||||
Run: runDoctor,
|
Run: runDoctor,
|
||||||
}
|
}
|
||||||
|
|
||||||
var doctorVerbose bool
|
var (
|
||||||
|
doctorVerbose bool
|
||||||
|
doctorJSON bool
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
doctorCmd.Flags().BoolVarP(&doctorVerbose, "verbose", "v", false, "Show detailed output including paths and versions")
|
doctorCmd.Flags().BoolVarP(&doctorVerbose, "verbose", "v", false, "Show detailed output including paths and versions")
|
||||||
|
doctorCmd.Flags().BoolVarP(&doctorJSON, "json", "j", false, "Output results in JSON format")
|
||||||
}
|
}
|
||||||
|
|
||||||
type category int
|
type category int
|
||||||
@@ -152,8 +157,38 @@ type checkResult struct {
|
|||||||
details string
|
details string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type checkResultJSON struct {
|
||||||
|
Category string `json:"category"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Details string `json:"details,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type doctorOutputJSON struct {
|
||||||
|
Summary struct {
|
||||||
|
Errors int `json:"errors"`
|
||||||
|
Warnings int `json:"warnings"`
|
||||||
|
OK int `json:"ok"`
|
||||||
|
Info int `json:"info"`
|
||||||
|
} `json:"summary"`
|
||||||
|
Results []checkResultJSON `json:"results"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r checkResult) toJSON() checkResultJSON {
|
||||||
|
return checkResultJSON{
|
||||||
|
Category: r.category.String(),
|
||||||
|
Name: r.name,
|
||||||
|
Status: string(r.status),
|
||||||
|
Message: r.message,
|
||||||
|
Details: r.details,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func runDoctor(cmd *cobra.Command, args []string) {
|
func runDoctor(cmd *cobra.Command, args []string) {
|
||||||
printDoctorHeader()
|
if !doctorJSON {
|
||||||
|
printDoctorHeader()
|
||||||
|
}
|
||||||
|
|
||||||
qsFeatures, qsMissingFeatures := checkQuickshellFeatures()
|
qsFeatures, qsMissingFeatures := checkQuickshellFeatures()
|
||||||
|
|
||||||
@@ -169,8 +204,12 @@ func runDoctor(cmd *cobra.Command, args []string) {
|
|||||||
checkEnvironmentVars(),
|
checkEnvironmentVars(),
|
||||||
)
|
)
|
||||||
|
|
||||||
printResults(results)
|
if doctorJSON {
|
||||||
printSummary(results, qsMissingFeatures)
|
printResultsJSON(results)
|
||||||
|
} else {
|
||||||
|
printResults(results)
|
||||||
|
printSummary(results, qsMissingFeatures)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printDoctorHeader() {
|
func printDoctorHeader() {
|
||||||
@@ -733,6 +772,8 @@ func checkSystemdServices() []checkResult {
|
|||||||
}
|
}
|
||||||
if dmsState.enabled == "disabled" {
|
if dmsState.enabled == "disabled" {
|
||||||
status, message = statusWarn, "Disabled"
|
status, message = statusWarn, "Disabled"
|
||||||
|
} else if dmsState.active == "failed" || dmsState.active == "inactive" {
|
||||||
|
status = statusError
|
||||||
}
|
}
|
||||||
results = append(results, checkResult{catServices, "dms.service", status, message, ""})
|
results = append(results, checkResult{catServices, "dms.service", status, message, ""})
|
||||||
}
|
}
|
||||||
@@ -799,6 +840,31 @@ func printResults(results []checkResult) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printResultsJSON(results []checkResult) {
|
||||||
|
var ds DoctorStatus
|
||||||
|
for _, r := range results {
|
||||||
|
ds.Add(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
output := doctorOutputJSON{}
|
||||||
|
output.Summary.Errors = ds.ErrorCount()
|
||||||
|
output.Summary.Warnings = ds.WarningCount()
|
||||||
|
output.Summary.OK = ds.OKCount()
|
||||||
|
output.Summary.Info = len(ds.Info)
|
||||||
|
|
||||||
|
output.Results = make([]checkResultJSON, 0, len(results))
|
||||||
|
for _, r := range results {
|
||||||
|
output.Results = append(output.Results, r.toJSON())
|
||||||
|
}
|
||||||
|
|
||||||
|
encoder := json.NewEncoder(os.Stdout)
|
||||||
|
encoder.SetIndent("", " ")
|
||||||
|
if err := encoder.Encode(output); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error encoding JSON: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func printResultLine(r checkResult, styles tui.Styles) {
|
func printResultLine(r checkResult, styles tui.Styles) {
|
||||||
icon, style := r.status.IconStyle(styles)
|
icon, style := r.status.IconStyle(styles)
|
||||||
|
|
||||||
|
|||||||
@@ -127,11 +127,19 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _onWritableCheckComplete(writable) {
|
function _onWritableCheckComplete(writable) {
|
||||||
|
const wasReadOnly = _isReadOnly;
|
||||||
_isReadOnly = !writable;
|
_isReadOnly = !writable;
|
||||||
if (_isReadOnly) {
|
if (_isReadOnly) {
|
||||||
console.info("SessionData: session.json is read-only (NixOS home-manager mode)");
|
_hasUnsavedChanges = _checkForUnsavedChanges();
|
||||||
} else if (_pendingMigration) {
|
if (!wasReadOnly)
|
||||||
settingsFile.setText(JSON.stringify(_pendingMigration, null, 2));
|
console.info("SessionData: session.json is now read-only");
|
||||||
|
} else {
|
||||||
|
_loadedSessionSnapshot = getCurrentSessionJson();
|
||||||
|
_hasUnsavedChanges = false;
|
||||||
|
if (wasReadOnly)
|
||||||
|
console.info("SessionData: session.json is now writable");
|
||||||
|
if (_pendingMigration)
|
||||||
|
settingsFile.setText(JSON.stringify(_pendingMigration, null, 2));
|
||||||
}
|
}
|
||||||
_pendingMigration = null;
|
_pendingMigration = null;
|
||||||
}
|
}
|
||||||
@@ -215,11 +223,9 @@ Singleton {
|
|||||||
function saveSettings() {
|
function saveSettings() {
|
||||||
if (isGreeterMode || _parseError || !_hasLoaded)
|
if (isGreeterMode || _parseError || !_hasLoaded)
|
||||||
return;
|
return;
|
||||||
if (_isReadOnly) {
|
|
||||||
_hasUnsavedChanges = _checkForUnsavedChanges();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
settingsFile.setText(getCurrentSessionJson());
|
settingsFile.setText(getCurrentSessionJson());
|
||||||
|
if (_isReadOnly)
|
||||||
|
_checkSessionWritable();
|
||||||
}
|
}
|
||||||
|
|
||||||
function migrateFromUndefinedToV1(settings) {
|
function migrateFromUndefinedToV1(settings) {
|
||||||
@@ -953,6 +959,10 @@ Singleton {
|
|||||||
parseSettings(settingsFile.text());
|
parseSettings(settingsFile.text());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onSaveFailed: error => {
|
||||||
|
root._isReadOnly = true;
|
||||||
|
root._hasUnsavedChanges = root._checkForUnsavedChanges();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FileView {
|
FileView {
|
||||||
|
|||||||
@@ -840,11 +840,19 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _onWritableCheckComplete(writable) {
|
function _onWritableCheckComplete(writable) {
|
||||||
|
const wasReadOnly = _isReadOnly;
|
||||||
_isReadOnly = !writable;
|
_isReadOnly = !writable;
|
||||||
if (_isReadOnly) {
|
if (_isReadOnly) {
|
||||||
console.info("SettingsData: settings.json is read-only (NixOS home-manager mode)");
|
_hasUnsavedChanges = _checkForUnsavedChanges();
|
||||||
} else if (_pendingMigration) {
|
if (!wasReadOnly)
|
||||||
settingsFile.setText(JSON.stringify(_pendingMigration, null, 2));
|
console.info("SettingsData: settings.json is now read-only");
|
||||||
|
} else {
|
||||||
|
_loadedSettingsSnapshot = JSON.stringify(Store.toJson(root));
|
||||||
|
_hasUnsavedChanges = false;
|
||||||
|
if (wasReadOnly)
|
||||||
|
console.info("SettingsData: settings.json is now writable");
|
||||||
|
if (_pendingMigration)
|
||||||
|
settingsFile.setText(JSON.stringify(_pendingMigration, null, 2));
|
||||||
}
|
}
|
||||||
_pendingMigration = null;
|
_pendingMigration = null;
|
||||||
}
|
}
|
||||||
@@ -889,11 +897,9 @@ Singleton {
|
|||||||
function saveSettings() {
|
function saveSettings() {
|
||||||
if (_loading || _parseError || !_hasLoaded)
|
if (_loading || _parseError || !_hasLoaded)
|
||||||
return;
|
return;
|
||||||
if (_isReadOnly) {
|
|
||||||
_hasUnsavedChanges = _checkForUnsavedChanges();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
settingsFile.setText(JSON.stringify(Store.toJson(root), null, 2));
|
settingsFile.setText(JSON.stringify(Store.toJson(root), null, 2));
|
||||||
|
if (_isReadOnly)
|
||||||
|
_checkSettingsWritable();
|
||||||
}
|
}
|
||||||
|
|
||||||
function savePluginSettings() {
|
function savePluginSettings() {
|
||||||
@@ -1889,6 +1895,10 @@ Singleton {
|
|||||||
applyStoredTheme();
|
applyStoredTheme();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onSaveFailed: error => {
|
||||||
|
root._isReadOnly = true;
|
||||||
|
root._hasUnsavedChanges = root._checkForUnsavedChanges();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FileView {
|
FileView {
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ Variants {
|
|||||||
}
|
}
|
||||||
pluginService: (liveInstanceData.widgetType !== "desktopClock" && liveInstanceData.widgetType !== "systemMonitor") ? PluginService : null
|
pluginService: (liveInstanceData.widgetType !== "desktopClock" && liveInstanceData.widgetType !== "systemMonitor") ? PluginService : null
|
||||||
screen: screenDelegate.screen
|
screen: screenDelegate.screen
|
||||||
visible: shouldBeVisible
|
widgetEnabled: shouldBeVisible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,6 +362,7 @@ PanelWindow {
|
|||||||
id: iconContainer
|
id: iconContainer
|
||||||
|
|
||||||
readonly property bool hasNotificationImage: notificationData && notificationData.image && notificationData.image !== ""
|
readonly property bool hasNotificationImage: notificationData && notificationData.image && notificationData.image !== ""
|
||||||
|
readonly property bool needsImagePersist: hasNotificationImage && notificationData.image.startsWith("image://qsimage/") && !notificationData.persistedImagePath
|
||||||
|
|
||||||
width: 63
|
width: 63
|
||||||
height: 63
|
height: 63
|
||||||
@@ -391,6 +392,22 @@ PanelWindow {
|
|||||||
const appName = notificationData?.appName || "?";
|
const appName = notificationData?.appName || "?";
|
||||||
return appName.charAt(0).toUpperCase();
|
return appName.charAt(0).toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onImageStatusChanged: {
|
||||||
|
if (imageStatus === Image.Ready && needsImagePersist) {
|
||||||
|
const cachePath = NotificationService.getImageCachePath(notificationData);
|
||||||
|
saveImageToFile(cachePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onImageSaved: filePath => {
|
||||||
|
if (!notificationData)
|
||||||
|
return;
|
||||||
|
notificationData.persistedImagePath = filePath;
|
||||||
|
const wrapperId = notificationData.notification?.id?.toString() || "";
|
||||||
|
if (wrapperId)
|
||||||
|
NotificationService.updateHistoryImage(wrapperId, filePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ Item {
|
|||||||
property var pluginService: null
|
property var pluginService: null
|
||||||
property string instanceId: ""
|
property string instanceId: ""
|
||||||
property var instanceData: null
|
property var instanceData: null
|
||||||
|
property bool widgetEnabled: true
|
||||||
|
|
||||||
readonly property bool isBuiltin: pluginId === "desktopClock" || pluginId === "systemMonitor"
|
readonly property bool isBuiltin: pluginId === "desktopClock" || pluginId === "systemMonitor"
|
||||||
readonly property var activeComponent: isBuiltin ? builtinComponent : PluginService.pluginDesktopComponents[pluginId] ?? null
|
readonly property var activeComponent: isBuiltin ? builtinComponent : PluginService.pluginDesktopComponents[pluginId] ?? null
|
||||||
@@ -202,7 +203,7 @@ Item {
|
|||||||
PanelWindow {
|
PanelWindow {
|
||||||
id: widgetWindow
|
id: widgetWindow
|
||||||
screen: root.screen
|
screen: root.screen
|
||||||
visible: root.visible && root.activeComponent !== null
|
visible: root.widgetEnabled && root.activeComponent !== null
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
WlrLayershell.namespace: "quickshell:desktop-widget:" + root.pluginId + (root.instanceId ? ":" + root.instanceId : "")
|
WlrLayershell.namespace: "quickshell:desktop-widget:" + root.pluginId + (root.instanceId ? ":" + root.instanceId : "")
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ Singleton {
|
|||||||
|
|
||||||
property var historyList: []
|
property var historyList: []
|
||||||
readonly property string historyFile: Paths.strip(Paths.cache) + "/notification_history.json"
|
readonly property string historyFile: Paths.strip(Paths.cache) + "/notification_history.json"
|
||||||
|
readonly property string imageCacheDir: Paths.strip(Paths.cache) + "/notification_images"
|
||||||
property bool historyLoaded: false
|
property bool historyLoaded: false
|
||||||
|
|
||||||
property list<NotifWrapper> notificationQueue: []
|
property list<NotifWrapper> notificationQueue: []
|
||||||
@@ -46,6 +47,7 @@ Singleton {
|
|||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
_recomputeGroups();
|
_recomputeGroups();
|
||||||
Quickshell.execDetached(["mkdir", "-p", Paths.strip(Paths.cache)]);
|
Quickshell.execDetached(["mkdir", "-p", Paths.strip(Paths.cache)]);
|
||||||
|
Quickshell.execDetached(["mkdir", "-p", imageCacheDir]);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileView {
|
FileView {
|
||||||
@@ -72,10 +74,46 @@ Singleton {
|
|||||||
onTriggered: root.performSaveHistory()
|
onTriggered: root.performSaveHistory()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getImageCachePath(wrapper) {
|
||||||
|
const ts = wrapper.time ? wrapper.time.getTime() : Date.now();
|
||||||
|
const id = wrapper.notification?.id?.toString() || "0";
|
||||||
|
return imageCacheDir + "/notif_" + ts + "_" + id + ".png";
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateHistoryImage(wrapperId, imagePath) {
|
||||||
|
const idx = historyList.findIndex(n => n.id === wrapperId);
|
||||||
|
if (idx < 0)
|
||||||
|
return;
|
||||||
|
const item = historyList[idx];
|
||||||
|
const updated = {
|
||||||
|
id: item.id,
|
||||||
|
summary: item.summary,
|
||||||
|
body: item.body,
|
||||||
|
htmlBody: item.htmlBody,
|
||||||
|
appName: item.appName,
|
||||||
|
appIcon: item.appIcon,
|
||||||
|
image: "file://" + imagePath,
|
||||||
|
urgency: item.urgency,
|
||||||
|
timestamp: item.timestamp,
|
||||||
|
desktopEntry: item.desktopEntry
|
||||||
|
};
|
||||||
|
const newList = historyList.slice();
|
||||||
|
newList[idx] = updated;
|
||||||
|
historyList = newList;
|
||||||
|
saveHistory();
|
||||||
|
}
|
||||||
|
|
||||||
function addToHistory(wrapper) {
|
function addToHistory(wrapper) {
|
||||||
if (!wrapper)
|
if (!wrapper)
|
||||||
return;
|
return;
|
||||||
const urg = typeof wrapper.urgency === "number" ? wrapper.urgency : 1;
|
const urg = typeof wrapper.urgency === "number" ? wrapper.urgency : 1;
|
||||||
|
const imageUrl = wrapper.image || "";
|
||||||
|
let persistableImage = "";
|
||||||
|
if (wrapper.persistedImagePath) {
|
||||||
|
persistableImage = "file://" + wrapper.persistedImagePath;
|
||||||
|
} else if (imageUrl && !imageUrl.startsWith("image://qsimage/")) {
|
||||||
|
persistableImage = imageUrl;
|
||||||
|
}
|
||||||
const data = {
|
const data = {
|
||||||
id: wrapper.notification?.id?.toString() || Date.now().toString(),
|
id: wrapper.notification?.id?.toString() || Date.now().toString(),
|
||||||
summary: wrapper.summary || "",
|
summary: wrapper.summary || "",
|
||||||
@@ -83,7 +121,7 @@ Singleton {
|
|||||||
htmlBody: wrapper.htmlBody || wrapper.body || "",
|
htmlBody: wrapper.htmlBody || wrapper.body || "",
|
||||||
appName: wrapper.appName || "",
|
appName: wrapper.appName || "",
|
||||||
appIcon: wrapper.appIcon || "",
|
appIcon: wrapper.appIcon || "",
|
||||||
image: wrapper.cleanImage || "",
|
image: persistableImage,
|
||||||
urgency: urg,
|
urgency: urg,
|
||||||
timestamp: wrapper.time.getTime(),
|
timestamp: wrapper.time.getTime(),
|
||||||
desktopEntry: wrapper.desktopEntry || ""
|
desktopEntry: wrapper.desktopEntry || ""
|
||||||
@@ -148,9 +186,19 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _deleteCachedImage(imagePath) {
|
||||||
|
if (!imagePath || !imagePath.startsWith("file://"))
|
||||||
|
return;
|
||||||
|
const filePath = imagePath.replace("file://", "");
|
||||||
|
if (filePath.startsWith(imageCacheDir)) {
|
||||||
|
Quickshell.execDetached(["rm", "-f", filePath]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function removeFromHistory(notificationId) {
|
function removeFromHistory(notificationId) {
|
||||||
const idx = historyList.findIndex(n => n.id === notificationId);
|
const idx = historyList.findIndex(n => n.id === notificationId);
|
||||||
if (idx >= 0) {
|
if (idx >= 0) {
|
||||||
|
_deleteCachedImage(historyList[idx].image);
|
||||||
historyList = historyList.filter((_, i) => i !== idx);
|
historyList = historyList.filter((_, i) => i !== idx);
|
||||||
saveHistory();
|
saveHistory();
|
||||||
return true;
|
return true;
|
||||||
@@ -159,6 +207,9 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function clearHistory() {
|
function clearHistory() {
|
||||||
|
for (const item of historyList) {
|
||||||
|
_deleteCachedImage(item.image);
|
||||||
|
}
|
||||||
historyList = [];
|
historyList = [];
|
||||||
saveHistory();
|
saveHistory();
|
||||||
}
|
}
|
||||||
@@ -268,15 +319,22 @@ Singleton {
|
|||||||
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const maxAgeMs = maxAgeDays * 24 * 60 * 60 * 1000;
|
const maxAgeMs = maxAgeDays * 24 * 60 * 60 * 1000;
|
||||||
|
const toRemove = historyList.filter(item => (now - item.timestamp) > maxAgeMs);
|
||||||
const pruned = historyList.filter(item => (now - item.timestamp) <= maxAgeMs);
|
const pruned = historyList.filter(item => (now - item.timestamp) <= maxAgeMs);
|
||||||
|
|
||||||
if (pruned.length !== historyList.length) {
|
if (pruned.length !== historyList.length) {
|
||||||
|
for (const item of toRemove) {
|
||||||
|
_deleteCachedImage(item.image);
|
||||||
|
}
|
||||||
historyList = pruned;
|
historyList = pruned;
|
||||||
saveHistory();
|
saveHistory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteHistory() {
|
function deleteHistory() {
|
||||||
|
for (const item of historyList) {
|
||||||
|
_deleteCachedImage(item.image);
|
||||||
|
}
|
||||||
historyList = [];
|
historyList = [];
|
||||||
historyAdapter.notifications = [];
|
historyAdapter.notifications = [];
|
||||||
historyFileView.writeAdapter();
|
historyFileView.writeAdapter();
|
||||||
@@ -461,6 +519,7 @@ Singleton {
|
|||||||
property bool removedByLimit: false
|
property bool removedByLimit: false
|
||||||
property bool isPersistent: true
|
property bool isPersistent: true
|
||||||
property int seq: 0
|
property int seq: 0
|
||||||
|
property string persistedImagePath: ""
|
||||||
|
|
||||||
onPopupChanged: {
|
onPopupChanged: {
|
||||||
if (!popup) {
|
if (!popup) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import Quickshell
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
@@ -13,6 +12,19 @@ Rectangle {
|
|||||||
property bool hasImage: imageSource !== ""
|
property bool hasImage: imageSource !== ""
|
||||||
property alias imageStatus: internalImage.status
|
property alias imageStatus: internalImage.status
|
||||||
|
|
||||||
|
signal imageSaved(string filePath)
|
||||||
|
|
||||||
|
function saveImageToFile(filePath) {
|
||||||
|
if (internalImage.status !== Image.Ready)
|
||||||
|
return false;
|
||||||
|
internalImage.grabToImage(function (result) {
|
||||||
|
if (result && result.saveToFile(filePath)) {
|
||||||
|
root.imageSaved(filePath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
radius: width / 2
|
radius: width / 2
|
||||||
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1)
|
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1)
|
||||||
border.color: "transparent"
|
border.color: "transparent"
|
||||||
@@ -67,7 +79,6 @@ Rectangle {
|
|||||||
visible: (internalImage.status !== Image.Ready || root.imageSource === "") && root.fallbackIcon !== ""
|
visible: (internalImage.status !== Image.Ready || root.imageSource === "") && root.fallbackIcon !== ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
visible: root.imageSource === "" && root.fallbackIcon === "" && root.fallbackText !== ""
|
visible: root.imageSource === "" && root.fallbackIcon === "" && root.fallbackText !== ""
|
||||||
|
|||||||
Reference in New Issue
Block a user