From c426f6b3b406bdacb688290027469c8c005d571e Mon Sep 17 00:00:00 2001 From: Olaf Wintermann Date: Fri, 28 Aug 2026 20:45:03 +0200 Subject: [PATCH] change attachments list type --- application/note/src/attachment.rs | 40 ++++++++++++++++++++ application/note/src/main.rs | 1 + application/note/src/note.rs | 6 ++- application/note/src/window.rs | 7 +++- ui-rs/src/ui/image.rs | 41 +++++++++++++++++++++ ui/gtk/image.c | 59 ++++++++++++++++++++++-------- ui/ui/image.h | 2 + 7 files changed, 137 insertions(+), 19 deletions(-) create mode 100644 application/note/src/attachment.rs diff --git a/application/note/src/attachment.rs b/application/note/src/attachment.rs new file mode 100644 index 0000000..b58dad4 --- /dev/null +++ b/application/note/src/attachment.rs @@ -0,0 +1,40 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +pub struct Attachment { + pub attachment: entity::attachment::Model, + //pub content: entity::attachmentcontent::Model, +} + +impl Attachment { + pub fn new(model: &entity::attachment::Model) -> Attachment { + Attachment { + attachment: model.clone(), + } + } +} \ No newline at end of file diff --git a/application/note/src/main.rs b/application/note/src/main.rs index d820e73..d8ebbb1 100644 --- a/application/note/src/main.rs +++ b/application/note/src/main.rs @@ -31,6 +31,7 @@ mod newnotebook; mod notebook; mod note; mod file; +mod attachment; use std::env; use backend::backend::{Backend, BackendHandle, BroadcastMessage}; diff --git a/application/note/src/note.rs b/application/note/src/note.rs index 900cc17..87acdc7 100644 --- a/application/note/src/note.rs +++ b/application/note/src/note.rs @@ -25,6 +25,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + use std::path::{Path, PathBuf}; use std::rc::Rc; use std::sync::atomic::{AtomicU64, Ordering}; @@ -39,6 +40,7 @@ use ui_rs::ui::*; use crate::AppStates; use crate::window::NoteTypeTabView; use notify::{Event}; +use crate::attachment::Attachment; static TMP_ID: AtomicU64 = AtomicU64::new(1); @@ -88,7 +90,7 @@ pub struct Note { pub info: UiString, #[bind("note_attachments")] - pub attachments: UiList + pub attachments: UiList } #[ui_actions] @@ -284,7 +286,7 @@ impl Note { Ok(attachments) => { note.attachments.data_mut().clear(); if attachments.len() > 0 { - note.attachments.data_mut().extend(attachments); + note.attachments.data_mut().extend(attachments.iter().map(|a| Attachment::new(a) )); doc.ctx.set_state(AppStates::NoteHasAttachments); } else { doc.ctx.unset_state(AppStates::NoteHasAttachments); diff --git a/application/note/src/window.rs b/application/note/src/window.rs index 82deac6..06491b5 100644 --- a/application/note/src/window.rs +++ b/application/note/src/window.rs @@ -33,6 +33,7 @@ use ui_rs::ui::*; use crate::{App, AppStates}; use entity::collection::{CollectionType, Model as Collection, Node}; use ui_rs::ui::widget::Widget; +use crate::attachment::Attachment; use crate::newnotebook::new_notebook_dialog; use crate::notebook::{notelist_getvalue, Notebook, NotebookItem}; @@ -288,8 +289,12 @@ pub fn create_window(app: &App, ctx: &AppContext) -> UiObject() + obj.itemlist::() .varname("note_attachments") + .createui(|obj, data, _i|{ + let _imgviewer = obj.imageviewer().create(); + // TODO: set img from attachment preview + }) .create(); }); w.set_size(-1, 120); diff --git a/ui-rs/src/ui/image.rs b/ui-rs/src/ui/image.rs index a97e546..35fe534 100644 --- a/ui-rs/src/ui/image.rs +++ b/ui-rs/src/ui/image.rs @@ -96,6 +96,45 @@ impl Widget for ImageViewer { } } +impl ImageViewer { + pub fn reset(&self) { + unsafe { + ui_imageviewer_reset(self.ptr); + } + } + + pub fn set_autoscale(&self, set: bool) { + unsafe { + ui_imageviewer_set_autoscale(self.ptr, set as c_int); + } + } + + pub fn set_adjustwidgetsize(&self, set: bool) { + unsafe { + ui_imageviewer_set_adjustwidgetsize(self.ptr, set as c_int); + } + } + + pub fn set_useradjustable(&self, set: bool) { + unsafe { + ui_imageviewer_set_useradjustable(self.ptr, set as c_int); + } + } + + pub fn load_file(&self, path: &Path) { + let path = CString::new(path.to_string_lossy().as_bytes()).expect("path contains an embedded NUL byte"); + unsafe { + ui_imageviewer_load_file(self.ptr, path.as_ptr() as *const c_char); + } + } + + pub fn load_data(&self, data: &Vec) { + unsafe { + ui_imageviewer_load_data(self.ptr, data.as_ptr() as *const c_void, data.len() as libc::size_t); + } + } +} + pub struct ImageViewerBuilder<'a, T> { args: *mut UiImageViewerArgs, obj: &'a mut toolkit::UiObject, @@ -398,4 +437,6 @@ unsafe extern "C" { fn ui_imageviewer_set_autoscale(widget: *mut c_void, set: c_int); fn ui_imageviewer_set_adjustwidgetsize(widget: *mut c_void, set: c_int); fn ui_imageviewer_set_useradjustable(widget: *mut c_void, set: c_int); + fn ui_imageviewer_load_file(widget: *mut c_void, path: *const c_char); + fn ui_imageviewer_load_data(widget: *mut c_void, imgdata: *const c_void, size: libc::size_t); } \ No newline at end of file diff --git a/ui/gtk/image.c b/ui/gtk/image.c index b323cd0..5fcb048 100644 --- a/ui/gtk/image.c +++ b/ui/gtk/image.c @@ -238,6 +238,48 @@ void ui_imageviewer_set_useradjustable(UIWIDGET w, UiBool set) { } } +static void imageviewer_set(UiImageViewer *imgviewer, GdkPixbuf *pixbuf) { + if(imgviewer->pixbuf) { + g_object_unref(imgviewer->pixbuf); + } + + g_object_ref(pixbuf); + imgviewer->pixbuf = pixbuf; + + imageviewer_reset(imgviewer); + if(imgviewer->adjustwidgetsize && !imgviewer->autoscale) { + int width = gdk_pixbuf_get_width(pixbuf); + int height = gdk_pixbuf_get_height(pixbuf); + gtk_widget_set_size_request(imgviewer->widget, width, height); + } + gtk_widget_queue_draw(imgviewer->widget); +} + +void ui_imageviewer_load_file(UIWIDGET w, const char *path) { + UiImageViewer *imgviewer = g_object_get_data(G_OBJECT(w), "uiimageviewer"); + if(imgviewer) { + GError *error = NULL; + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &error); + if(pixbuf) { + imageviewer_set(imgviewer, pixbuf); + } + } +} + +void ui_imageviewer_load_data(UIWIDGET w, const void *imgdata, size_t size) { + UiImageViewer *imgviewer = g_object_get_data(G_OBJECT(w), "uiimageviewer"); + if(imgviewer) { + GBytes *bytes = g_bytes_new_static(imgdata, size); + GInputStream *in = g_memory_input_stream_new_from_bytes(bytes); + GError *error = NULL; + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_stream(in, NULL, &error); + g_object_unref(in); + if(pixbuf) { + imageviewer_set(imgviewer, pixbuf); + } + } +} + void ui_cairo_draw_image(UiImageViewer *imgviewer, cairo_t *cr, int width, int height) { if(!imgviewer->pixbuf) { return; @@ -306,24 +348,9 @@ int ui_imageviewer_set(UiGeneric *g, void *value, const char *type) { } GdkPixbuf *pixbuf = value; - g_object_ref(pixbuf); - UiImageViewer *imgviewer = g->obj; g->value = pixbuf; - - imageviewer_reset(imgviewer); - - if(imgviewer->pixbuf) { - g_object_unref(imgviewer->pixbuf); - } - imgviewer->pixbuf = pixbuf; - - if(imgviewer->adjustwidgetsize && !imgviewer->autoscale) { - int width = gdk_pixbuf_get_width(pixbuf); - int height = gdk_pixbuf_get_height(pixbuf); - gtk_widget_set_size_request(imgviewer->widget, width, height); - } - gtk_widget_queue_draw(imgviewer->widget); + imageviewer_set(imgviewer, pixbuf); return 0; } diff --git a/ui/ui/image.h b/ui/ui/image.h index f3498fa..e4eee59 100644 --- a/ui/ui/image.h +++ b/ui/ui/image.h @@ -92,6 +92,8 @@ UIEXPORT void ui_imageviewer_reset(UIWIDGET w); UIEXPORT void ui_imageviewer_set_autoscale(UIWIDGET w, UiBool set); UIEXPORT void ui_imageviewer_set_adjustwidgetsize(UIWIDGET w, UiBool set); UIEXPORT void ui_imageviewer_set_useradjustable(UIWIDGET w, UiBool set); +UIEXPORT void ui_imageviewer_load_file(UIWIDGET w, const char *path); +UIEXPORT void ui_imageviewer_load_data(UIWIDGET w, const void *imgdata, size_t size); UIEXPORT int ui_image_load_file(UiGeneric *obj, const char *path); UIEXPORT int ui_image_load_data(UiGeneric *obj, const void *imgdata, size_t size); -- 2.52.0