]> uap-core.de Git - note.git/commitdiff
implement Open button in the FileNote viewmodel main
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Wed, 15 Jul 2026 18:17:33 +0000 (20:17 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Wed, 15 Jul 2026 18:17:33 +0000 (20:17 +0200)
application/backend/src/backend.rs
application/note/src/file.rs
application/note/src/notebook.rs
ui-rs/src/ui/toolkit.rs
ui/gtk/toolkit.c
ui/motif/Grid.c
ui/ui/toolkit.h

index e22b06096c68cab88d38f0a793227ae3be781661..3253a1eb624ccb019a41e197e638a10716640d1e 100644 (file)
@@ -589,6 +589,30 @@ impl BackendHandle {
         });
         let _ = self.tx.send(cmd);
     }
+
+    pub fn open_extern<F>(&self, note_id: i32, callback: F)
+    where F: FnOnce(OpenExternResult) + Send + 'static {
+        let backend = self.backend.clone();
+        let cmd = Box::pin(async move {
+            // check if the note content is stored in the filesystem or database
+            let storage_result = get_note_storage_path(&backend.db, note_id).await;
+            let note_path = match storage_result {
+                Ok(note_path) => note_path,
+                Err(e) => {
+                    callback(OpenExternResult::DbErr(e));
+                    return;
+                }
+            };
+
+            if let Some(note_path) = note_path {
+                // local storage
+                callback(OpenExternResult::Ok((note_path, false)));
+            } else {
+                // TODO: copy content from db to tmp file
+            }
+        });
+        let _ = self.tx.send(cmd);
+    }
 }
 
 
