repository_id: Set(repo.repository_id),
name: Set("Notebooks".to_string()),
parent: Set("".to_string()),
- icon: Set("".to_string()),
kind: Set(CollectionType::Notebook),
..Default::default()
repository_id: Set(repo.repository_id),
name: Set("Notes".to_string()),
parent: Set("/Notebooks".to_string()),
- icon: Set("".to_string()),
kind: Set(CollectionType::Notebook),
..Default::default()
profile_id: Set(profile_id),
name: Set(name.to_string()),
parent: Set(parent_path),
- icon: Set("".to_string()),
kind: Set(CollectionType::Notebook),
..Default::default()
return;
}
};
-
+
let mut update = Note::update_many();
if let Some(nodename ) = &nodename {
- update = update.col_expr(Column::Nodename, Expr::value(nodename.clone()));
+ update = update.col_expr(Column::Nodename, Expr::value(nodename.clone())).col_expr(Column::FixedTitle, Expr::value(true));
}
if let Some(title ) = &title {
update = update.col_expr(Column::Title, Expr::value(title));
}
-
+
let result = update
.filter(Column::NoteId.eq(note_id))
.exec(&bhandle.backend.db).await;
let path = get_note_storage_path(db, note_id).await?;
if let Some(path) = path {
- let m = fs::metadata(Path::new(&path)).await;
- if m.is_ok() {
- return Ok(false) // file exists
+ let p = Path::new(&path);
+ if let Some(parent) = p.parent() {
+ let new_path = parent.join(nodename);
+ let m = fs::metadata(Path::new(new_path.as_path())).await;
+ if m.is_ok() {
+ return Ok(false) // file exists
+ }
}
}
menu.item("New").action("new_note").create();
menu.item("New Window").onclick(|_| new_app_window() ).create();
menu.separator();
+ menu.item("Rename").action("note_rename").create();
menu.item("Delete").action("note_delete").create();
menu.item("Edit Title").action("note_edit_title").create();
});
app.toolbar_appmenu(|menu|{
menu.item("New Window").onclick(|_| new_app_window() ).create();
menu.separator();
+ menu.item("Rename").action("note_rename").create();
menu.item("Delete").action("delete_note").create();
menu.item("Edit Title").action("note_edit_title").create();
});
use backend::backend::{BackendHandle, BroadcastMessage, NoteContentRet, NoteId, NoteTitleUpdate, SaveNoteResult};
use backend::lockmanager::NoteLock;
use entity::note::NoteType;
-use ui_rs::{action, doc_cast, ui_actions, UiModel};
+use ui_rs::{action, dialog, doc_cast, ui_actions, UiModel};
use ui_rs::ui::*;
use crate::AppStates;
use crate::window::NoteTypeTabView;
};
doc.ctx.unset_state(AppStates::NoteShowExtModInfo as i32);
}
+
+ #[action]
+ pub fn note_rename(&mut self, event: &mut ActionEvent) {
+ let Some(doc) = self.doc.get_doc() else {
+ return;
+ };
+ let Some(obj) = &event.obj else {
+ return;
+ };
+ let NoteId::Id(note_id) = self.id else {
+ return;
+ };
+
+ let nodename = match &self.nodename {
+ Some(name) => name.as_str(),
+ None => "",
+ };
+
+ let proxy = doc.doc_proxy();
+ let collection_id = self.collection_id;
+ let backend = self.backend.clone();
+
+ obj.dialog()
+ .title("Rename Note")
+ .content("File Name")
+ .input(true)
+ .input_value(nodename)
+ .button1_label("OK")
+ .closebutton_label("Cancel")
+ .result(move |event|{
+ if let EventType::String(new_name) = &event.event_type && event.intval == 1 {
+ // Rename OK
+ // check if the new nodename is available
+ let new_nodename = new_name.clone();
+ backend.check_nodename(collection_id, note_id, new_name.as_str(), move|result|{
+ proxy.call_mainthread(move|doc, note| {
+ match result {
+ Ok(available) => {
+ if available {
+ let proxy = doc.doc_proxy();
+ note.backend.rename_note(1, Some(new_nodename.clone()), None, |result|{
+ proxy.call_mainthread(|_doc, note|{
+ match result {
+ Ok(updated) => {
+ if updated.rows_affected != 1 {
+ eprintln!("rename_note: unexpected number of rows affected");
+ } else {
+ note.nodename = Some(new_nodename);
+ note.fixed_title = true;
+ }
+ },
+ Err(e) => {
+ eprintln!("note update failed: {:?}", e);
+ }
+ }
+ });
+ });
+ } else {
+ let msg = format!("File {} already exists", new_nodename);
+ dialog!(title = "Rename Note", content = msg.as_str(), button1_label = "OK");
+ }
+ }
+ Err(e) => {
+ eprintln!("check_nodename failed: {:?}", e);
+ }
+ }
+ });
+ });
+ }
+ })
+ .create();
+ }
}
impl NoteViewModel for Note {
pub name: String,
pub parent: String,
- pub icon: String,
+ pub icon: Option<String>,
pub kind: CollectionType,
pub storage: LocalStorageSetting
}
pub fn onactivate<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_list_args_set_onactivate(self.args, Some(event::event_wrapper::<T>));
pub fn onselection<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_list_args_set_onselection(self.args, Some(event::event_wrapper::<T>));
pub fn onactivate<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_list_args_set_onactivate(self.args, Some(event::event_wrapper::<T>));
pub fn onselection<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_list_args_set_onselection(self.args, Some(event::event_wrapper::<T>));
pub fn onactivate<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_sourcelist_args_set_onactivate(self.args, Some(event::event_wrapper::<T>));
pub fn onbuttonclick<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_sourcelist_args_set_onbuttonclick(self.args, Some(event::event_wrapper::<T>));
pub fn onclick<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ctx = UiContext { ptr: self.ctx };
let ptr = ctx.reg_box(wrapper);
unsafe {
pub fn onchange<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ctx = UiContext { ptr: self.ctx };
let ptr = ctx.reg_box(wrapper);
unsafe {
pub fn onchange<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f) );
let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_textarea_args_set_onchange(self.args, Some(event::event_wrapper::<T>));
pub fn ontextchanged<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_textarea_args_set_ontextchanged(self.args, Some(event::event_wrapper::<T>));
pub fn onactivate<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_textfield_args_set_onactivate(self.args, Some(event::event_wrapper::<T>));
pub fn onchange<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ptr = self.obj.ctx.reg_box(wrapper);
unsafe {
ui_textfield_args_set_onchange(self.args, Some(event::event_wrapper::<T>));
pub fn onclick<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ctx = UiContext { ptr: self.ctx };
let ptr = ctx.reg_box(wrapper);
unsafe {
pub fn onchange<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ctx = UiContext { ptr: self.ctx };
let ptr = ctx.reg_box(wrapper);
unsafe {
pub fn onchange<F>(&mut self, f: F) -> &mut Self
where F: FnMut(&mut event::Event<T>) + 'static {
- let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let wrapper = Box::new(EventWrapper::new(f));
let ctx = UiContext { ptr: self.ctx };
let ptr = ctx.reg_box(wrapper);
unsafe {
static void dialog_response(AdwAlertDialog *self, gchar *response, UiEventData *data) {
UiEvent evt;
evt.obj = data->obj;
- evt.document = evt.obj->ctx->document;
- evt.window = evt.obj->window;
+ evt.document = evt.obj ? evt.obj->ctx->document : NULL;
+ evt.window = evt.obj ? evt.obj->window : NULL;
evt.eventdata = NULL;
evt.eventdatatype = 0;
evt.intval = 0;