[niepce] workspace: added delete folder command
- From: Hubert Figuière <hub src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [niepce] workspace: added delete folder command
- Date: Fri, 17 Nov 2017 18:26:12 +0000 (UTC)
commit 20910be51b670a812b26e0d5b7a88f358c65473d
Author: Hubert Figuière <hub figuiere net>
Date: Fri Nov 17 12:50:12 2017 -0500
workspace: added delete folder command
- NotificationType enum no longer have hard coded values
- Added delete folder library client interface
- Added create folder async version
- Added FOLDER_DELETED notifiation type and associated enums and API
- Added ui::confirm_dialog
src/Makefile.am | 1 +
src/engine/db/library.rs | 11 +++++++
src/engine/library/commands.rs | 8 +++++
src/engine/library/notification.rs | 38 +++++++++++++----------
src/libraryclient/clientimpl.rs | 12 +++++++
src/libraryclient/clientinterface.rs | 2 +
src/libraryclient/libraryclient.rs | 14 +++++++++
src/niepce/ui/dialogs/confirm.rs | 48 +++++++++++++++++++++++++++++
src/niepce/ui/dialogs/mod.rs | 20 ++++++++++++-
src/niepce/ui/workspacecontroller.cpp | 53 +++++++++++++++++++++++++++++++++
src/niepce/ui/workspacecontroller.hpp | 5 +++
src/rust_bindings.hpp | 1 +
12 files changed, 195 insertions(+), 18 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 97156c8..bf29b29 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -42,6 +42,7 @@ RUST_SOURCES = \
@top_srcdir@/src/niepce/mod.rs \
@top_srcdir@/src/niepce/ui/mod.rs \
@top_srcdir@/src/niepce/ui/dialogs/mod.rs \
+ @top_srcdir@/src/niepce/ui/dialogs/confirm.rs \
@top_srcdir@/src/niepce/ui/dialogs/requestnewfolder.rs \
$(NULL)
diff --git a/src/engine/db/library.rs b/src/engine/db/library.rs
index 5a6e768..852502f 100644
--- a/src/engine/db/library.rs
+++ b/src/engine/db/library.rs
@@ -274,6 +274,17 @@ impl Library {
return Some(lf);
}
+ pub fn delete_folder(&self, id: LibraryId) -> bool {
+ if let Some(ref conn) = self.dbconn {
+ if let Some(c) = conn.execute("DELETE FROM folders WHERE id=:1", &[&id]).ok() {
+ if c == 1 {
+ return true;
+ }
+ }
+ }
+ false
+ }
+
pub fn get_folder(&self, folder: &str) -> Option<LibFolder> {
let foldername = try_opt!(Self::leaf_name_for_pathname(folder));
let conn = try_opt!(self.dbconn.as_ref());
diff --git a/src/engine/library/commands.rs b/src/engine/library/commands.rs
index 972febd..4e6201e 100644
--- a/src/engine/library/commands.rs
+++ b/src/engine/library/commands.rs
@@ -132,6 +132,14 @@ pub fn cmd_create_folder(lib: &Library, name: &String, path: Option<String>) ->
0
}
+pub fn cmd_delete_folder(lib: &Library, id: LibraryId) -> bool {
+ if lib.delete_folder(id) {
+ lib.notify(Box::new(LibNotification::FolderDeleted(id)));
+ return true;
+ }
+ false
+}
+
pub fn cmd_request_metadata(lib: &Library, file_id: LibraryId) -> bool {
if let Some(lm) = lib.get_metadata(file_id) {
lib.notify(Box::new(LibNotification::MetadataQueried(lm)));
diff --git a/src/engine/library/notification.rs b/src/engine/library/notification.rs
index 098777a..bd71666 100644
--- a/src/engine/library/notification.rs
+++ b/src/engine/library/notification.rs
@@ -31,23 +31,24 @@ pub type Content = QueriedContent;
#[repr(i32)]
#[allow(non_camel_case_types)]
pub enum NotificationType {
- NONE = 0,
- NEW_LIBRARY_CREATED = 1,
- ADDED_FOLDER = 2,
- ADDED_FILE = 3,
- ADDED_FILES = 4,
- ADDED_KEYWORD = 5,
- ADDED_LABEL = 6,
- FOLDER_CONTENT_QUERIED = 7,
- KEYWORD_CONTENT_QUERIED = 8,
- METADATA_QUERIED = 9,
- METADATA_CHANGED = 10,
- LABEL_CHANGED = 11,
- LABEL_DELETED = 12,
- XMP_NEEDS_UPDATE = 13,
- FOLDER_COUNTED = 14,
- FOLDER_COUNT_CHANGE = 15,
- FILE_MOVED = 16,
+ NONE,
+ NEW_LIBRARY_CREATED,
+ ADDED_FOLDER,
+ ADDED_FILE,
+ ADDED_FILES,
+ ADDED_KEYWORD,
+ ADDED_LABEL,
+ FOLDER_CONTENT_QUERIED,
+ FOLDER_DELETED,
+ KEYWORD_CONTENT_QUERIED,
+ METADATA_QUERIED,
+ METADATA_CHANGED,
+ LABEL_CHANGED,
+ LABEL_DELETED,
+ XMP_NEEDS_UPDATE,
+ FOLDER_COUNTED,
+ FOLDER_COUNT_CHANGE ,
+ FILE_MOVED,
}
#[repr(C)]
@@ -93,6 +94,7 @@ pub enum Notification {
FolderContentQueried(Content),
FolderCounted(FolderCount),
FolderCountChanged(FolderCount),
+ FolderDeleted(LibraryId),
KeywordContentQueried(Content),
LabelChanged(Label),
LabelDeleted(LibraryId),
@@ -146,6 +148,7 @@ pub extern "C" fn engine_library_notification_type(n: *const Notification) -> No
Some(&Notification::FolderContentQueried(_)) => NotificationType::FOLDER_CONTENT_QUERIED,
Some(&Notification::FolderCounted(_)) => NotificationType::FOLDER_COUNTED,
Some(&Notification::FolderCountChanged(_)) => NotificationType::FOLDER_COUNT_CHANGE,
+ Some(&Notification::FolderDeleted(_)) => NotificationType::FOLDER_DELETED,
Some(&Notification::KeywordContentQueried(_)) =>
NotificationType::KEYWORD_CONTENT_QUERIED,
Some(&Notification::LabelChanged(_)) => NotificationType::LABEL_CHANGED,
@@ -164,6 +167,7 @@ pub extern "C" fn engine_library_notification_type(n: *const Notification) -> No
pub extern "C" fn engine_library_notification_get_id(n: *const Notification) -> LibraryId {
match unsafe { n.as_ref() } {
Some(&Notification::MetadataChanged(ref changed)) => changed.id,
+ Some(&Notification::FolderDeleted(id)) => id,
Some(&Notification::LabelDeleted(id)) => id,
_ => unreachable!(),
}
diff --git a/src/libraryclient/clientimpl.rs b/src/libraryclient/clientimpl.rs
index 65d1ec4..27a6b16 100644
--- a/src/libraryclient/clientimpl.rs
+++ b/src/libraryclient/clientimpl.rs
@@ -140,6 +140,18 @@ impl ClientInterface for ClientImpl {
});
}
+ fn create_folder(&mut self, name: String, path: Option<String>) {
+ self.schedule_op(move |lib| {
+ commands::cmd_create_folder(&lib, &name, path.clone()) != 0
+ });
+ }
+
+ fn delete_folder(&mut self, id: LibraryId) {
+ self.schedule_op(move |lib| {
+ commands::cmd_delete_folder(&lib, id)
+ });
+ }
+
fn request_metadata(&mut self, file_id: LibraryId) {
self.schedule_op(move |lib| {
commands::cmd_request_metadata(&lib, file_id)
diff --git a/src/libraryclient/clientinterface.rs b/src/libraryclient/clientinterface.rs
index e58e8c1..4206b8c 100644
--- a/src/libraryclient/clientinterface.rs
+++ b/src/libraryclient/clientinterface.rs
@@ -33,6 +33,8 @@ pub trait ClientInterface {
fn get_all_folders(&mut self);
fn query_folder_content(&mut self, id: LibraryId);
fn count_folder(&mut self, id: LibraryId);
+ fn create_folder(&mut self, name: String, path: Option<String>);
+ fn delete_folder(&mut self, id: LibraryId);
fn request_metadata(&mut self, id: LibraryId);
/// set the metadata
diff --git a/src/libraryclient/libraryclient.rs b/src/libraryclient/libraryclient.rs
index 5de76e4..ae470f1 100644
--- a/src/libraryclient/libraryclient.rs
+++ b/src/libraryclient/libraryclient.rs
@@ -94,6 +94,14 @@ impl ClientInterface for LibraryClient {
self.pimpl.count_folder(id);
}
+ fn create_folder(&mut self, name: String, path: Option<String>) {
+ self.pimpl.create_folder(name, path);
+ }
+
+ fn delete_folder(&mut self, id: LibraryId) {
+ self.pimpl.delete_folder(id);
+ }
+
fn request_metadata(&mut self, id: LibraryId) {
self.pimpl.request_metadata(id);
}
@@ -209,6 +217,12 @@ pub extern "C" fn libraryclient_create_folder_sync(client: &mut LibraryClientWra
}
#[no_mangle]
+pub extern "C" fn libraryclient_delete_folder(client: &mut LibraryClientWrapper,
+ id: LibraryId) {
+ client.unwrap_mut().delete_folder(id);
+}
+
+#[no_mangle]
pub extern "C" fn libraryclient_count_folder(client: &mut LibraryClientWrapper,
folder_id: LibraryId) {
client.unwrap_mut().count_folder(folder_id)
diff --git a/src/niepce/ui/dialogs/confirm.rs b/src/niepce/ui/dialogs/confirm.rs
new file mode 100644
index 0000000..0908798
--- /dev/null
+++ b/src/niepce/ui/dialogs/confirm.rs
@@ -0,0 +1,48 @@
+/*
+ * niepce - niepce/ui/dialogs/confirm.rs
+ *
+ * Copyright (C) 2017 Hubert Figuière
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+use libc::c_char;
+use std::ffi::CStr;
+
+use glib::translate::*;
+use gtk::prelude::*;
+use gtk;
+use gtk_sys;
+use gtk::{
+ MessageDialog,
+};
+
+#[no_mangle]
+pub extern "C" fn dialog_confirm(message: *const c_char,
+ parent: *mut gtk_sys::GtkWindow) -> bool {
+
+ let mut result: bool = false;
+ let msg = unsafe { CStr::from_ptr(message) }.to_string_lossy();
+ let parent = unsafe { gtk::Window::from_glib_none(parent) };
+ let dialog = MessageDialog::new(Some(&parent), gtk::DIALOG_MODAL,
+ gtk::MessageType::Question, gtk::ButtonsType::YesNo,
+ &*msg);
+
+ if dialog.run() == gtk::ResponseType::Yes.into() {
+ result = true;
+ }
+ dialog.destroy();
+
+ result
+}
diff --git a/src/niepce/ui/dialogs/mod.rs b/src/niepce/ui/dialogs/mod.rs
index 77354fe..4bb2738 100644
--- a/src/niepce/ui/dialogs/mod.rs
+++ b/src/niepce/ui/dialogs/mod.rs
@@ -1,3 +1,21 @@
+/*
+ * niepce - niepce/ui/dialogs/mod.rs
+ *
+ * Copyright (C) 2017 Hubert Figuière
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
-
+pub mod confirm;
pub mod requestnewfolder;
diff --git a/src/niepce/ui/workspacecontroller.cpp b/src/niepce/ui/workspacecontroller.cpp
index b26009f..5fe484e 100644
--- a/src/niepce/ui/workspacecontroller.cpp
+++ b/src/niepce/ui/workspacecontroller.cpp
@@ -96,6 +96,17 @@ void WorkspaceController::action_new_folder()
ui::dialog_request_new_folder(getLibraryClient()->client(), window.gobj());
}
+void WorkspaceController::action_delete_folder()
+{
+ auto id = get_selected_folder_id();
+ if (id) {
+ auto& window = std::dynamic_pointer_cast<NiepceWindow>(m_parent.lock())->gtkWindow();
+ if (ui::dialog_confirm(_("Delete selected folder?"), window.gobj())) {
+ ffi::libraryclient_delete_folder(getLibraryClient()->client(), id);
+ }
+ }
+}
+
void WorkspaceController::action_file_import()
{
int result;
@@ -154,6 +165,12 @@ void WorkspaceController::on_lib_notification(const eng::LibNotification &ln)
this->add_folder_item(f);
break;
}
+ case eng::NotificationType::FOLDER_DELETED:
+ {
+ auto id = engine_library_notification_get_id(&ln);
+ remove_folder_item(id);
+ break;
+ }
case eng::NotificationType::ADDED_KEYWORD:
{
auto k = engine_library_notification_get_keyword(&ln);
@@ -200,6 +217,20 @@ void WorkspaceController::on_count_notification(int)
DBG_OUT("received NOTIFICATION_COUNT");
}
+eng::library_id_t WorkspaceController::get_selected_folder_id()
+{
+ auto selection = m_librarytree.get_selection();
+ auto selected = selection->get_selected();
+ if (selected == m_librarytree.get_model()->children().end()) {
+ return 0;
+ }
+ int type = (*selected)[m_librarycolumns.m_type];
+ eng::library_id_t id = (*selected)[m_librarycolumns.m_id];
+ if (type != FOLDER_ITEM) {
+ return 0;
+ }
+ return id;
+}
void WorkspaceController::on_libtree_selection()
{
@@ -221,6 +252,9 @@ void WorkspaceController::on_libtree_selection()
default:
DBG_OUT("selected something not a folder");
}
+
+ Glib::RefPtr<Gio::SimpleAction>::cast_dynamic(
+ m_action_group->lookup_action("DeleteFolder"))->set_enabled(type == FOLDER_ITEM);
}
void WorkspaceController::on_row_expanded_collapsed(const Gtk::TreeIter& iter,
@@ -275,6 +309,16 @@ void WorkspaceController::add_keyword_item(const eng::Keyword* k)
}
}
+void WorkspaceController::remove_folder_item(eng::library_id_t id)
+{
+ auto iter = m_folderidmap.find(id);
+ if (iter == m_folderidmap.end()) {
+ return;
+ }
+ m_treestore->erase(iter->second);
+ m_folderidmap.erase(iter);
+}
+
void WorkspaceController::add_folder_item(const eng::LibFolder* f)
{
int icon_idx = ICON_ROLL;
@@ -368,6 +412,15 @@ Gtk::Widget * WorkspaceController::buildWidget()
sigc::mem_fun(*this,
&WorkspaceController::action_new_folder),
section, _("New Folder..."), "workspace");
+ auto action = fwk::add_action(m_action_group, "DeleteFolder",
+ sigc::mem_fun(*this,
+ &WorkspaceController::action_delete_folder),
+ section, _("Delete Folder"), "workspace");
+ action->set_enabled(false);
+
+ section = Gio::Menu::create();
+ menu->append_section(section);
+
fwk::add_action(m_action_group, "Import",
sigc::mem_fun(*this,
&WorkspaceController::action_file_import),
diff --git a/src/niepce/ui/workspacecontroller.hpp b/src/niepce/ui/workspacecontroller.hpp
index aad58f4..4598503 100644
--- a/src/niepce/ui/workspacecontroller.hpp
+++ b/src/niepce/ui/workspacecontroller.hpp
@@ -84,9 +84,12 @@ public:
virtual Gtk::Widget * buildWidget() override;
private:
+ /** Return the selected folder id. 0 if not a folder or no selection*/
+ eng::library_id_t get_selected_folder_id();
/** action to create a new folder */
void action_new_folder();
+ void action_delete_folder();
/** action to import images */
void action_file_import();
@@ -102,6 +105,8 @@ private:
/** add a folder item to the treeview */
void add_folder_item(const eng::LibFolder* f);
+ /** Remove a folder from the treeview */
+ void remove_folder_item(eng::library_id_t id);
/** add a keyword item to the treeview */
void add_keyword_item(const eng::Keyword* k);
/** add a tree item in the treeview
diff --git a/src/rust_bindings.hpp b/src/rust_bindings.hpp
index c6de18b..ac5bb66 100644
--- a/src/rust_bindings.hpp
+++ b/src/rust_bindings.hpp
@@ -69,6 +69,7 @@ typedef ffi::FolderVirtualType FolderVirtualType;
namespace ui {
using ffi::dialog_request_new_folder;
+ using ffi::dialog_confirm;
}
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]