@@ -602,6 +626,12 @@ pub enum SaveNoteResult {
     ValidationError(&'static str)
 }
 
+pub enum OpenExternResult {
+    Ok((String, bool)), // path, istmp
+    DbErr(DbErr),
+    FsErr(Error)
+}
+
 impl SaveNoteResult {
     pub fn is_ok(&self) -> bool {
         matches!(self, SaveNoteResult::Ok(_))
index 36068f926f7b946dd8c3f2aee5f3355d189d032f..f5622c2ad0c49e5baaadbf92ac691d0c976c8667 100644 (file)
  * POSSIBILITY OF SUCH DAMAGE.
  */
 use std::rc::Rc;
-use backend::backend::{BackendHandle, NoteId};
-use entity::note::NoteType;
+use backend::backend::{BackendHandle, NoteId, OpenExternResult};
 use ui_rs::{action, ui_actions, UiModel};
 use ui_rs::ui::*;
 use crate::AppStates;
-use crate::note::Note;
 use crate::window::NoteTypeTabView;
 
 #[derive(UiModel)]
@@ -44,6 +42,9 @@ pub struct FileNote {
     pub id: NoteId,
     pub nodename: String,
 
+    pub local_path: Option<String>,
+    pub is_tmp_file: bool,
+
     #[bind("note_type")]
     pub note_type: UiInteger,
 
@@ -62,6 +63,8 @@ impl FileNote {
 
             id,
             nodename: String::default(),
+            local_path: None,
+            is_tmp_file: false,
 
             note_type: Default::default(),
             note_nodename: Default::default(),
@@ -80,7 +83,31 @@ impl FileNote {
 
     #[action]
     pub fn open_extern(&mut self, _event: &ActionEvent) {
-        // TODO: request open from backend
+        let Some(doc) = self.doc.get_doc() else {
+            return;
+        };
+
+        if let Some(path) = &self.local_path {
+            println!("open file: {}", path);
+            open_file(path.as_str());
+        } else if let NoteId::Id(note_id) = self.id {
+            let proxy = doc.doc_proxy();
+            self.backend.open_extern(note_id, |result|{
+                proxy.call_mainthread(move |_doc, note|{
+                    match result {
+                        OpenExternResult::Ok((path, istmp)) => {
+                            println!("open file: {}", path);
+                            open_file(path.as_str());
+                            note.local_path = Some(path);
+                            note.is_tmp_file = istmp;
+                        }
+                        _ => {
+                            println!("open_extern failed");
+                        }
+                    }
+                });
+            });
+        }
     }
 
     #[action]
index becd621ca51cd223e361b90cf39d56ece2d4596f..c5ee2ece590bc79ef36c0a5f915fb451ae30a1ac 100644 (file)
@@ -109,7 +109,7 @@ impl Notebook {
             // doc_ref.get_doc() should never fail here
             if let Some(mut doc) = self.doc_ref.get_doc() {
                 // save the note
-                let note_proxy = current.doc.save_note();
+                current.doc.save_note();
 
                 // detach the note
                 current.doc.detach_from(&mut doc.ctx);
index d40d07b0b9fb2021fde724a6b1b028a45a0117f5..39c119db9ceddbabf561b1ab2d4106cc92588d1e 100644 (file)
@@ -1334,6 +1334,23 @@ pub fn app_set_configdir(path: &str) {
     }
 }
 
+/* ----------------------------------- Utils ---------------------------------- */
+
+pub fn open_uri(uri: &str) {
+    let cstr = CString::new(uri).unwrap();
+    unsafe {
+        ui_open_uri(cstr.as_ptr());
+    }
+}
+
+pub fn open_file(path: &str) {
+    let cstr = CString::new(path).unwrap();
+    unsafe {
+        ui_open_file(cstr.as_ptr());
+    }
+}
+
+
 /* -------------------------------- C functions -------------------------------- */
 
 unsafe extern "C" {
@@ -1453,4 +1470,7 @@ unsafe extern "C" {
     fn ui_call_action(ctx: *mut ffi::UiContext, action: *const c_char) -> c_int;
     fn ui_call_action3(ctx: *mut ffi::UiContext, action: *const c_char, data: *mut c_void, typeid: u64) -> c_int;
     fn ui_mainthread_broadcast(action: *const c_char);
+
+    fn ui_open_uri(uri: *const c_char);
+    fn ui_open_file(path: *const c_char);
 }
index dbdde0a91164fbdcc36a09352bc3ce1380478a29..f4636dd6099ec9a3f9506d60542d2bc5e40b0015 100644 (file)
@@ -579,3 +579,10 @@ void ui_open_uri(const char *uri) {
     // TODO: call xdg-open
 #endif
 }
+
+void ui_open_file(const char *path) {
+    GFile *file = g_file_new_for_path(path);
+    GError *error = NULL;
+    g_app_info_launch_default_for_uri(g_file_get_uri(file), NULL, &error);
+    g_object_unref(file);
+}
index da74124f14b673ffbbecb3f1366250100ee99048..23cf424994700c4d4c9f0e9b24488157dce3733f 100644 (file)
@@ -281,11 +281,11 @@ GridClassRec gridClassRec = {
         NULL,                         // set_values_hook
         XtInheritSetValuesAlmost,     // set_values_almost
         NULL,                         // get_values_hook
-        (XtAcceptFocusProc)grid_acceptfocus,       // accept_focus
+        (XtAcceptFocusProc)NULL,       // accept_focus
         XtVersion,                    // version
         NULL,                         // callback_offsets
         //NULL,                         // tm_table
-                defaultTranslations,
+        XtInheritTranslations, //defaultTranslations,
         XtInheritQueryGeometry,       // query_geometry
         NULL,                         // display_accelerator
         NULL,                         // extension
@@ -342,7 +342,7 @@ void grid_initialize(Widget request, Widget new, ArgList args, Cardinal num_args
 void grid_realize(Widget w,XtValueMask *valueMask,XSetWindowAttributes *attributes) {
     Grid grid = (Grid)w;
     XtMakeResizeRequest(w, 400, 400, NULL, NULL);
-    (coreClassRec.core_class.realize)((Widget)w, valueMask, attributes); 
+    (*xmManagerClassRec.core_class.realize)(w, valueMask, attributes);
     grid_place_children(grid);
 }
 
@@ -363,9 +363,6 @@ Boolean grid_set_values(Widget old, Widget request, Widget neww, ArgList args, C
     return False;
 }
 
-Boolean grid_acceptfocus(Widget w, Time *t) {
-    
-}
 
 void grid_getfocus(Widget myw, XEvent *event, String *params, Cardinal *nparam) {
     
index 0537d58f073ec029fe8ad69f73d2d28025bab62a..e56a3c5b6d484d04713546a4be0461a10211db1d 100644 (file)
@@ -795,6 +795,7 @@ UIEXPORT void ui_app_ref(void);
 UIEXPORT void ui_app_unref(void);
 
 UIEXPORT void ui_open_uri(const char *uri);
+UIEXPORT void ui_open_file(const char *path);
 
 #ifdef __cplusplus
 }