Launcher: wip image preview
This commit is contained in:
parent
ded133d164
commit
132dbce3a3
3 changed files with 55 additions and 53 deletions
|
|
@ -231,9 +231,6 @@ NPanel {
|
|||
|
||||
clip: true
|
||||
cacheBuffer: resultsList.height * 2
|
||||
//boundsBehavior: Flickable.StopAtBounds
|
||||
// maximumFlickVelocity: 2500
|
||||
// flickDeceleration: 2000
|
||||
onCurrentIndexChanged: {
|
||||
cancelFlick()
|
||||
if (currentIndex >= 0) {
|
||||
|
|
@ -245,15 +242,26 @@ NPanel {
|
|||
policy: ScrollBar.AsNeeded
|
||||
}
|
||||
|
||||
// Replace the delegate in Launcher.qml's ListView with this enhanced version:
|
||||
delegate: Rectangle {
|
||||
id: entry
|
||||
|
||||
property bool isSelected: mouseArea.containsMouse || (index === selectedIndex)
|
||||
property int badgeSize: Style.baseWidgetSize * 1.75 * scaling
|
||||
property int badgeSize: Style.baseWidgetSize * 1.75 * scaling
|
||||
|
||||
// Property to reliably track the current item's ID.
|
||||
// This changes whenever the delegate is recycled for a new item.
|
||||
property var currentClipboardId: modelData.isImage ? modelData.clipboardId : ""
|
||||
|
||||
// When this delegate is assigned a new image item, trigger the decode.
|
||||
onCurrentClipboardIdChanged: {
|
||||
// Check if it's a valid ID and if the data isn't already cached.
|
||||
if (currentClipboardId && !CliphistService.getImageData(currentClipboardId)) {
|
||||
CliphistService.decodeToDataUrl(currentClipboardId, modelData.mime, null)
|
||||
}
|
||||
}
|
||||
|
||||
width: resultsList.width - Style.marginS * scaling
|
||||
height: badgeSize + Style.marginM * 2 *scaling
|
||||
height: badgeSize + Style.marginM * 2 * scaling
|
||||
radius: Style.radiusM * scaling
|
||||
color: entry.isSelected ? Color.mTertiary : Color.mSurface
|
||||
|
||||
|
|
@ -282,8 +290,19 @@ NPanel {
|
|||
id: imagePreview
|
||||
anchors.fill: parent
|
||||
anchors.margins: 2 * scaling
|
||||
visible: modelData.isImage && modelData.imageSource
|
||||
source: modelData.imageSource || ""
|
||||
visible: modelData.isImage
|
||||
|
||||
// This property creates a dependency on the service's revision counter
|
||||
readonly property int _rev: CliphistService.revision
|
||||
|
||||
// Fetches from the service's cache.
|
||||
// The dependency on `_rev` ensures this binding is re-evaluated
|
||||
// when the cache is updated by the service.
|
||||
source: {
|
||||
_rev
|
||||
return CliphistService.getImageData(modelData.clipboardId) || ""
|
||||
}
|
||||
|
||||
fillMode: Image.PreserveAspectFit
|
||||
smooth: true
|
||||
mipmap: true
|
||||
|
|
@ -307,7 +326,6 @@ NPanel {
|
|||
// Error fallback
|
||||
onStatusChanged: {
|
||||
if (status === Image.Error) {
|
||||
// Fall back to icon
|
||||
iconLoader.visible = true
|
||||
imagePreview.visible = false
|
||||
}
|
||||
|
|
@ -319,7 +337,8 @@ NPanel {
|
|||
id: iconLoader
|
||||
anchors.fill: parent
|
||||
anchors.margins: Style.marginXS * scaling
|
||||
visible: !modelData.isImage || !modelData.imageSource || imagePreview.status === Image.Error
|
||||
|
||||
visible: !modelData.isImage || imagePreview.status === Image.Error
|
||||
active: visible
|
||||
|
||||
sourceComponent: Component {
|
||||
|
|
@ -391,23 +410,6 @@ NPanel {
|
|||
Layout.fillWidth: true
|
||||
visible: text !== ""
|
||||
}
|
||||
|
||||
// // Show text preview for text items if space allows
|
||||
// NText {
|
||||
// visible: !modelData.isImage && modelData.fullText && modelData.fullText.length > 100
|
||||
// text: {
|
||||
// if (!modelData.fullText) return ""
|
||||
// const preview = modelData.fullText.substring(0, 150).replace(/\n/g, " ")
|
||||
// return preview + (modelData.fullText.length > 150 ? "..." : "")
|
||||
// }
|
||||
// font.pointSize: Style.fontSizeXS * scaling
|
||||
// color: entry.isSelected ? Color.mOnTertiary : Color.mOnSurfaceVariant
|
||||
// opacity: 0.7
|
||||
// elide: Text.ElideRight
|
||||
// maximumLineCount: 2
|
||||
// wrapMode: Text.WordWrap
|
||||
// Layout.fillWidth: true
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,17 @@ QtObject {
|
|||
// Plugin capabilities
|
||||
property bool handleSearch: false // Don't handle regular search
|
||||
|
||||
// Connections {
|
||||
// target: CliphistService
|
||||
// // Use the function syntax for on<SignalName>
|
||||
// function onListCompleted() {
|
||||
// // Only refresh if the clipboard plugin is active
|
||||
// if (launcher && launcher.activePlugin === root) {
|
||||
// launcher.updateResults()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Initialize plugin
|
||||
function init() {
|
||||
Logger.log("ClipboardPlugin", "Initialized")
|
||||
|
|
@ -121,40 +132,22 @@ QtObject {
|
|||
return results
|
||||
}
|
||||
|
||||
// Helper: Format image clipboard entry with actual image data
|
||||
// Helper: Format image clipboard entry
|
||||
function formatImageEntry(item) {
|
||||
const meta = parseImageMeta(item.preview)
|
||||
|
||||
// Get the actual image data/path from the clipboard service
|
||||
// This assumes CliphistService provides either a path or base64 data
|
||||
let imageData = null
|
||||
|
||||
// Try to get image data from the service
|
||||
// Method 1: If the service provides a file path
|
||||
if (item.imagePath) {
|
||||
imageData = "file://" + item.imagePath
|
||||
} // Method 2: If the service provides base64 data
|
||||
else if (item.imageData) {
|
||||
imageData = ClipHistService.getImageData(item.id)
|
||||
|
||||
// "data:" + (item.mime || "image/png") + ";base64," + item.imageData
|
||||
} // Method 3: If we need to fetch it from the service
|
||||
|
||||
// else if (item.id) {
|
||||
// // Some clipboard services might require fetching the image separately
|
||||
// // This would depend on your CliphistService implementation
|
||||
// imageData = CliphistService.getImageData ? CliphistService.getImageData(item.id) : null
|
||||
// }
|
||||
// The launcher's delegate will now be responsible for fetching the image data.
|
||||
// This function's role is to provide the necessary metadata for that request.
|
||||
return {
|
||||
"name": meta ? `Image ${meta.w}×${meta.h}` : "Image",
|
||||
"description": meta ? `${meta.fmt} • ${meta.size}` : item.mime || "Image data",
|
||||
"icon": "image",
|
||||
"isImage": true,
|
||||
"imageSource": imageData,
|
||||
"imageWidth": meta ? meta.w : 0,
|
||||
"imageHeight": meta ? meta.h : 0,
|
||||
"clipboardId"// Add clipboard item ID for potential async loading
|
||||
: item.id
|
||||
"clipboardId"// Provide the ID and mime type for the delegate to make an async request
|
||||
: item.id,
|
||||
"mime": item.mime
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -185,7 +178,7 @@ QtObject {
|
|||
return {
|
||||
"name": title,
|
||||
"description": description,
|
||||
"icon": "description",
|
||||
"icon": "text-x-generic",
|
||||
"isImage": false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ Singleton {
|
|||
property string _b64CurrentMime: ""
|
||||
property string _b64CurrentId: ""
|
||||
|
||||
signal listCompleted()
|
||||
|
||||
// Check if cliphist is available
|
||||
Component.onCompleted: {
|
||||
checkCliphistAvailability()
|
||||
|
|
@ -147,6 +149,9 @@ Singleton {
|
|||
})
|
||||
items = parsed
|
||||
loading = false
|
||||
|
||||
// Emit the signal for subscribers
|
||||
root.listCompleted()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -285,10 +290,12 @@ Singleton {
|
|||
}
|
||||
|
||||
function getImageData(id) {
|
||||
if (id === undefined) {
|
||||
return null
|
||||
}
|
||||
return root.imageDataById[id]
|
||||
}
|
||||
|
||||
|
||||
function _startNextB64() {
|
||||
if (root._b64Queue.length === 0 || !root.cliphistAvailable)
|
||||
return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue