[niepce: 23/29] rust: now use library in Rust
- From: Hubert Figuière <hub src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [niepce: 23/29] rust: now use library in Rust
- Date: Fri, 22 Sep 2017 00:43:39 +0000 (UTC)
commit 4d36f02a75206bcfa60bd421683ce9e4f3895da8
Author: Hubert Figuière <hub figuiere net>
Date: Mon Sep 11 00:02:43 2017 -0400
rust: now use library in Rust
- remove sqlite C++ code
- add more bindings
- lib notifications are now in Rust
.gitignore | 4 -
Cargo.toml | 3 +-
build.rs | 44 +-
camerawire/src/Makefile.am | 2 +
configure.ac | 2 -
src/engine/Makefile.am | 20 +-
src/engine/db/bindings.hpp | 7 +
src/engine/db/filebundle.rs | 34 +
src/engine/db/label.cpp | 38 +
src/engine/db/label.hpp | 54 +-
src/engine/db/label.rs | 37 +
src/engine/db/libfile.cpp | 63 +-
src/engine/db/libfile.hpp | 50 +-
src/engine/db/libfile.rs | 24 +-
src/engine/db/libfolder.cpp | 33 +-
src/engine/db/libfolder.hpp | 27 +-
src/engine/db/libfolder.rs | 1 +
src/engine/db/libmetadata.cpp | 282 +++-----
src/engine/db/libmetadata.hpp | 56 +-
src/engine/db/libmetadata.rs | 182 +++++
src/engine/db/library.cpp | 996 +------------------------
src/engine/db/library.hpp | 200 +-----
src/engine/db/library.rs | 295 +++++++-
src/engine/db/mod.rs | 1 +
src/engine/db/properties-def.hpp | 2 +-
src/engine/db/test_library.cpp | 109 ---
src/engine/importer/cameraimporter.cpp | 2 +
src/engine/library/commands.cpp | 226 ------
src/engine/library/commands.hpp | 75 +--
src/engine/library/commands.rs | 239 ++++++
src/engine/library/mod.rs | 4 +
src/engine/library/notification.cpp | 52 +-
src/engine/library/notification.hpp | 231 ++----
src/engine/library/notification.rs | 203 +++++
src/engine/library/op.cpp | 4 +-
src/engine/library/op.hpp | 10 +-
src/engine/library/test_opqueue.cpp | 2 +-
src/engine/library/thumbnailcache.cpp | 4 +-
src/engine/library/thumbnailcache.hpp | 2 +-
src/engine/mod.rs | 2 +-
src/fwk/base/colour.cpp | 73 +-
src/fwk/base/colour.hpp | 35 +-
src/fwk/base/date.cpp | 29 +-
src/fwk/base/date.hpp | 32 +-
src/fwk/base/date.rs | 11 +
src/fwk/base/propertybag.cpp | 36 +
src/fwk/base/propertybag.hpp | 43 +-
src/fwk/base/rgbcolour.rs | 65 ++-
src/fwk/base/rust.hpp | 12 +
src/fwk/base/t/testpropertybag.cpp | 2 +-
src/fwk/toolkit/gdkutils.cpp | 9 +-
src/fwk/toolkit/gdkutils.hpp | 2 +-
src/fwk/toolkit/metadatawidget.cpp | 10 +-
src/fwk/utils/Makefile.am | 32 +-
src/fwk/utils/db/Makefile.am | 3 -
src/fwk/utils/db/iconnectiondriver.hpp | 122 ---
src/fwk/utils/db/iconnectionmanagerdriver.hpp | 106 ---
src/fwk/utils/db/insertstatement.cpp | 115 ---
src/fwk/utils/db/insertstatement.hpp | 61 --
src/fwk/utils/db/sqlite/Makefile.am | 4 -
src/fwk/utils/db/sqlite/sqlitecnxdrv.cpp | 587 ---------------
src/fwk/utils/db/sqlite/sqlitecnxdrv.hpp | 113 ---
src/fwk/utils/db/sqlite/sqlitecnxmgrdrv.cpp | 156 ----
src/fwk/utils/db/sqlite/sqlitecnxmgrdrv.hpp | 60 --
src/fwk/utils/db/sqlstatement.cpp | 133 ----
src/fwk/utils/db/sqlstatement.hpp | 138 ----
src/fwk/utils/db/test_db.cpp | 56 --
src/fwk/utils/db/test_db2.cpp | 58 --
src/fwk/utils/db/test_db3.cpp | 83 --
src/fwk/utils/db/test_db4.cpp | 62 --
src/fwk/utils/exempi.cpp | 224 +------
src/fwk/utils/exempi.hpp | 65 +--
src/fwk/utils/exempi.rs | 59 ++-
src/fwk/utils/files.cpp | 16 +
src/fwk/utils/files.hpp | 27 +-
src/lib.rs | 8 +
src/libraryclient/Makefile.am | 3 +-
src/libraryclient/clientimpl.cpp | 67 +-
src/libraryclient/clientimpl.hpp | 2 +-
src/libraryclient/locallibraryserver.cpp | 3 +-
src/libraryclient/locallibraryserver.hpp | 20 +-
src/libraryclient/test_worker.cpp | 4 +-
src/libraryclient/uidataprovider.cpp | 28 +-
src/libraryclient/uidataprovider.hpp | 15 +-
src/niepce/Makefile.am | 1 +
src/niepce/main.cpp | 2 +-
src/niepce/modules/map/mapmodule.cpp | 10 +-
src/niepce/notificationcenter.cpp | 8 +-
src/niepce/notificationcenter.hpp | 1 +
src/niepce/ui/dialogs/editlabels.cpp | 15 +-
src/niepce/ui/dialogs/editlabels.hpp | 2 +-
src/niepce/ui/gridviewmodule.cpp | 22 +-
src/niepce/ui/imageliststore.cpp | 48 +-
src/niepce/ui/imageliststore.hpp | 1 +
src/niepce/ui/librarycellrenderer.cpp | 2 +-
src/niepce/ui/metadatapanecontroller.cpp | 4 +-
src/niepce/ui/metadatapanecontroller.hpp | 2 +-
src/niepce/ui/niepcewindow.cpp | 46 +-
src/niepce/ui/niepcewindow.hpp | 1 +
src/niepce/ui/selectioncontroller.cpp | 4 +-
src/niepce/ui/workspacecontroller.cpp | 75 +--
src/niepce/ui/workspacecontroller.hpp | 4 +-
102 files changed, 2015 insertions(+), 4644 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 7baae6b..6861622 100644
--- a/.gitignore
+++ b/.gitignore
@@ -83,10 +83,6 @@ src/fwk/base/testdate
src/fwk/base/testmap
src/fwk/base/testoption
src/fwk/base/testpropertybag
-src/fwk/utils/test_db
-src/fwk/utils/test_db2
-src/fwk/utils/test_db3
-src/fwk/utils/test_db4
src/fwk/utils/testfiles
src/fwk/utils/testpathutils
src/fwk/utils/teststringutils
diff --git a/Cargo.toml b/Cargo.toml
index e4aee8a..3892f64 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,8 +13,7 @@ gio = "0.2.0"
#gphoto = "0.1.1"
[build-dependencies]
-# We need git master as currently it the crate version fail on shared_ptr<>
-bindgen = { git = "https://github.com/servo/rust-bindgen.git" }
+bindgen = "0.30.0"
pkg-config = "0.3.9"
[lib]
diff --git a/build.rs b/build.rs
index 1e1d139..6bd2964 100644
--- a/build.rs
+++ b/build.rs
@@ -1,27 +1,61 @@
extern crate bindgen;
+extern crate pkg_config;
use std::env;
use std::path::PathBuf;
fn main() {
+ let exempi = pkg_config::Config::new()
+ .print_system_libs(false)
+ .probe("exempi-2.0")
+ .unwrap();
// The bindgen::Builder is the main entry point
// to bindgen, and lets you build up options for
// the resulting bindings.
- let builder = bindgen::Builder::default()
- // Do not generate unstable Rust code that
- // requires a nightly rustc and enabling
- // unstable features.
- .no_unstable_rust()
+ let mut builder = bindgen::Builder::default()
.enable_cxx_namespaces()
.generate_comments(false)
+ .generate_inline_functions(true)
// The input header we would like to generate
// bindings for.
.whitelisted_type("eng::NiepceProperties")
+ .whitelisted_type("eng::LibFileType")
+ .whitelisted_type("eng::LibNotificationType")
+ .whitelisted_type("eng::LnFileMove")
+ .whitelisted_type("eng::LnFolderCount")
+ .whitelisted_type("eng::QueriedContent")
+ .opaque_type("eng::QueriedContent")
+ .whitelisted_type("eng::metadata_desc_t")
+ .whitelisted_type("eng::LibraryManaged")
+ .whitelisted_type("fwk::FileList")
+ // PropertyValue is complicated
+ .whitelisted_type("fwk::PropertyValue")
+ .opaque_type("fwk::PropertyValue")
+ .whitelisted_type("fwk::StringArray")
+ .opaque_type("fwk::StringArray")
+ .whitelisted_function("fwk::is_empty")
+ .whitelisted_function("fwk::is_integer")
+ .whitelisted_function("fwk::is_string")
+ .whitelisted_function("fwk::is_string_array")
+ .whitelisted_function("fwk::is_date")
+ .whitelisted_function("fwk::get_integer")
+ .whitelisted_function("fwk::get_date")
+ .whitelisted_function("fwk::get_string_cstr")
+ .whitelisted_function("fwk::get_string_array")
+ .whitelisted_function("fwk::string_array_len")
+ .whitelisted_function("fwk::string_array_at_cstr")
+ .whitelisted_type("eng::IndexToXmp")
+ .whitelisted_function("eng::property_index_to_xmp")
.header("src/engine/db/bindings.hpp")
.clang_arg("--std=c++11")
.clang_arg("-DRUST_BINDGEN=1")
.clang_arg("-I./src");
+ for include in exempi.include_paths.into_iter().map(|path| {
+ format!("-I{}", path.to_str().unwrap_or("."))
+ }) {
+ builder = builder.clang_arg(include);
+ }
// Finish the builder and generate the bindings.
let bindings = builder.generate()
diff --git a/camerawire/src/Makefile.am b/camerawire/src/Makefile.am
index b414207..a5020f2 100644
--- a/camerawire/src/Makefile.am
+++ b/camerawire/src/Makefile.am
@@ -17,7 +17,9 @@ camerawire_LDADD = \
$(top_builddir)/src/fwk/toolkit/libniepceframework.a \
$(top_builddir)/src/fwk/utils/libniepceutils.a \
$(top_builddir)/src/fwk/base/libfwkbase.a \
+ $(top_builddir)/target/debug/libniepce_rust.a \
@FRAMEWORK_LIBS@ \
@GPHOTO_LIBS@ \
@OPENRAW_LIBS@ \
+ -ldl \
$(NULL)
diff --git a/configure.ac b/configure.ac
index 368f4aa..9bb42bb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -180,8 +180,6 @@ src/ext/libview/Makefile
src/fwk/Makefile
src/fwk/base/Makefile
src/fwk/utils/Makefile
-src/fwk/utils/db/Makefile
-src/fwk/utils/db/sqlite/Makefile
src/fwk/toolkit/Makefile
src/engine/Makefile
src/libraryclient/Makefile
diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am
index 2824724..f3e0da0 100644
--- a/src/engine/Makefile.am
+++ b/src/engine/Makefile.am
@@ -4,11 +4,12 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/ @FRAMEWORK_CFLAGS@ \
@GPHOTO_CFLAGS@ \
$(NULL)
-TESTS = test_library test_filebundle test_opqueue
+TESTS = test_filebundle test_opqueue
TEST_LIBS = \
libniepceengine.a \
$(top_builddir)/target/debug/libniepce_rust.a \
+ libniepceengineglue.a \
$(top_builddir)/src/fwk/utils/libniepceutils.a \
$(top_builddir)/src/fwk/toolkit/libniepceframework.a \
$(top_builddir)/src/fwk/base/libfwkbase.a \
@@ -19,10 +20,7 @@ TEST_LIBS = \
$(NULL)
-check_PROGRAMS = test_library test_filebundle test_opqueue
-
-test_library_SOURCES = db/test_library.cpp
-test_library_LDADD = $(TEST_LIBS)
+check_PROGRAMS = test_filebundle test_opqueue
test_filebundle_SOURCES = db/test_filebundle.cpp
test_filebundle_LDADD = $(TEST_LIBS)
@@ -30,14 +28,14 @@ test_filebundle_LDADD = $(TEST_LIBS)
test_opqueue_SOURCES = library/test_opqueue.cpp library/opqueue.hpp
test_opqueue_LDADD = $(TEST_LIBS)
-noinst_LIBRARIES = libniepceengine.a
+noinst_LIBRARIES = libniepceengine.a libniepceengineglue.a
libniepceengine_a_SOURCES = \
db/library.hpp db/library.cpp \
db/librarytypes.hpp \
db/libfile.hpp db/libfile.cpp \
db/libfolder.hpp db/libfolder.cpp \
- db/label.hpp \
+ db/label.hpp db/label.cpp \
db/libmetadata.hpp db/libmetadata.cpp \
db/keyword.hpp db/keyword.cpp \
db/storage.hpp \
@@ -47,9 +45,8 @@ libniepceengine_a_SOURCES = \
db/properties.hpp db/properties.cpp \
db/properties-def.hpp \
library/clienttypes.hpp \
- library/notification.hpp library/notification.cpp \
library/op.hpp library/op.cpp \
- library/commands.hpp library/commands.cpp \
+ library/commands.hpp \
library/thumbnailcache.hpp library/thumbnailcache.cpp \
library/thumbnailnotification.hpp \
importer/iimporter.hpp \
@@ -60,3 +57,8 @@ libniepceengine_a_SOURCES = \
importer/importedfile.hpp \
importer/importedfile.cpp \
$(NULL)
+
+# glue code called from Rust. Library order issue.
+libniepceengineglue_a_SOURCES = \
+ library/notification.hpp library/notification.cpp \
+ $(NULL)
diff --git a/src/engine/db/bindings.hpp b/src/engine/db/bindings.hpp
index 1d234bc..d1db23f 100644
--- a/src/engine/db/bindings.hpp
+++ b/src/engine/db/bindings.hpp
@@ -1,3 +1,10 @@
/** @brief what to generate bindings for in Rust */
#include "properties-enum.hpp"
+
+#include "engine/db/libmetadata.hpp"
+#include "engine/db/library.hpp"
+#include "engine/library/clienttypes.hpp"
+#include "engine/library/notification.hpp"
+#include "fwk/base/propertybag.hpp"
+#include "fwk/utils/files.hpp"
diff --git a/src/engine/db/filebundle.rs b/src/engine/db/filebundle.rs
index f63808c..e7e7528 100644
--- a/src/engine/db/filebundle.rs
+++ b/src/engine/db/filebundle.rs
@@ -20,9 +20,12 @@
use libc::c_char;
use std::ffi::CStr;
use std::ffi::CString;
+use std::ffi::OsString;
+use std::path::Path;
use super::libfile::FileType;
use fwk::MimeType;
+use root::fwk::FileList;
pub struct FileBundle {
file_type: FileType,
@@ -48,6 +51,37 @@ impl FileBundle {
}
}
+ pub fn filter_bundles(files: &mut FileList) -> Vec<FileBundle> {
+ let mut bundles: Vec<FileBundle> = vec!();
+ unsafe { files.sort(); }
+ let len = unsafe { files.size() };
+ let mut current_base = OsString::new();
+ let mut current_bundle: Option<FileBundle> = None;
+
+ for i in 0..len {
+ let f = unsafe { files.at_cstr(i) };
+ let cstr = unsafe { CStr::from_ptr(f) }.to_string_lossy();
+ let path = Path::new(&*cstr);
+ if let Some(basename) = path.file_stem() {
+ if basename == current_base {
+ current_bundle.as_mut().unwrap().add(&basename.to_string_lossy());
+ } else {
+ if current_bundle.is_some() {
+ bundles.push(current_bundle.unwrap());
+ }
+ let mut bundle = FileBundle::new();
+ bundle.add(&cstr);
+ current_base = basename.to_os_string();
+ current_bundle = Some(bundle);
+ }
+ }
+ }
+ if current_bundle.is_some() {
+ bundles.push(current_bundle.unwrap());
+ }
+ bundles
+ }
+
pub fn add(&mut self, path: &str) -> bool {
dbg_out!("path {}", path);
let mime_type = MimeType::new(path);
diff --git a/src/engine/db/label.cpp b/src/engine/db/label.cpp
new file mode 100644
index 0000000..56d477b
--- /dev/null
+++ b/src/engine/db/label.cpp
@@ -0,0 +1,38 @@
+/*
+ * niepce - engine/db/label.cpp
+ *
+ * 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/>.
+ */
+
+#include "label.hpp"
+
+extern "C" {
+void engine_db_label_delete(eng::Label*);
+eng::Label* engine_db_label_clone(const eng::Label*);
+}
+
+namespace eng {
+
+LabelPtr label_wrap(Label* l)
+{
+ return LabelPtr(l, &engine_db_label_delete);
+}
+
+LabelPtr label_clone(const Label* l)
+{
+ return label_wrap(engine_db_label_clone(l));
+}
+}
diff --git a/src/engine/db/label.hpp b/src/engine/db/label.hpp
index f04ba24..ddbfac2 100644
--- a/src/engine/db/label.hpp
+++ b/src/engine/db/label.hpp
@@ -17,55 +17,35 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#pragma once
-#ifndef __NIEPCE_DB_LABEL_HPP__
-#define __NIEPCE_DB_LABEL_HPP__
-
+#include <memory>
#include <string>
#include <vector>
-#include <memory>
-#include "fwk/base/colour.hpp"
#include "engine/db/librarytypes.hpp"
-namespace eng {
-
-/** represent a label assigned to a library object
- * There shouldn't be much instances of this.
- */
-class Label
-{
-public:
- typedef std::shared_ptr<Label> Ptr;
- typedef std::vector<Ptr> List;
- typedef std::shared_ptr<List> ListPtr;
+namespace fwk {
+class RgbColour;
+}
- Label(library_id_t _id, const std::string & _label, const std::string & _colourstring)
- : m_id(_id), m_label(_label)
- , m_colour(_colourstring)
- {
- }
+namespace eng {
- library_id_t id() const
- { return m_id; }
- const std::string & label()
- { return m_label; }
- void set_label(const std::string & l)
- { m_label = l; }
- const fwk::RgbColour & colour() const
- { return m_colour; }
- void set_colour(const fwk::RgbColour & c)
- { m_colour = c; }
+class Label;
+typedef std::shared_ptr<Label> LabelPtr;
+typedef std::vector<LabelPtr> LabelList;
+typedef std::shared_ptr<LabelList> LabelListPtr;
-private:
- library_id_t m_id;
- std::string m_label;
- fwk::RgbColour m_colour;
-};
+LabelPtr label_wrap(Label*);
+LabelPtr label_clone(const Label*);
+}
+extern "C" {
+eng::library_id_t engine_db_label_id(const eng::Label*);
+const fwk::RgbColour* engine_db_label_colour(const eng::Label*);
+const char* engine_db_label_label(const eng::Label*);
}
-#endif
/*
Local Variables:
mode:c++
diff --git a/src/engine/db/label.rs b/src/engine/db/label.rs
index 0b57103..9a5a435 100644
--- a/src/engine/db/label.rs
+++ b/src/engine/db/label.rs
@@ -17,6 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+use libc::c_char;
+use std::ffi::CString;
use std::str::FromStr;
use rusqlite;
@@ -24,9 +26,11 @@ use super::LibraryId;
use super::FromDb;
use fwk::base::rgbcolour::RgbColour;
+#[derive(Clone)]
pub struct Label {
id: LibraryId,
label: String,
+ pub cstr: CString,
colour: RgbColour,
}
@@ -37,6 +41,7 @@ impl Label {
Label {
id: id,
label: String::from(label),
+ cstr: CString::new("").unwrap(),
colour: colour
}
}
@@ -77,3 +82,35 @@ impl FromDb for Label {
Label::new(row.get(0), &label, &colour)
}
}
+
+
+#[no_mangle]
+pub fn engine_db_label_delete(l: *mut Label) {
+ unsafe { Box::from_raw(l) };
+}
+
+#[no_mangle]
+pub fn engine_db_label_clone(l: &Label) -> *mut Label {
+ Box::into_raw(Box::new(l.clone()))
+}
+
+#[no_mangle]
+pub fn engine_db_label_id(l: &Label) -> LibraryId {
+ l.id()
+}
+
+#[no_mangle]
+pub fn engine_db_label_label(this: &mut Label) -> *const c_char {
+ let cstr;
+ {
+ let s = this.label();
+ cstr = CString::new(s).unwrap();
+ }
+ this.cstr = cstr;
+ this.cstr.as_ptr()
+}
+
+#[no_mangle]
+pub fn engine_db_label_colour(l: &Label) -> *const RgbColour {
+ l.colour()
+}
diff --git a/src/engine/db/libfile.cpp b/src/engine/db/libfile.cpp
index 2c21cf5..206e585 100644
--- a/src/engine/db/libfile.cpp
+++ b/src/engine/db/libfile.cpp
@@ -17,25 +17,47 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-#include "fwk/base/debug.hpp"
#include "libfile.hpp"
+#include "engine/library/notification.hpp"
+#include "fwk/base/debug.hpp"
#include "properties.hpp"
+extern "C" {
+eng::LibFile *engine_db_libfile_new(eng::library_id_t id,
+ eng::library_id_t folder_id,
+ eng::library_id_t fs_file_id,
+ const char *path, const char *name);
+void engine_db_libfile_delete(eng::LibFile *);
+}
-extern "C" eng::LibFile* engine_db_libfile_new(eng::library_id_t id,
- eng::library_id_t folder_id,
- eng::library_id_t fs_file_id,
- const char* path, const char* name);
-extern "C" void engine_db_libfile_delete(eng::LibFile*);
+namespace eng {
+
+// some glue for rust
+QueriedContent::QueriedContent(library_id_t _container)
+ : container(_container)
+ , files(new LibFileList)
+{
+}
+
+void QueriedContent::push(LibFile *f)
+{
+ files->push_back(eng::libfile_wrap(f));
+}
+}
namespace eng {
-LibFilePtr libfile_new(library_id_t id, library_id_t folder_id, library_id_t fs_file_id,
- const char* path, const char* name) {
- return LibFilePtr(
- engine_db_libfile_new(id, folder_id, fs_file_id, path, name),
- &engine_db_libfile_delete);
+LibFilePtr libfile_new(library_id_t id, library_id_t folder_id,
+ library_id_t fs_file_id, const char *path,
+ const char *name)
+{
+ return libfile_wrap(
+ engine_db_libfile_new(id, folder_id, fs_file_id, path, name));
+}
+
+LibFilePtr libfile_wrap(LibFile *lf)
+{
+ return LibFilePtr(lf, &engine_db_libfile_delete);
}
/**
@@ -46,25 +68,16 @@ LibFilePtr libfile_new(library_id_t id, library_id_t folder_id, library_id_t fs_
*/
LibFileType mimetype_to_filetype(fwk::MimeType mime)
{
- if(mime.isDigicamRaw())
- {
+ if (mime.isDigicamRaw()) {
return LibFileType::RAW;
- }
- else if(mime.isImage())
- {
+ } else if (mime.isImage()) {
return LibFileType::IMAGE;
- }
- else if(mime.isMovie())
- {
+ } else if (mime.isMovie()) {
return LibFileType::VIDEO;
- }
- else
- {
+ } else {
return LibFileType::UNKNOWN;
}
}
-
-
}
/*
Local Variables:
diff --git a/src/engine/db/libfile.hpp b/src/engine/db/libfile.hpp
index 00c45a6..17a47ff 100644
--- a/src/engine/db/libfile.hpp
+++ b/src/engine/db/libfile.hpp
@@ -19,14 +19,17 @@
#pragma once
-#include <string>
#include <list>
#include <memory>
+#include <string>
+#if !RUST_BINDGEN
#include "fwk/toolkit/mimetype.hpp"
-#include "fwk/base/propertybag.hpp"
-#include "engine/db/librarytypes.hpp"
+#endif
+
#include "engine/db/keyword.hpp"
+#include "engine/db/librarytypes.hpp"
+#include "fwk/base/propertybag.hpp"
namespace eng {
@@ -38,32 +41,39 @@ enum class LibFileType {
VIDEO = 4
};
+#if !RUST_BINDGEN
LibFileType mimetype_to_filetype(fwk::MimeType mime);
+#endif
class LibFile;
typedef std::shared_ptr<LibFile> LibFilePtr;
-typedef std::weak_ptr< LibFile> LibFileWeakPtr;
+typedef std::weak_ptr<LibFile> LibFileWeakPtr;
typedef std::list<LibFilePtr> LibFileList;
typedef std::shared_ptr<LibFileList> LibFileListPtr;
-LibFilePtr libfile_new(library_id_t, library_id_t, library_id_t, const char*, const char*);
+LibFilePtr libfile_new(library_id_t, library_id_t, library_id_t, const char *,
+ const char *);
+LibFilePtr libfile_wrap(LibFile *);
}
-extern "C" const char* engine_db_libfile_path(const eng::LibFile*);
-extern "C" eng::library_id_t engine_db_libfile_id(const eng::LibFile*);
-extern "C" eng::library_id_t engine_db_libfile_folderid(const eng::LibFile*);
-extern "C" int32_t engine_db_libfile_orientation(const eng::LibFile*);
-extern "C" int32_t engine_db_libfile_rating(const eng::LibFile*);
-extern "C" int32_t engine_db_libfile_label(const eng::LibFile*);
-extern "C" int32_t engine_db_libfile_flag(const eng::LibFile*);
-extern "C" int32_t engine_db_libfile_property(const eng::LibFile*, fwk::PropertyIndex);
-extern "C" eng::LibFileType engine_db_libfile_file_type(const eng::LibFile*);
-extern "C" void engine_db_libfile_set_orientation(eng::LibFile*, int32_t);
-extern "C" void engine_db_libfile_set_rating(eng::LibFile*, int32_t);
-extern "C" void engine_db_libfile_set_label(eng::LibFile*, int32_t);
-extern "C" void engine_db_libfile_set_flag(eng::LibFile*, int32_t);
-extern "C" void engine_db_libfile_set_property(const eng::LibFile*, fwk::PropertyIndex, int32_t);
-extern "C" void engine_db_libfile_set_file_type(eng::LibFile*, eng::LibFileType);
+extern "C" {
+const char *engine_db_libfile_path(const eng::LibFile *);
+eng::library_id_t engine_db_libfile_id(const eng::LibFile *);
+eng::library_id_t engine_db_libfile_folderid(const eng::LibFile *);
+int32_t engine_db_libfile_orientation(const eng::LibFile *);
+int32_t engine_db_libfile_rating(const eng::LibFile *);
+int32_t engine_db_libfile_label(const eng::LibFile *);
+int32_t engine_db_libfile_flag(const eng::LibFile *);
+int32_t engine_db_libfile_property(const eng::LibFile *, fwk::PropertyIndex);
+eng::LibFileType engine_db_libfile_file_type(const eng::LibFile *);
+void engine_db_libfile_set_orientation(eng::LibFile *, int32_t);
+void engine_db_libfile_set_rating(eng::LibFile *, int32_t);
+void engine_db_libfile_set_label(eng::LibFile *, int32_t);
+void engine_db_libfile_set_flag(eng::LibFile *, int32_t);
+void engine_db_libfile_set_property(const eng::LibFile *, fwk::PropertyIndex,
+ int32_t);
+void engine_db_libfile_set_file_type(eng::LibFile *, eng::LibFileType);
+}
/*
Local Variables:
diff --git a/src/engine/db/libfile.rs b/src/engine/db/libfile.rs
index c42a9c7..4b8c899 100644
--- a/src/engine/db/libfile.rs
+++ b/src/engine/db/libfile.rs
@@ -29,19 +29,9 @@ use super::LibraryId;
use super::fsfile::FsFile;
use fwk::base::PropertyIndex;
use root::eng::NiepceProperties as Np;
+pub use root::eng::LibFileType as FileType;
use fwk;
-#[repr(i32)]
-#[allow(non_camel_case_types)]
-#[derive(Clone,PartialEq)]
-pub enum FileType {
- UNKNOWN = 0,
- RAW = 1,
- RAW_JPEG = 2,
- IMAGE = 3,
- VIDEO = 4
-}
-
impl From<i32> for FileType {
fn from(t: i32) -> Self {
match t {
@@ -55,6 +45,18 @@ impl From<i32> for FileType {
}
}
+impl Into<i32> for FileType {
+ fn into(self) -> i32 {
+ match self {
+ FileType::UNKNOWN => 0,
+ FileType::RAW => 1,
+ FileType::RAW_JPEG => 2,
+ FileType::IMAGE => 3,
+ FileType::VIDEO => 4,
+ }
+ }
+}
+
pub struct LibFile {
id: LibraryId,
folder_id: LibraryId,
diff --git a/src/engine/db/libfolder.cpp b/src/engine/db/libfolder.cpp
index 176f60e..76b3cbd 100644
--- a/src/engine/db/libfolder.cpp
+++ b/src/engine/db/libfolder.cpp
@@ -19,38 +19,17 @@
#include "libfolder.hpp"
-extern "C" eng::LibFolder* engine_db_libfolder_new(eng::library_id_t id, const char* name);
-extern "C" void engine_db_libfolder_delete(eng::LibFolder*);
+extern "C" eng::LibFolder *engine_db_libfolder_new(eng::library_id_t id,
+ const char *name);
+extern "C" void engine_db_libfolder_delete(eng::LibFolder *);
namespace eng {
-LibFolderPtr libfolder_new(eng::library_id_t id, const char* name) {
- return LibFolderPtr(
- engine_db_libfolder_new(id, name), &engine_db_libfolder_delete);
-}
-
-const char* libfolder_read_db_columns()
-{
- return "id,name,virtual,locked,expanded";
-}
-
-LibFolderPtr libfolder_read_from(const db::IConnectionDriver::Ptr & db)
+LibFolderPtr libfolder_new(eng::library_id_t id, const char *name)
{
- library_id_t id;
- std::string name;
- int32_t virt_type, locked, expanded;
- db->get_column_content(0, id);
- db->get_column_content(1, name);
- db->get_column_content(2, virt_type);
- db->get_column_content(3, locked);
- db->get_column_content(4, expanded);
- LibFolderPtr f(libfolder_new(id, name.c_str()));
- engine_db_libfolder_set_virtual_type(f.get(), virt_type);
- engine_db_libfolder_set_locked(f.get(), (bool)locked);
- engine_db_libfolder_set_expanded(f.get(), (bool)expanded);
- return f;
+ return LibFolderPtr(engine_db_libfolder_new(id, name),
+ &engine_db_libfolder_delete);
}
-
}
/*
Local Variables:
diff --git a/src/engine/db/libfolder.hpp b/src/engine/db/libfolder.hpp
index d654bc3..1e2a4ec 100644
--- a/src/engine/db/libfolder.hpp
+++ b/src/engine/db/libfolder.hpp
@@ -17,15 +17,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
#pragma once
-#include <string>
#include <list>
#include <memory>
+#include <string>
#include "engine/db/librarytypes.hpp"
-#include "fwk/utils/db/iconnectiondriver.hpp"
namespace eng {
class LibFolder;
@@ -40,21 +38,18 @@ enum class LibFolderVirtualType {
_LAST
};
-const char * libfolder_read_db_columns();
-LibFolderPtr libfolder_read_from(const db::IConnectionDriver::Ptr & db);
-
-LibFolderPtr libfolder_new(library_id_t id, const char* name);
-
-extern "C" library_id_t engine_db_libfolder_id(const LibFolder*);
-extern "C" const char* engine_db_libfolder_name(const LibFolder*);
-extern "C" int32_t engine_db_libfolder_virtual_type(const LibFolder*);
-extern "C" bool engine_db_libfolder_expanded(const LibFolder*);
-extern "C" void engine_db_libfolder_set_locked(const LibFolder*, bool);
-extern "C" void engine_db_libfolder_set_expanded(const LibFolder*, bool);
-extern "C" void engine_db_libfolder_set_virtual_type(const LibFolder*, int32_t);
+LibFolderPtr libfolder_new(library_id_t id, const char *name);
+extern "C" {
+library_id_t engine_db_libfolder_id(const LibFolder *);
+const char *engine_db_libfolder_name(const LibFolder *);
+int32_t engine_db_libfolder_virtual_type(const LibFolder *);
+bool engine_db_libfolder_expanded(const LibFolder *);
+void engine_db_libfolder_set_locked(const LibFolder *, bool);
+void engine_db_libfolder_set_expanded(const LibFolder *, bool);
+void engine_db_libfolder_set_virtual_type(const LibFolder *, int32_t);
+}
}
-
/*
Local Variables:
diff --git a/src/engine/db/libfolder.rs b/src/engine/db/libfolder.rs
index 824bef2..d87b7ae 100644
--- a/src/engine/db/libfolder.rs
+++ b/src/engine/db/libfolder.rs
@@ -42,6 +42,7 @@ impl From<i32> for VirtualType {
}
}
+#[derive(Clone)]
pub struct LibFolder {
id: LibraryId,
name: String,
diff --git a/src/engine/db/libmetadata.cpp b/src/engine/db/libmetadata.cpp
index 7728012..9075ae1 100644
--- a/src/engine/db/libmetadata.cpp
+++ b/src/engine/db/libmetadata.cpp
@@ -1,7 +1,7 @@
/*
* niepce - db/libmetadata.cpp
*
- * Copyright (C) 2008-2013 Hubert Figuiere
+ * Copyright (C) 2008-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
@@ -17,156 +17,83 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <string.h>
-#include <time.h>
#include <exempi/xmpconsts.h>
#include <exempi/xmperrors.h>
+#include <string.h>
+#include <time.h>
+#include "fwk/base/date.hpp"
#include "fwk/base/debug.hpp"
+#include "fwk/base/rust.hpp"
+#include "fwk/utils/exempi.hpp"
#include "fwk/utils/stringutils.hpp"
#include "libmetadata.hpp"
#include "properties.hpp"
namespace eng {
-typedef std::map<fwk::PropertyIndex, std::pair<const char*, const char *> > PropsToXmpMap;
+typedef std::map<fwk::PropertyIndex, std::pair<const char *, const char *>>
+ PropsToXmpMap;
/** get the mapping of properties to XMP */
-const PropsToXmpMap & props_to_xmp_map();
+const PropsToXmpMap &props_to_xmp_map();
-
-const PropsToXmpMap & props_to_xmp_map()
+const PropsToXmpMap &props_to_xmp_map()
{
static PropsToXmpMap s_props_map;
- if(s_props_map.empty()) {
+ if (s_props_map.empty()) {
-#define DEFINE_PROPERTY(a,b,c,d,e) \
- s_props_map.insert(std::make_pair(b, std::make_pair(c,d)));
+#define DEFINE_PROPERTY(a, b, c, d, e) \
+ s_props_map.insert(std::make_pair(b, std::make_pair(c, d)));
#include "engine/db/properties-def.hpp"
#undef DEFINE_PROPERTY
-
}
return s_props_map;
}
-bool
-LibMetadata::property_index_to_xmp(fwk::PropertyIndex index,
- const char * & ns, const char * & property)
+IndexToXmp property_index_to_xmp(fwk::PropertyIndex index)
{
- const PropsToXmpMap & propmap = props_to_xmp_map();
+ const PropsToXmpMap &propmap = props_to_xmp_map();
PropsToXmpMap::const_iterator iter = propmap.find(index);
- if(iter == propmap.end()) {
+ if (iter == propmap.end()) {
// not found
- return false;
+ return {ns : nullptr, property : nullptr};
}
- if(iter->second.first == NULL || iter->second.second == NULL) {
+ if (iter->second.first == NULL || iter->second.second == NULL) {
// no XMP equivalent
- return false;
+ return {ns : nullptr, property : nullptr};
}
- ns = iter->second.first;
- property = iter->second.second;
- return true;
+ return {ns : iter->second.first, property : iter->second.second};
}
-
-
-LibMetadata::LibMetadata(library_id_t _id)
- : XmpMeta(),
- m_id(_id)
+bool get_meta_data(const LibMetadata *meta, fwk::PropertyIndex p,
+ fwk::PropertyValue &value)
{
-}
-
-
-bool LibMetadata::setMetaData(fwk::PropertyIndex meta,
- const fwk::PropertyValue & value)
-{
- const char * ns = NULL;
- const char * property = NULL;
- bool result = false;
-
- result = property_index_to_xmp(meta, ns, property);
- if(result) {
-
- if(fwk::is_empty(value)) {
- result = xmp_delete_property(xmp(), ns, property);
- }
- else if(fwk::is_integer(value)) {
- result = xmp_set_property_int32(xmp(), ns, property,
- fwk::get_integer(value), 0);
- }
- else if(value.type() == typeid(std::string)) {
- std::string val = boost::get<std::string>(value);
- if (val.empty()) {
- result = xmp_delete_property(xmp(), ns, property);
- }
- else {
- result = xmp_set_property(xmp(), ns, property, val.c_str(), 0);
- // FIXME we should know in advance it is localized.
- if(!result && (xmp_get_error() == XMPErr_BadXPath)) {
- result = xmp_set_localized_text(xmp(), ns, property,
- "", "x-default",
- val.c_str(), 0);
- }
- }
- }
- else if(value.type() == typeid(fwk::StringArray)) {
- fwk::StringArray v = boost::get<fwk::StringArray>(value);
- // TODO see if we can get that without deleting the whole property
- result = xmp_delete_property(xmp(), ns, property);
- std::for_each(v.begin(), v.end(),
- [this, ns, property] (const std::string & val) {
- /*result =*/
- xmp_append_array_item(this->xmp(),
- ns, property,
- XMP_PROP_VALUE_IS_ARRAY,
- val.c_str(), 0);
- });
- }
- else if(value.type() == typeid(fwk::Date)) {
- fwk::Date d = boost::get<fwk::Date>(value);
-
- result = xmp_set_property_date(xmp(), ns, property,
- &d.xmp_date(), 0);
-
- }
- if(!result) {
- ERR_OUT("error setting property %s:%s %d", ns, property,
- xmp_get_error());
- }
- }
- else {
- ERR_OUT("unknown property");
- }
- return result;
-}
-
-
-bool LibMetadata::getMetaData(fwk::PropertyIndex p,
- fwk::PropertyValue & value) const
-{
- const PropsToXmpMap & propmap = props_to_xmp_map();
+ const PropsToXmpMap &propmap = props_to_xmp_map();
PropsToXmpMap::const_iterator iter = propmap.find(p);
- if(iter == propmap.end()) {
+ if (iter == propmap.end()) {
// not found
return false;
}
- if(iter->second.first == NULL || iter->second.second == NULL) {
+ if (iter->second.first == NULL || iter->second.second == NULL) {
// no XMP equivalent
return false;
}
xmp::ScopedPtr<XmpStringPtr> xmp_value(xmp_string_new());
uint32_t prop_bits = 0;
- const char * ns = iter->second.first;
- const char * xmp_prop = iter->second.second;
- bool found = xmp_get_property(xmp(), ns, xmp_prop, xmp_value, &prop_bits);
- if(found && XMP_IS_ARRAY_ALTTEXT(prop_bits)) {
- found = xmp_get_localized_text(xmp(), ns, xmp_prop, "", "x-default",
- NULL, xmp_value, NULL);
+ const char *ns = iter->second.first;
+ const char *xmp_prop = iter->second.second;
+ bool found = xmp_get_property(engine_libmetadata_get_xmp(meta), ns,
+ xmp_prop, xmp_value, &prop_bits);
+ if (found && XMP_IS_ARRAY_ALTTEXT(prop_bits)) {
+ found = xmp_get_localized_text(engine_libmetadata_get_xmp(meta), ns,
+ xmp_prop, "", "x-default", nullptr,
+ xmp_value, nullptr);
}
- if(found) {
- const char * v = NULL;
+ if (found) {
+ const char *v = NULL;
v = xmp_string_cstr(xmp_value);
- if(v) {
+ if (v) {
value = fwk::PropertyValue(v);
return true;
}
@@ -175,84 +102,69 @@ bool LibMetadata::getMetaData(fwk::PropertyIndex p,
return false;
}
-void LibMetadata::to_properties(const fwk::PropertySet & propset,
- fwk::PropertyBag & props)
-{
- std::for_each(propset.begin(), propset.end(),
- [&props, this] (fwk::PropertySet::key_type prop_id) {
- switch(prop_id) {
- case NpXmpRatingProp:
- props.set_value_for_property(prop_id,
- fwk::PropertyValue(rating()));
- break;
- case NpXmpLabelProp:
- props.set_value_for_property(prop_id,
- fwk::PropertyValue(label()));
- break;
- case NpTiffOrientationProp:
- props.set_value_for_property(prop_id,
- fwk::PropertyValue(orientation()));
- break;
- case NpExifDateTimeOriginalProp:
- props.set_value_for_property(prop_id,
- fwk::PropertyValue(creation_date()));
- break;
- case NpIptcKeywordsProp:
- {
- xmp::ScopedPtr<XmpIteratorPtr>
- iter(xmp_iterator_new(xmp(), NS_DC,
- "subject", XMP_ITER_JUSTLEAFNODES));
- fwk::StringArray vec;
- xmp::ScopedPtr<XmpStringPtr> value(xmp_string_new());
- while(xmp_iterator_next(iter, NULL, NULL, value, NULL)) {
- vec.push_back(xmp_string_cstr(value));
- }
- fwk::PropertyValue v(vec);
- //DBG_ASSERT(check_property_type(prop_id, v.type()), "wrong type");
- props.set_value_for_property(prop_id, v);
- break;
- }
- default:
- {
- fwk::PropertyValue propval;
- if(getMetaData(prop_id, propval)) {
- //DBG_ASSERT(check_property_type(prop_id, propval.type()), "wrong type");
- props.set_value_for_property(prop_id, propval);
- }
- else {
- DBG_OUT("missing prop %u", prop_id);
- }
- break;
- }
- }
- }
- );
-}
-
-
-bool LibMetadata::touch()
+void libmetadata_to_properties(const LibMetadata *meta,
+ const fwk::PropertySet &propset,
+ fwk::PropertyBag &props)
{
- bool result = false;
- XmpDateTime date;
- struct tm dt, *dt2;
- time_t currenttime = time(NULL);
- dt2 = gmtime_r(¤ttime, &dt);
- if(dt2 == &dt) {
- memset(&date, 0, sizeof date);
- date.second = dt.tm_sec;
- date.minute = dt.tm_min;
- date.hour = dt.tm_hour;
- date.day = dt.tm_mday;
- date.month = dt.tm_mon;
- date.year = dt.tm_year + 1900;
-
- result = xmp_set_property_date(xmp(), NS_XAP, "MetadataDate",
- &date, 0);
- }
- return result;
+ std::for_each(
+ propset.begin(), propset.end(),
+ [&props, meta](fwk::PropertySet::key_type prop_id) {
+ auto xmpmeta = engine_libmetadata_get_xmpmeta(meta);
+ switch (prop_id) {
+ case NpXmpRatingProp:
+ props.set_value_for_property(
+ prop_id,
+ fwk::PropertyValue(fwk_xmp_meta_get_rating(xmpmeta)));
+ break;
+ case NpXmpLabelProp: {
+ char *str = fwk_xmp_meta_get_label(xmpmeta);
+ if (str) {
+ props.set_value_for_property(prop_id,
+ fwk::PropertyValue(str));
+ rust_cstring_delete(str);
+ }
+ break;
+ }
+ case NpTiffOrientationProp:
+ props.set_value_for_property(
+ prop_id,
+ fwk::PropertyValue(fwk_xmp_meta_get_orientation(xmpmeta)));
+ break;
+ case NpExifDateTimeOriginalProp: {
+ fwk::DatePtr date =
+ fwk::date_wrap(fwk_xmp_meta_get_creation_date(xmpmeta));
+ props.set_value_for_property(prop_id, fwk::PropertyValue(date));
+ break;
+ }
+ case NpIptcKeywordsProp: {
+ xmp::ScopedPtr<XmpIteratorPtr> iter(
+ xmp_iterator_new(engine_libmetadata_get_xmp(meta), NS_DC,
+ "subject", XMP_ITER_JUSTLEAFNODES));
+ fwk::StringArray vec;
+ xmp::ScopedPtr<XmpStringPtr> value(xmp_string_new());
+ while (xmp_iterator_next(iter, NULL, NULL, value, NULL)) {
+ vec.push_back(xmp_string_cstr(value));
+ }
+ fwk::PropertyValue v(vec);
+ // DBG_ASSERT(check_property_type(prop_id, v.type()), "wrong
+ // type");
+ props.set_value_for_property(prop_id, v);
+ break;
+ }
+ default: {
+ fwk::PropertyValue propval;
+ if (get_meta_data(meta, prop_id, propval)) {
+ // DBG_ASSERT(check_property_type(prop_id, propval.type()),
+ // "wrong type");
+ props.set_value_for_property(prop_id, propval);
+ } else {
+ DBG_OUT("missing prop %u", prop_id);
+ }
+ break;
+ }
+ }
+ });
}
-
-
}
/*
diff --git a/src/engine/db/libmetadata.hpp b/src/engine/db/libmetadata.hpp
index 680236c..5fd15aa 100644
--- a/src/engine/db/libmetadata.hpp
+++ b/src/engine/db/libmetadata.hpp
@@ -1,7 +1,7 @@
/*
* niepce - eng/db/libmetadata.hpp
*
- * Copyright (C) 2008-2013 Hubert Figuiere
+ * Copyright (C) 2008-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
@@ -17,57 +17,39 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __DB_LIBMETADATA_H_
-#define __DB_LIBMETADATA_H_
+#pragma once
-#include <vector>
-#include <string>
#include <memory>
+#include <string>
+#include <vector>
#include <boost/any.hpp>
-#include "fwk/base/propertybag.hpp"
-#include "fwk/utils/exempi.hpp"
#include "engine/db/librarytypes.hpp"
#include "engine/db/metadata.hpp"
+#include "fwk/base/propertybag.hpp"
+#include "fwk/utils/exempi.hpp"
namespace eng {
-class LibMetadata
- : public fwk::XmpMeta
-{
-public:
- typedef std::shared_ptr<LibMetadata> Ptr;
-
- LibMetadata(library_id_t _id);
-
- library_id_t id() const
- { return m_id; }
- bool setMetaData(fwk::PropertyIndex meta, const fwk::PropertyValue & value);
- bool getMetaData(fwk::PropertyIndex meta, fwk::PropertyValue & value) const;
+class LibMetadata;
- /** convert XMP to a set of properties
- * @param propset the property set requested
- * @param props the output properties
- */
- void to_properties(const fwk::PropertySet & propset,
- fwk::PropertyBag & properties);
- /** do like the unix "touch". Update the MetadataDate
- * to the current time, in UTC.
- */
- bool touch();
-private:
- LibMetadata(const LibMetadata &);
+void libmetadata_to_properties(const LibMetadata *meta,
+ const fwk::PropertySet &propset,
+ fwk::PropertyBag &props);
- static bool property_index_to_xmp(fwk::PropertyIndex index,
- const char * & ns, const char * & property);
-
- library_id_t m_id;
+struct IndexToXmp {
+ const char *ns;
+ const char *property;
};
-
+IndexToXmp property_index_to_xmp(fwk::PropertyIndex index);
}
-#endif
+extern "C" {
+eng::library_id_t engine_libmetadata_get_id(const eng::LibMetadata *meta);
+XmpPtr engine_libmetadata_get_xmp(const eng::LibMetadata *meta);
+fwk::XmpMeta *engine_libmetadata_get_xmpmeta(const eng::LibMetadata *meta);
+}
/*
Local Variables:
diff --git a/src/engine/db/libmetadata.rs b/src/engine/db/libmetadata.rs
new file mode 100644
index 0000000..cddbde1
--- /dev/null
+++ b/src/engine/db/libmetadata.rs
@@ -0,0 +1,182 @@
+/*
+ * niepce - eng/db/libmetadata.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 std::ffi::CStr;
+use rusqlite;
+use exempi;
+
+use fwk;
+use fwk::{
+ XmpMeta,
+ make_xmp_date_time
+};
+use fwk::utils::exempi::NS_XAP;
+use super::{
+ FromDb,
+ LibraryId
+};
+use root::eng::NiepceProperties as Np;
+use root::fwk::{
+ is_empty,
+ is_integer,
+ is_string,
+ is_string_array,
+ is_date,
+ get_string_cstr,
+ get_string_array,
+ get_integer,
+ get_date,
+ string_array_len,
+ string_array_at_cstr,
+ PropertyValue
+};
+
+pub struct LibMetadata {
+ xmp: XmpMeta,
+ id: LibraryId
+}
+
+struct IndexToXmp {
+ pub ns: String,
+ pub property: String
+}
+
+fn property_index_to_xmp(meta: Np) -> Option<IndexToXmp> {
+ let index = unsafe { ::root::eng::property_index_to_xmp(meta as u32) };
+ if index.ns.is_null() || index.property.is_null() {
+ err_out!("property {} not found", meta as u32);
+ return None;
+ }
+ Some(IndexToXmp {
+ ns: String::from(unsafe { CStr::from_ptr(index.ns) }.to_string_lossy()),
+ property: String::from(unsafe { CStr::from_ptr(index.property) }.to_string_lossy())
+ })
+}
+
+
+impl LibMetadata {
+
+ pub fn new(id: LibraryId) -> LibMetadata {
+ LibMetadata{
+ xmp: XmpMeta::new(),
+ id: id
+ }
+ }
+
+ pub fn new_with_xmp(id: LibraryId, xmp: XmpMeta) -> LibMetadata {
+ LibMetadata{
+ xmp: xmp,
+ id: id
+ }
+ }
+
+ pub fn serialize_inline(&self) -> String {
+ self.xmp.serialize_inline()
+ }
+
+ pub fn set_metadata(&mut self, meta: Np, value: &PropertyValue) -> bool {
+ if let Some(ix) = property_index_to_xmp(meta) {
+ if unsafe { is_empty(value) } {
+ return self.xmp.xmp.delete_property(&ix.ns, &ix.property);
+ } else if unsafe { is_integer(value) } {
+ return self.xmp.xmp.set_property_i32(
+ &ix.ns, &ix.property, unsafe { get_integer(value) }, exempi::PROP_NONE);
+ } else if unsafe { is_string(value) } {
+ let cstr = unsafe { CStr::from_ptr(get_string_cstr(value)) };
+ if cstr.to_bytes().len() == 0 {
+ return self.xmp.xmp.delete_property(&ix.ns, &ix.property);
+ } else if !self.xmp.xmp.set_property(
+ &ix.ns, &ix.property, &*cstr.to_string_lossy(), exempi::PROP_NONE) {
+ if exempi::get_error() == exempi::Error::BadXPath {
+ return self.xmp.xmp.set_localized_text(
+ &ix.ns, &ix.property, "", "x-default",
+ &*cstr.to_string_lossy(), exempi::PROP_NONE);
+ }
+ } else {
+ return true;
+ }
+ } else if unsafe { is_string_array(value) } {
+ self.xmp.xmp.delete_property(&ix.ns, &ix.property);
+ let a = unsafe { get_string_array(value) };
+ let count = unsafe { string_array_len(a) };
+ for i in 0..count {
+ let cstr = unsafe { CStr::from_ptr(string_array_at_cstr(a, i)) };
+ self.xmp.xmp.append_array_item(&ix.ns, &ix.property,
+ exempi::ARRAY_NONE,
+ &*cstr.to_string_lossy(),
+ exempi::ITEM_NONE);
+ }
+ return true;
+ } else if unsafe { is_date(value) } {
+ let d = unsafe { get_date(value) } as *const fwk::Date;
+ return self.xmp.xmp.set_property_date(
+ &ix.ns, &ix.property, unsafe { &(*d) }.xmp_date(), exempi::PROP_NONE);
+ }
+ err_out!("error setting property {}:{} {}", ix.ns, ix.property,
+ exempi::get_error() as u32);
+ }
+ err_out!("Unknown property {:?}", meta);
+ false
+ }
+
+ pub fn touch(&mut self) -> bool {
+ let mut xmpdate = exempi::DateTime::new();
+ if make_xmp_date_time(fwk::Date::now(), &mut xmpdate) {
+ return self.xmp.xmp.set_property_date(NS_XAP, "MetadataDate",
+ &xmpdate, exempi::PROP_NONE);
+ }
+ false
+ }
+}
+
+impl FromDb for LibMetadata {
+
+ fn read_db_columns() -> &'static str {
+ "id,xmp"
+ }
+
+ fn read_db_tables() -> &'static str {
+ "files"
+ }
+
+ fn read_from(row: &rusqlite::Row) -> Self {
+ let id: LibraryId = row.get(0);
+ let xmp: String = row.get(1);
+
+ let mut xmpmeta = XmpMeta::new();
+ xmpmeta.unserialize(&xmp);
+ LibMetadata::new_with_xmp(id, xmpmeta)
+ }
+
+}
+
+#[no_mangle]
+pub fn engine_libmetadata_get_id(meta: &LibMetadata) -> LibraryId {
+ return meta.id;
+}
+
+#[no_mangle]
+pub fn engine_libmetadata_get_xmp(meta: &LibMetadata) -> exempi::Xmp {
+ return meta.xmp.xmp.clone();
+}
+
+#[no_mangle]
+pub fn engine_libmetadata_get_xmpmeta(meta: &LibMetadata) -> *const XmpMeta {
+ return &meta.xmp;
+}
diff --git a/src/engine/db/library.cpp b/src/engine/db/library.cpp
index 0c1e6fc..50e1583 100644
--- a/src/engine/db/library.cpp
+++ b/src/engine/db/library.cpp
@@ -17,1003 +17,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <time.h>
-#include <stdio.h>
-
-#include <iostream>
-
-#include <boost/format.hpp>
-
-#include <glibmm/i18n.h>
-
-#include "fwk/base/colour.hpp"
-#include "niepce/notifications.hpp"
#include "library.hpp"
-#include "metadata.hpp"
-#include "properties.hpp"
-#include "fwk/base/debug.hpp"
-#include "fwk/utils/exception.hpp"
-#include "fwk/utils/exempi.hpp"
-#include "fwk/utils/pathutils.hpp"
-#include "fwk/utils/db/sqlite/sqlitecnxmgrdrv.hpp"
-#include "fwk/utils/db/sqlite/sqlitecnxdrv.hpp"
-#include "fwk/utils/db/sqlstatement.hpp"
-#include "fwk/toolkit/notificationcenter.hpp"
-#include "fwk/toolkit/mimetype.hpp"
-using ::fwk::NotificationCenter;
-using ::db::SQLStatement;
+extern "C" eng::Library *engine_db_library_new(const char *dir,
+ uint64_t notif_id);
+extern "C" void engine_db_library_delete(eng::Library *);
namespace eng {
-const char * s_databaseName = "niepcelibrary.db";
-
-
-Library::Library(const std::string & dir, uint64_t notif_id)
- : m_maindir(dir),
- m_dbname(m_maindir + "/" + s_databaseName),
- m_dbmgr(new db::sqlite::SqliteCnxMgrDrv()),
- m_notif_id(notif_id),
- m_inited(false)
-{
- DBG_OUT("dir = %s", dir.c_str());
- db::DBDesc desc("", 0, m_dbname);
- try {
- m_dbdrv = m_dbmgr->connect_to_db(desc, "", "");
- m_inited = init();
-
- m_dbdrv->create_function0(
- "rewrite_xmp",
- [this] () {
- DBG_OUT("rewrite_xmp");
- notify(
- LibNotification::make<LibNotification::Type::XMP_NEEDS_UPDATE>({}));
- });
- }
- catch(const std::exception &e)
- {
- ERR_OUT("Exception: %s", e.what());
- }
-}
-
-Library::~Library()
-{
-}
-
-void Library::notify(LibNotification&& ln)
-{
- auto wnc = fwk::NotificationCenter::get_nc(m_notif_id);
- auto nc = wnc.lock();
- if (nc) {
- DBG_OUT("notif");
- // pass the notification
- fwk::Notification::Ptr n(new fwk::Notification(niepce::NOTIFICATION_LIB));
- n->setData(boost::any(ln));
- nc->post(std::move(n));
- }
- else {
- DBG_OUT("try to send a notification without notification center");
- }
-}
-
-/** init the database
- * @return true is the DB is inited. false if it fail.
- */
-bool Library::init()
-{
- int version = checkDatabaseVersion();
- if(version == -1) {
- // error
- DBG_OUT("version check -1");
- }
- else if(version == 0) {
- // let's create our DB
- DBG_OUT("version == 0");
- return _initDb();
- }
- else if(version != DB_SCHEMA_VERSION)
- {
- }
- return true;
-}
-
-bool Library::_initDb()
-{
- SQLStatement adminTable("CREATE TABLE admin (key TEXT NOT NULL,"
- " value TEXT)");
- SQLStatement adminVersion(boost::format("INSERT INTO admin (key, value) "
- " VALUES ('version', '%1%')") %
- DB_SCHEMA_VERSION);
- SQLStatement vaultTable("CREATE TABLE vaults (id INTEGER PRIMARY KEY,"
- " path TEXT)");
- SQLStatement folderTable("CREATE TABLE folders (id INTEGER PRIMARY KEY,"
- " path TEXT, name TEXT, "
- " vault_id INTEGER DEFAULT 0, "
- " locked INTEGER DEFAULT 0, "
- " virtual INTEGER DEFAULT 0,"
- " expanded INTEGER DEFAULT 0,"
- " parent_id INTEGER)");
-
- SQLStatement initialFolders(
- boost::format("insert into folders (name, locked, virtual, parent_id) "
- " values ('%1%', 1, %2%, 0)")
- % _("Trash")
- % int(LibFolderVirtualType::TRASH));
- SQLStatement fileTable("CREATE TABLE files (id INTEGER PRIMARY KEY,"
- " main_file INTEGER, name TEXT, parent_id INTEGER,"
- " orientation INTEGER, file_type INTEGER, "
- " file_date INTEGER, rating INTEGER DEFAULT 0, "
- " label INTEGER, flag INTEGER DEFAULT 0, "
- " import_date INTEGER, mod_date INTEGER, "
- " xmp TEXT, xmp_date INTEGER, xmp_file INTEGER,"
- " jpeg_file INTEGER)");
- SQLStatement fsFileTable("CREATE TABLE fsfiles (id INTEGER PRIMARY KEY,"
- " path TEXT)");
- SQLStatement keywordTable("CREATE TABLE keywords (id INTEGER PRIMARY KEY,"
- " keyword TEXT, parent_id INTEGER DEFAULT 0)");
- SQLStatement keywordingTable("CREATE TABLE keywording (file_id INTEGER,"
- " keyword_id INTEGER,"
- " UNIQUE(file_id, keyword_id))");
- SQLStatement labelTable("CREATE TABLE labels (id INTEGER PRIMARY KEY,"
- " name TEXT, color TEXT)");
- SQLStatement xmpUpdateQueueTable("CREATE TABLE xmp_update_queue "
- " (id INTEGER UNIQUE)");
-// SQLStatement collsTable("CREATE TABLE collections (id INTEGER PRIMARY KEY,"
-// " name TEXT)");
-// SQLStatement collectingTable("CREATE TABLE collecting (file_id INTEGER,"
-// " collection_id INTEGER)");
-
- SQLStatement fileUpdateTrigger(
- "CREATE TRIGGER file_update_trigger UPDATE ON files "
- " BEGIN"
- " UPDATE files SET mod_date = strftime('%s','now');"
- " END");
- SQLStatement xmpUpdateTrigger(
- "CREATE TRIGGER xmp_update_trigger UPDATE OF xmp ON files "
- " BEGIN"
- " INSERT OR IGNORE INTO xmp_update_queue (id) VALUES(new.id);"
- " SELECT rewrite_xmp(); "
- " END");
-
- m_dbdrv->execute_statement(adminTable);
- m_dbdrv->execute_statement(adminVersion);
- m_dbdrv->execute_statement(vaultTable);
- m_dbdrv->execute_statement(folderTable);
- m_dbdrv->execute_statement(initialFolders);
- m_dbdrv->execute_statement(fileTable);
- m_dbdrv->execute_statement(fsFileTable);
- m_dbdrv->execute_statement(keywordTable);
- m_dbdrv->execute_statement(keywordingTable);
- m_dbdrv->execute_statement(labelTable);
- m_dbdrv->execute_statement(xmpUpdateQueueTable);
-// m_dbdrv->execute_statement(collsTable);
-// m_dbdrv->execute_statement(collectingTable);
-
- m_dbdrv->execute_statement(fileUpdateTrigger);
- m_dbdrv->execute_statement(xmpUpdateTrigger);
- notify(LibNotification::make<LibNotification::Type::NEW_LIBRARY_CREATED>({}));
- return true;
-}
-
-/** check that database verion
- * @return the DB version. -1 in case of error. 0 is can't read it.
- */
-int Library::checkDatabaseVersion()
-{
- int v = 0;
- std::string version;
- try {
- SQLStatement sql("SELECT value FROM admin WHERE key='version'");
-
- if(m_dbdrv->execute_statement(sql)) {
- if(m_dbdrv->read_next_row()
- && m_dbdrv->get_column_content(0, version)) {
- v = std::stoi(version);
- }
- }
- }
- catch(const fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- v = -1;
- }
- catch(const std::bad_cast &)
- {
- DBG_OUT("version is %s, can't convert to int", version.c_str());
- v = 0;
- }
- catch(...)
- {
- v = -1;
- }
- return v;
-}
-
-
-int64_t Library::addFsFile(const std::string & file)
-{
- int64_t ret = -1;
-
- SQLStatement sql(boost::format("INSERT INTO fsfiles (path)"
- " VALUES ('%1%')")
- % file);
- if(m_dbdrv->execute_statement(sql)) {
- int64_t id = m_dbdrv->last_row_id();
- DBG_OUT("last row inserted %d", (int)id);
- ret = id;
- }
- return ret;
-}
-
-std::string Library::getFsFile(library_id_t id)
-{
- std::string p;
- SQLStatement sql(boost::format("SELECT path FROM fsfiles"
- " WHERE id='%1%'")
- % id);
- try {
- if(m_dbdrv->execute_statement(sql) &&
- m_dbdrv->read_next_row()) {
- std::string path;
- m_dbdrv->get_column_content(0, path);
- p = path;
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
-
- return p;
-}
-
-
-library_id_t Library::addFile(library_id_t folder_id, const std::string & file,
- LibraryManaged manage)
-{
- library_id_t ret = -1;
- DBG_ASSERT(manage == LibraryManaged::NO, "manage not supported");
- DBG_ASSERT(folder_id != -1, "invalid folder ID");
- try {
- int32_t rating, orientation, flag;
- library_id_t label_id;
- std::string label;
- fwk::MimeType mime = fwk::MimeType(file);
- eng::LibFileType file_type = eng::mimetype_to_filetype(mime);
- fwk::XmpMeta meta(file, file_type == eng::LibFileType::RAW);
- label_id = 0;
- orientation = meta.orientation();
- rating = meta.rating();
- label = meta.label();
- flag = meta.flag();
- time_t creation_date = fwk::make_time_value(meta.creation_date());
- if(creation_date == -1) {
- creation_date = 0;
- }
-
- library_id_t fs_file_id = addFsFile(file);
- if(fs_file_id <= 0) {
- throw(fwk::Exception("add fsfile failed"));
- }
- SQLStatement sql(boost::format("INSERT INTO files ("
- " main_file, name, parent_id, "
- " import_date, mod_date, "
- " orientation, file_date, rating, label, "
- " file_type, flag, xmp) "
- " VALUES ("
- " '%1%', '%2%', '%3%', "
- " '%4%', '%4%',"
- " '%5%', '%6%', '%7%', '%8%', '%9%',"
- " '%10%',"
- " ?1);")
- % fs_file_id % fwk::path_basename(file) % folder_id
- % time(NULL)
- % orientation % creation_date % rating
- % label_id % static_cast<int>(file_type) % flag);
- std::string buf = meta.serialize_inline();
- sql.bind(1, buf);
- if(m_dbdrv->execute_statement(sql)) {
- library_id_t id = m_dbdrv->last_row_id();
- DBG_OUT("last row inserted %d", (int)id);
- ret = id;
- auto & keywords = meta.keywords();
- for(auto k : keywords) {
- library_id_t kwid = makeKeyword(k);
- if(kwid != -1) {
- assignKeyword(kwid, id);
- }
- }
- }
- }
- catch(const fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- ret = -1;
- }
- catch(const std::exception & e)
- {
- DBG_OUT("unknown exception %s", e.what());
- ret = -1;
- }
- return ret;
-}
-
-
-library_id_t Library::addFileAndFolder(const std::string & folder,
- const std::string & file,
- LibraryManaged manage)
-{
- LibFolderPtr f;
- f = getFolder(folder);
- if(f == NULL) {
- ERR_OUT("Folder %s not found", folder.c_str());
- }
- return addFile(f ? engine_db_libfolder_id(f.get()) : -1, file, manage);
-}
-
-library_id_t Library::addBundle(library_id_t folder_id,
- const eng::FileBundlePtr & bundle,
- LibraryManaged manage)
-{
- library_id_t file_id = 0;
- file_id = addFile(folder_id, engine_db_filebundle_main(bundle.get()), manage);
- if(file_id > 0) {
- library_id_t fsfile_id;
- bool success;
- // addXmpSidecar
- if(engine_db_filebundle_sidecar(bundle.get())[0] == 0) {
- fsfile_id = addFsFile(engine_db_filebundle_sidecar(bundle.get()));
- if(fsfile_id > 0) {
- success = addSidecarFileToBundle(file_id, fsfile_id);
- }
- }
- // addJpeg
- if(engine_db_filebundle_jpeg(bundle.get())[0] == 0) {
- fsfile_id = addFsFile(engine_db_filebundle_jpeg(bundle.get()));
- if(fsfile_id > 0) {
- success = addJpegFileToBundle(file_id, fsfile_id);
- }
- }
- }
- return file_id;
-}
-
-bool Library::addSidecarFileToBundle(library_id_t file_id,
- library_id_t fsfile_id)
-{
- SQLStatement sql(boost::format("UPDATE files SET xmp_file='%2%'"
- " WHERE id='%1%';")
- % file_id % fsfile_id);
- try {
- return m_dbdrv->execute_statement(sql);
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
- return false;
-}
-
-
-bool Library::addJpegFileToBundle(library_id_t file_id, library_id_t fsfile_id)
-{
- SQLStatement sql(boost::format("UPDATE files SET jpeg_file='%2%',"
- " file_type='%3%' "
- " WHERE id='%1%';")
- % file_id % fsfile_id
- % static_cast<int>(LibFileType::RAW_JPEG));
- try {
- return m_dbdrv->execute_statement(sql);
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
- return false;
-}
-
-
-LibFolderPtr Library::getFolder(const std::string & folder)
-{
- LibFolderPtr f;
- SQLStatement sql(boost::format("SELECT %1% "
- "FROM folders WHERE path='%2%'")
- % libfolder_read_db_columns() % folder);
-
- try {
- if(m_dbdrv->execute_statement(sql)) {
- if(m_dbdrv->read_next_row()) {
- f = libfolder_read_from(m_dbdrv);
- }
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
- return f;
-}
-
-
-LibFolderPtr Library::addFolder(const std::string & folder)
-{
- LibFolderPtr f;
- SQLStatement sql(boost::format("INSERT INTO folders "
- "(path,name,vault_id,parent_id) "
- "VALUES('%1%', '%2%', '0', '0')")
- % folder % fwk::path_basename(folder));
- try {
- if(m_dbdrv->execute_statement(sql)) {
- library_id_t id = m_dbdrv->last_row_id();
- DBG_OUT("last row inserted %Ld", (long long)id);
- f = libfolder_new(id, fwk::path_basename(folder).c_str());
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
- return f;
-}
-
-
-void Library::getAllFolders(const LibFolderListPtr & l)
-{
- SQLStatement sql(boost::format("SELECT %1% FROM folders")
- % libfolder_read_db_columns());
- try {
- if(m_dbdrv->execute_statement(sql)) {
- while(m_dbdrv->read_next_row()) {
- LibFolderPtr f = libfolder_read_from(m_dbdrv);
- l->push_back(f);
- }
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
-}
-
-static LibFilePtr getFileFromDbRow(const db::IConnectionDriver::Ptr & dbdrv)
-{
- library_id_t id;
- library_id_t fid;
- library_id_t fsfid;
- std::string pathname;
- std::string name;
- DBG_ASSERT(dbdrv->get_number_of_columns() == 10, "wrong number of columns");
- dbdrv->get_column_content(0, id);
- dbdrv->get_column_content(1, fid);
- dbdrv->get_column_content(2, pathname);
- dbdrv->get_column_content(3, name);
- dbdrv->get_column_content(8, fsfid);
- DBG_OUT("found %s", pathname.c_str());
- LibFilePtr f(libfile_new(id, fid, fsfid,
- pathname.c_str(), name.c_str()));
- int32_t val;
- dbdrv->get_column_content(4, val);
- engine_db_libfile_set_orientation(f.get(), val);
- dbdrv->get_column_content(5, val);
- engine_db_libfile_set_rating(f.get(), val);
- dbdrv->get_column_content(6, val);
- engine_db_libfile_set_label(f.get(), val);
- dbdrv->get_column_content(9, val);
- engine_db_libfile_set_flag(f.get(), val);
-
- /* Casting needed. Remember that a simple enum like this is just a couple
- * of #define for integers.
- */
- dbdrv->get_column_content(7, val);
- engine_db_libfile_set_file_type(f.get(),(eng::LibFileType)val);
- return f;
-}
-
-void Library::getFolderContent(library_id_t folder_id, const LibFileListPtr & fl)
-{
- SQLStatement sql(boost::format("SELECT files.id,parent_id,fsfiles.path,"
- "name,"
- "orientation,rating,label,file_type,"
- "fsfiles.id,flag"
- " FROM files,fsfiles "
- " WHERE parent_id='%1%' "
- " AND files.main_file=fsfiles.id")
- % folder_id);
- try {
- if(m_dbdrv->execute_statement(sql)) {
- while(m_dbdrv->read_next_row()) {
- LibFilePtr f(getFileFromDbRow(m_dbdrv));
- fl->push_back(f);
- }
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
-}
-
-int Library::countFolder(library_id_t folder_id)
+LibraryPtr library_new(const char *dir, uint64_t notif_id)
{
- int count = -1;
- SQLStatement sql(boost::format("SELECT COUNT(id) FROM files WHERE parent_id='%1%';")
- % folder_id);
- try {
- if(m_dbdrv->execute_statement(sql)) {
- if(m_dbdrv->read_next_row()) {
- m_dbdrv->get_column_content(0, count);
- }
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
- return count;
+ return LibraryPtr(engine_db_library_new(dir, notif_id),
+ &engine_db_library_delete);
}
-
-void Library::getAllKeywords(const KeywordListPtr & l)
-{
- SQLStatement sql("SELECT id,keyword FROM keywords ORDER BY keyword");
- try {
- if(m_dbdrv->execute_statement(sql)) {
- while(m_dbdrv->read_next_row()) {
- library_id_t id;
- std::string name;
- m_dbdrv->get_column_content(0, id);
- m_dbdrv->get_column_content(1, name);
- l->push_back(keyword_new(id, name.c_str()));
- }
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
-}
-
-library_id_t Library::makeKeyword(const std::string & keyword)
-{
- library_id_t keyword_id = -1;
- SQLStatement sql("SELECT id FROM keywords WHERE "
- "keyword=?1;");
- sql.bind(1, keyword);
- try {
- if(m_dbdrv->execute_statement(sql)) {
- if(m_dbdrv->read_next_row()) {
- m_dbdrv->get_column_content(0, keyword_id);
- }
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
- if(keyword_id == -1) {
- SQLStatement sql2("INSERT INTO keywords (keyword, parent_id) "
- " VALUES(?1, 0);");
- sql2.bind(1, keyword);
- try {
- if(m_dbdrv->execute_statement(sql2)) {
- keyword_id = m_dbdrv->last_row_id();
- KeywordPtr kw(keyword_new(keyword_id, keyword.c_str()));
- notify(LibNotification::make<LibNotification::Type::ADDED_KEYWORD>({kw}));
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
- }
-
- return keyword_id;
-}
-
-
-bool Library::unassignAllKeywordsForFile(library_id_t file_id)
-{
- bool ret = false;
- SQLStatement sql(boost::format("DELETE FROM keywording"
- " WHERE file_id='%1%'")
- % file_id);
- try {
- ret = m_dbdrv->execute_statement(sql);
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
- return ret;
-}
-
-bool Library::assignKeyword(library_id_t kw_id, library_id_t file_id)
-{
- bool ret = false;
- // we must IGNORE as there is a unicity constraint
- // that way setting a keyword relationship is solid
- SQLStatement sql(boost::format("INSERT OR IGNORE INTO keywording"
- " (file_id, keyword_id) "
- " VALUES('%1%', '%2%');")
- % file_id % kw_id );
- try {
- ret = m_dbdrv->execute_statement(sql);
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
- return ret;
-}
-
-
-void Library::getKeywordContent(library_id_t keyword_id, const LibFileListPtr & fl)
-{
- SQLStatement sql(boost::format("SELECT files.id,parent_id,fsfiles.path,"
- "name,orientation,rating,label,file_type,"
- " fsfiles.id,flag"
- " FROM files,fsfiles "
- " WHERE files.id IN "
- " (SELECT file_id FROM keywording "
- " WHERE keyword_id='%1%') "
- " AND fsfiles.id = files.main_file;")
- % keyword_id);
- try {
- if(m_dbdrv->execute_statement(sql)) {
- while(m_dbdrv->read_next_row()) {
- LibFilePtr f(getFileFromDbRow(m_dbdrv));
- fl->push_back(f);
- }
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
-}
-
-
-void Library::getMetaData(library_id_t file_id, const LibMetadata::Ptr & meta)
-{
- SQLStatement sql(boost::format("SELECT xmp FROM files "
- " WHERE id='%1%';")
- % file_id);
- try {
- if(m_dbdrv->execute_statement(sql)) {
- while(m_dbdrv->read_next_row()) {
- std::string xml;
- m_dbdrv->get_column_content(0, xml);
- meta->unserialize(xml.c_str());
- }
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
-}
-
-
-
-
-bool Library::setInternalMetaDataInt(library_id_t file_id, const char* col,
- int32_t value)
-{
- bool ret = false;
- DBG_OUT("setting metadata in column %s", col);
- SQLStatement sql(boost::format("UPDATE files SET %1%='%2%' "
- " WHERE id='%3%';")
- % col % value % file_id);
- try {
- ret = m_dbdrv->execute_statement(sql);
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- ret = false;
- }
- return ret;
-}
-
-/** set metadata block
- * @param file_id the file ID to set the metadata block
- * @param meta the metadata block
- * @return false on error
- */
-bool Library::setMetaData(library_id_t file_id, const LibMetadata::Ptr & meta)
-{
- bool ret = false;
- SQLStatement sql(boost::format("UPDATE files SET xmp=?1 "
- " WHERE id='%1%';")
- % file_id);
- sql.bind(1, meta->serialize_inline());
- try {
- ret = m_dbdrv->execute_statement(sql);
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- ret = false;
- }
- return ret;
-}
-
-
-/** set metadata
- * @param file_id the file ID to set the metadata block
- * @param meta the metadata index
- * @param value the value to set
- * @return false on error
- */
-bool Library::setMetaData(library_id_t file_id, fwk::PropertyIndex meta,
- const fwk::PropertyValue & value)
-{
- bool retval = false;
- DBG_OUT("setting metadata %x", meta);
- DBG_ASSERT(check_property_type(meta, value.type()),
- "wrong property value type");
- switch(meta) {
- case eng::NpXmpRatingProp:
- case eng::NpXmpLabelProp:
- case eng::NpTiffOrientationProp:
- case eng::NpNiepceFlagProp:
- if(is_empty(value) || is_integer(value)) {
- // internal.
- // make the column mapping more generic.
- const char * col = NULL;
- switch(meta) {
- case eng::NpXmpRatingProp:
- col = "rating";
- break;
- case eng::NpTiffOrientationProp:
- col = "orientation";
- break;
- case eng::NpXmpLabelProp:
- col = "label";
- break;
- case eng::NpNiepceFlagProp:
- col = "flag";
- break;
- }
- if(col) {
- retval = setInternalMetaDataInt(file_id, col,
- get_integer(value));
- }
- }
- break;
- case eng::NpIptcKeywordsProp:
- {
- // unassign all keywords
- unassignAllKeywordsForFile(file_id);
-
- fwk::StringArray keywords(boost::get<fwk::StringArray>(value));
- for_each(keywords.begin(), keywords.end(),
- [this, file_id](const std::string & s) {
- library_id_t kwid = makeKeyword(s);
- if(kwid != -1) {
- assignKeyword(kwid, file_id);
- }
- });
- break;
- }
- default:
- // external
- // TODO add the external metadata
- //
- break;
- }
- LibMetadata::Ptr metablock(new LibMetadata(file_id));
- getMetaData(file_id, metablock);
- retval = metablock->setMetaData(meta, value);
- retval = metablock->touch();
- retval = setMetaData(file_id, metablock);
- return retval;
-}
-
-bool Library::writeMetaData(library_id_t file_id)
-{
- return rewriteXmpForId(file_id, true);
-}
-
-bool Library::moveFileToFolder(library_id_t file_id, library_id_t folder_id)
-{
- SQLStatement sql(boost::format("SELECT id FROM folders WHERE id = %1%;") % folder_id);
- try {
- if(m_dbdrv->execute_statement(sql)) {
- if(m_dbdrv->read_next_row()) {
- // we have the destination folder
- SQLStatement sql2(boost::format("UPDATE files SET parent_id = %1% "
- " WHERE id = %2%;") % folder_id % file_id);
- if(m_dbdrv->execute_statement(sql2)) {
- return true;
- }
- }
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
- return false;
-}
-
-void Library::getAllLabels(const Label::ListPtr & l)
-{
- SQLStatement sql("SELECT id,name,color FROM labels ORDER BY id");
- try {
- if(m_dbdrv->execute_statement(sql)) {
- while(m_dbdrv->read_next_row()) {
- int32_t id;
- std::string name;
- std::string colour;
- m_dbdrv->get_column_content(0, id);
- m_dbdrv->get_column_content(1, name);
- m_dbdrv->get_column_content(2, colour);
- l->push_back(Label::Ptr(new Label(id, name, colour)));
- }
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
-}
-
-
-library_id_t Library::addLabel(const std::string & name, const std::string & colour)
-{
- library_id_t ret = -1;
-
- SQLStatement sql(boost::format("INSERT INTO labels (name,color)"
- " VALUES ('%1%', '%2%')")
- % name % colour);
- if(m_dbdrv->execute_statement(sql)) {
- library_id_t id = m_dbdrv->last_row_id();
- DBG_OUT("last row inserted %d", (int)id);
- ret = id;
- }
- return ret;
-}
-
-
-library_id_t Library::addLabel(const std::string & name,
- const fwk::RgbColour & c)
-{
- return addLabel(name, c.to_string());
-}
-
-
-bool Library::updateLabel(library_id_t label_id, const std::string & name,
- const std::string & colour)
-{
- SQLStatement sql(boost::format("UPDATE labels SET name='%2%', color='%3%'"
- " WHERE id='%1%';")
- % label_id % name % colour);
- try {
- return m_dbdrv->execute_statement(sql);
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
- return false;
-}
-
-
-bool Library::deleteLabel(library_id_t label_id)
-{
- SQLStatement sql(boost::format("DELETE FROM labels "
- " WHERE id='%1%';") % label_id);
- try {
- return m_dbdrv->execute_statement(sql);
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- }
- return false;
-}
-
-
-bool Library::getXmpIdsInQueue(std::vector<library_id_t> & ids)
-{
- SQLStatement sql("SELECT id FROM xmp_update_queue;");
- try {
- if(m_dbdrv->execute_statement(sql)) {
- while(m_dbdrv->read_next_row()) {
- library_id_t id;
- m_dbdrv->get_column_content(0, id);
- ids.push_back(id);
- }
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- return false;
- }
- return true;
-}
-
-
-bool Library::rewriteXmpForId(library_id_t id, bool write_xmp)
-{
- SQLStatement del(boost::format("DELETE FROM xmp_update_queue "
- " WHERE id='%1%';") % id);
- SQLStatement getxmp(boost::format("SELECT xmp, main_file, xmp_file FROM files "
- " WHERE id='%1%';") % id);
- try {
-
- if(m_dbdrv->execute_statement(del)
- && m_dbdrv->execute_statement(getxmp)) {
- while(write_xmp && m_dbdrv->read_next_row()) {
- std::string xmp_buffer;
- library_id_t main_file_id;
- library_id_t xmp_file_id;
- m_dbdrv->get_column_content(0, xmp_buffer);
- m_dbdrv->get_column_content(1, main_file_id);
- m_dbdrv->get_column_content(2, xmp_file_id);
- std::string spath = getFsFile(main_file_id);
- DBG_ASSERT(!spath.empty(), "couldn't find the main file");
- std::string p;
- if(xmp_file_id > 0) {
- p = getFsFile(xmp_file_id);
- DBG_ASSERT(!p.empty(), "couldn't find the xmp file path");
- }
- if(p.empty()) {
- p = fwk::path_replace_extension(spath, ".xmp");
- DBG_ASSERT(p != spath, "path must have been changed");
- }
- if(fwk::path_exists(p)) {
- DBG_OUT("%s already exist", p.c_str());
- // TODO backup
- }
- // TODO probably a faster way to do that
- fwk::XmpMeta xmppacket;
- xmppacket.unserialize(xmp_buffer.c_str());
- // TODO use different API
- FILE * f = fopen(p.c_str(), "w");
- if(f) {
- std::string sidecar = xmppacket.serialize();
- fwrite(sidecar.c_str(), sizeof(std::string::value_type),
- sidecar.size(), f);
- fclose(f);
- if(xmp_file_id <= 0) {
- xmp_file_id = addFsFile(p);
- DBG_ASSERT(xmp_file_id > 0, "couldn't add xmp_file");
- bool res = addSidecarFileToBundle(id, xmp_file_id);
- DBG_ASSERT(res, "addSidecarFileToBundle failed");
- }
- }
- // TODO rewrite the modified date in the files table
- // caveat: this will trigger this rewrite recursively.
- }
- }
- }
- catch(fwk::Exception & e)
- {
- DBG_OUT("db exception %s", e.what());
- return false;
- }
-
- return true;
-}
-
-
-bool Library::processXmpUpdateQueue(bool write_xmp)
-{
- bool retval = false;
- std::vector<library_id_t> ids;
- retval = getXmpIdsInQueue(ids);
- if (retval) {
- std::for_each(ids.begin(), ids.end(),
- [this, write_xmp] (auto id){
- this->rewriteXmpForId(id, write_xmp);
- });
- }
- return retval;
-}
-
-
}
/*
Local Variables:
diff --git a/src/engine/db/library.hpp b/src/engine/db/library.hpp
index 60de203..bc3cfc0 100644
--- a/src/engine/db/library.hpp
+++ b/src/engine/db/library.hpp
@@ -17,206 +17,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-
-#ifndef _DB_LIBRARY_H_
-#define _DB_LIBRARY_H_
-
-#include <string>
+#pragma once
#include <memory>
-#include <boost/any.hpp>
-
-#include "fwk/toolkit/notificationcenter.hpp"
-#include "fwk/utils/db/iconnectiondriver.hpp"
-#include "fwk/utils/db/iconnectionmanagerdriver.hpp"
-#include "engine/db/librarytypes.hpp"
-#include "engine/db/libfolder.hpp"
-#include "engine/db/libfile.hpp"
-#include "engine/db/libmetadata.hpp"
-#include "engine/db/filebundle.hpp"
-#include "engine/db/keyword.hpp"
-#include "engine/db/label.hpp"
-#include "engine/library/notification.hpp"
-
-// The database schema version. Increase at each change.
-// Some will be persistent and have a conversion TBD.
-#define DB_SCHEMA_VERSION 6
-
-namespace fwk {
-class RgbColour;
-}
namespace eng {
-/** Whether to import managed. */
-enum class LibraryManaged {
- NO = 0,
- YES
-};
-
-class Library
-{
-public:
- typedef std::shared_ptr<Library> Ptr;
-
- Library(const std::string & dir, uint64_t notif_id);
- virtual ~Library();
-
- bool ok() const
- { return m_inited; }
- /** set the main library directory */
-// void setMainDir(const std::string & dir)
-// { m_maindir = dir; }
- /** return the main directory */
- const std::string & mainDir() const
- { return m_maindir; }
- /** get the path to the DB file */
- const std::string & dbName() const
- { return m_dbname; }
-
- void notify(LibNotification&& n);
-
- /** add a file to the library
- * @param folder the path of the containing folder
- * @param file the file path
- * @param manage pass LibraryManaged::YES if the library *manage* the file.
- * Currently unsupported.
- */
- library_id_t addFileAndFolder(const std::string & folder,
- const std::string & file, LibraryManaged manage);
-
- /** add a fs file to the library
- * @param file the file path
- * @return the id of the fs_file, -1 in case of error
- */
- library_id_t addFsFile(const std::string & file);
-
- /** Get a FsFile from an id
- * @param id the id of the FsFile
- * @return the path. Empty if not found.
- */
- std::string getFsFile(library_id_t id);
-
- /** add a file to the library
- * @param folder_id the id of the containing folder
- * @param file the file path
- * @param manage pass LibraryManaged::YES if the library *manage* the file.
- * Currently unsupported.
- */
- library_id_t addFile(library_id_t folder_id, const std::string & file, LibraryManaged manage);
+class Library;
+typedef std::shared_ptr<Library> LibraryPtr;
- /** add a bundle of files to the library
- * @param folder_id the id of the containing folder
- * @param bundle the bundle
- * @param manage pass LibraryManaged::YES if the library *manage* the file.
- * Currently unsupported.
- */
- library_id_t addBundle(library_id_t folder_id,
- const eng::FileBundlePtr& bundle,
- LibraryManaged manage);
- /** add a sidecar fsfile to a bundle (file)
- * @param file_id the id of the file bundle
- * @param fsfile_id the id of the fsfile
- * @return true if success
- */
- bool addSidecarFileToBundle(library_id_t file_id, library_id_t fsfile_id);
- /** add a jpeg fsfile to a bundle (file)
- * @param file_id the id of the file bundle
- * @param fsfile_id the id of the fsfile
- * @return true if success
- */
- bool addJpegFileToBundle(library_id_t file_id, library_id_t fsfile_id);
-
- /** Get a specific folder id from the library
- * @param folder the folder path to check
- * @return the folder, NULL if not found
- */
- LibFolderPtr getFolder(const std::string & folder);
-
- /** Add a folder
- * @param folder the folder path
- */
- LibFolderPtr addFolder(const std::string & folder);
- /** List all the folders.
- * @param l the list of LibFolder
- */
- void getAllFolders(const LibFolderListPtr & l);
-
- /** List the folder content
- * @param folder_id id of the folder
- * @param fl the resulting file list
- */
- void getFolderContent(library_id_t folder_id, const LibFileListPtr & fl);
- int countFolder(library_id_t folder_id);
- void getAllKeywords(const KeywordListPtr & l);
- void getKeywordContent(library_id_t keyword_id, const LibFileListPtr & fl);
- /** get the metadata block (XMP) */
- void getMetaData(library_id_t file_id, const LibMetadata::Ptr & );
- /** set the metadata block (XMP) */
- bool setMetaData(library_id_t file_id, const LibMetadata::Ptr & );
- bool setMetaData(library_id_t file_id, fwk::PropertyIndex meta,
- const fwk::PropertyValue & value);
- bool writeMetaData(library_id_t file_id);
-
- bool moveFileToFolder(library_id_t file_id, library_id_t folder_id);
-
- void getAllLabels(const eng::Label::ListPtr & l);
- library_id_t addLabel(const std::string & name, const std::string & colour);
- library_id_t addLabel(const std::string & name, const fwk::RgbColour & c);
- bool updateLabel(library_id_t label_id, const std::string & name, const std::string & colour);
- bool deleteLabel(library_id_t label_id);
-
- /** Trigger the processing of the XMP update queue */
- bool processXmpUpdateQueue(bool rewrite_xmp);
-
- /** Locate the keyword, creating it if needed
- * @param keyword the keyword to locate
- * @return -1 if not found (shouldn't happen) or the id of the
- * keyword, either found or just created.
- */
- library_id_t makeKeyword(const std::string & keyword);
- /** Assign a keyword to a file.
- * @param kw_id the keyword id
- * @param file_id the file id
- * @return true if success, false if error
- */
- bool assignKeyword(library_id_t kw_id, library_id_t file_id);
- /** Unassign all keyword for a file.
- * @param file_id the file id
- * @return true if success, false if error
- */
- bool unassignAllKeywordsForFile(library_id_t file_id);
-
- int checkDatabaseVersion();
-
- db::IConnectionDriver::Ptr dbDriver()
- { return m_dbdrv; }
-private:
- bool init();
- bool _initDb();
-
- bool getXmpIdsInQueue(std::vector<library_id_t> & ids);
- /** rewrite the XMP sidecar for the file whose id is %id
- * and remove it from the queue.
- */
- bool rewriteXmpForId(library_id_t id, bool rewrite_xmp);
-
- /** set an "internal" metadata of type int */
- bool setInternalMetaDataInt(library_id_t file_id, const char* col,
- int32_t value);
-
- std::string m_maindir;
- std::string m_dbname;
- db::IConnectionManagerDriver::Ptr m_dbmgr;
- db::IConnectionDriver::Ptr m_dbdrv;
- uint64_t m_notif_id;
- bool m_inited;
-};
+LibraryPtr library_new(const char *dir, uint64_t notif_id);
+/** Whether to import managed. */
+enum class LibraryManaged { NO = 0, YES };
}
-#endif
+extern "C" bool engine_db_library_ok(const eng::Library *library);
+
/*
Local Variables:
mode:c++
@@ -226,4 +43,3 @@ private:
fill-column:99
End:
*/
-
diff --git a/src/engine/db/library.rs b/src/engine/db/library.rs
index 5aa955b..739339b 100644
--- a/src/engine/db/library.rs
+++ b/src/engine/db/library.rs
@@ -1,5 +1,5 @@
/*
- * niepce - eng/db/library.rs
+ * niepce - engine/db/library.rs
*
* Copyright (C) 2017 Hubert Figuière
*
@@ -17,34 +17,49 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+use libc::{
+ c_char,
+ c_void
+};
use std::path::{
Path,
PathBuf
};
+use std::ffi::CStr;
use std::fs::File;
use std::io::Write;
use rusqlite;
+
use super::{
FromDb,
LibraryId
};
+use super::label::Label;
use super::libfolder;
use super::libfolder::LibFolder;
use super::libfile;
use super::libfile::LibFile;
+use super::libmetadata::LibMetadata;
+use super::filebundle::FileBundle;
use super::keyword::Keyword;
-
+use engine::library::notification::Notification as LibNotification;
+use engine::library::notification::engine_library_notify;
use fwk;
+use root::fwk::{
+ PropertyValue,
+ is_empty,
+ is_integer,
+ get_integer,
+ get_string_array,
+ string_array_len,
+ string_array_at_cstr
+};
+use root::eng::NiepceProperties as Np;
+pub use root::eng::LibraryManaged as Managed;
const DB_SCHEMA_VERSION: i32 = 6;
const DATABASENAME: &str = "niepcelibrary.db";
-#[repr(i32)]
-pub enum Managed {
- NO = 0,
- YES = 1
-}
-
pub struct Library {
maindir: PathBuf,
dbpath: PathBuf,
@@ -53,20 +68,13 @@ pub struct Library {
notif_id: u64,
}
-extern "C" {
- pub fn lib_notification_notify_new_lib_created(notif_id: u64);
- pub fn lib_notification_notify_xmp_needs_update(notif_id: u64);
- pub fn lib_notification_notify_kw_added(notif_id: u64, keyword: *mut Keyword);
-}
-
-
impl Library {
- pub fn new(dir: &Path, notif_id: u64) -> Library {
- let mut dbpath = PathBuf::from(dir);
+ pub fn new(dir: PathBuf, notif_id: u64) -> Library {
+ let mut dbpath = dir.clone();
dbpath.push(DATABASENAME);
let mut lib = Library {
- maindir: PathBuf::from(dir),
+ maindir: dir,
dbpath: dbpath,
dbconn: None,
inited: false,
@@ -82,7 +90,7 @@ impl Library {
let conn_attempt = rusqlite::Connection::open(self.dbpath.clone());
if let Ok(conn) = conn_attempt {
conn.create_scalar_function("rewrite_xmp", 0, false, |_| {
- unsafe { lib_notification_notify_xmp_needs_update(self.notif_id); }
+ self.notify(Box::new(LibNotification::XmpNeedsUpdate));
Ok(true)
});
self.dbconn = Some(conn);
@@ -181,12 +189,30 @@ impl Library {
SELECT rewrite_xmp();\
END", &[]).unwrap();
- unsafe { lib_notification_notify_new_lib_created(self.notif_id); }
+ self.notify(Box::new(LibNotification::LibCreated));
return true;
}
false
}
+ pub fn notify(&self, notif: Box<LibNotification>) {
+ unsafe { engine_library_notify(self.notif_id, Box::into_raw(notif) as *mut c_void); }
+ }
+
+ pub fn add_jpeg_file_to_bundle(&self, file_id: LibraryId, fsfile_id: LibraryId) -> bool {
+ if let Some(ref conn) = self.dbconn {
+ let filetype: i32 = libfile::FileType::RAW_JPEG.into();
+ if let Ok(c) = conn.execute("UPDATE files SET jpeg_file=:1 file_type=:3 WHERE id=:2;",
+ &[&fsfile_id, &file_id,
+ &filetype]) {
+ if c == 1 {
+ return true;
+ }
+ }
+ }
+ false
+ }
+
pub fn add_sidecar_file_to_bundle(&self, file_id: LibraryId, fsfile_id: LibraryId) -> bool {
if let Some(ref conn) = self.dbconn {
if let Ok(c) = conn.execute("UPDATE files SET xmp_file=:1 WHERE id=:2;",
@@ -350,10 +376,30 @@ impl Library {
None
}
- pub fn add_file(&self, folder_id: LibraryId, file: &str, _manage: Managed) -> LibraryId {
+ pub fn add_bundle(&self, folder_id: LibraryId, bundle: &FileBundle,
+ manage: Managed) -> LibraryId {
+ let file_id = self.add_file(folder_id, bundle.main(), manage);
+ if file_id > 0 {
+ if !bundle.sidecar().is_empty() {
+ let fsfile_id = self.add_fs_file(bundle.sidecar());
+ if fsfile_id > 0 {
+ self.add_sidecar_file_to_bundle(file_id, fsfile_id);
+ }
+ }
+ if !bundle.jpeg().is_empty() {
+ let fsfile_id = self.add_fs_file(bundle.jpeg());
+ if fsfile_id > 0 {
+ self.add_jpeg_file_to_bundle(file_id, fsfile_id);
+ }
+ }
+ }
+ file_id
+ }
+
+ pub fn add_file(&self, folder_id: LibraryId, file: &str, manage: Managed) -> LibraryId {
let mut ret: LibraryId = -1;
- //DBG_ASSERT(manage == Managed::NO, "manage not supported");
- //DBG_ASSERT(folder_id != -1, "invalid folder ID");
+ dbg_assert!(manage == Managed::NO, "manage not supported");
+ dbg_assert!(folder_id != -1, "invalid folder ID");
let mime = fwk::MimeType::new(file);
let file_type = libfile::mimetype_to_filetype(&mime);
let label_id: LibraryId = 0;
@@ -450,9 +496,9 @@ impl Library {
return -1;
}
let keyword_id = conn.last_insert_rowid();
- unsafe { lib_notification_notify_kw_added(
- self.notif_id,
- Box::into_raw(Box::new(Keyword::new(keyword_id, keyword)))); }
+ self.notify(
+ Box::new(LibNotification::AddedKeyword(
+ Keyword::new(keyword_id, keyword))));
return keyword_id;
}
@@ -478,6 +524,120 @@ impl Library {
WHERE keyword_id=:1) ")
}
+ pub fn get_metadata(&self, file_id: LibraryId) -> Option<LibMetadata> {
+ if let Some(ref conn) = self.dbconn {
+ let sql = format!("SELECT {} FROM {} WHERE id=:1",
+ LibMetadata::read_db_columns(),
+ LibMetadata::read_db_tables());
+ if let Ok(mut stmt) = conn.prepare(&sql) {
+ let mut rows = stmt.query(&[&file_id]).unwrap();
+ if let Some(Ok(row)) = rows.next() {
+ let meta = LibMetadata::read_from(&row);
+ return Some(meta);
+ }
+ }
+ }
+ None
+ }
+
+
+ fn unassign_all_keywords_for_file(&self, file_id: LibraryId) -> bool {
+ if let Some(ref conn) = self.dbconn {
+ if let Ok(_) = conn.execute("DELETE FROM keywording \
+ WHERE file_id=:1;",
+ &[&file_id]) {
+ // XXX check success.
+ return true;
+ }
+ }
+ false
+ }
+
+ fn set_internal_metadata(&self, file_id: LibraryId, column: &str, value: i32) -> bool {
+ if let Some(ref conn) = self.dbconn {
+ if let Ok(_) = conn.execute("UPDATE files SET :1=:2 \
+ WHERE id=:3;",
+ &[&column, &value, &file_id]) {
+ // XXX check success.
+ return true;
+ }
+ }
+ false
+ }
+
+ fn set_metadata_block(&self, file_id: LibraryId, metablock: &LibMetadata) -> bool {
+ let xmp = metablock.serialize_inline();
+ if let Some(ref conn) = self.dbconn {
+ if let Ok(_) = conn.execute("UPDATE files SET xmp=:1 \
+ WHERE id=:2;",
+ &[&xmp, &file_id]) {
+ // XXX check success.
+ return true;
+ }
+ }
+ false
+ }
+
+ pub fn set_metadata(&self, file_id: LibraryId, meta: Np,
+ value: &PropertyValue) -> bool {
+ let mut retval = false;
+ match meta {
+ Np::NpXmpRatingProp |
+ Np::NpXmpLabelProp |
+ Np::NpTiffOrientationProp |
+ Np::NpNiepceFlagProp => {
+ if unsafe { is_empty(value) || is_integer(value) } {
+ // internal
+ // make the column mapping more generic.
+ let column = match meta {
+ Np::NpXmpRatingProp =>
+ "rating",
+ Np::NpXmpLabelProp =>
+ "orientation",
+ Np::NpTiffOrientationProp =>
+ "label",
+ Np::NpNiepceFlagProp =>
+ "flag",
+ _ =>
+ unreachable!()
+ };
+ if !column.is_empty() {
+ retval = self.set_internal_metadata(file_id, column,
+ unsafe { get_integer(value) });
+ if !retval {
+ return false;
+ }
+ }
+ }
+ },
+ Np::NpIptcKeywordsProp => {
+ self.unassign_all_keywords_for_file(file_id);
+
+ let keywords = unsafe { get_string_array(value) };
+ let length = unsafe { string_array_len(keywords) };
+ for i in 0..length {
+ let s = unsafe { string_array_at_cstr(keywords, i) };
+ let cstr = unsafe { CStr::from_ptr(s) }.to_string_lossy();
+ let id = self.make_keyword(&cstr);
+ if id != -1 {
+ self.assign_keyword(id, file_id);
+ }
+ }
+ }
+ _ => {
+ // XXX TODO
+ dbg_out!("unhandled meta {}", meta as u32);
+ }
+ }
+ if let Some(mut metablock) = self.get_metadata(file_id) {
+ metablock.set_metadata(meta, value);
+ metablock.touch();
+ retval = self.set_metadata_block(file_id, &metablock);
+ }
+
+ retval
+ }
+
pub fn move_file_to_folder(&self, file_id: LibraryId, folder_id: LibraryId) -> bool {
if let Some(ref conn) = self.dbconn {
if let Ok(mut stmt) = conn.prepare("SELECT id FROM folders WHERE \
@@ -495,6 +655,65 @@ impl Library {
false
}
+ pub fn get_all_labels(&self) -> Vec<Label> {
+ if let Some(ref conn) = self.dbconn {
+ let sql = format!("SELECT {} FROM {} ORDER BY id;",
+ Label::read_db_columns(),
+ Label::read_db_tables());
+ if let Ok(mut stmt) = conn.prepare(&sql) {
+ let mut labels: Vec<Label> = vec!();
+ let mut rows = stmt.query(&[]).unwrap();
+ while let Some(Ok(row)) = rows.next() {
+ let label = Label::read_from(&row);
+ labels.push(label);
+ }
+ return labels;
+ }
+ }
+ vec!()
+ }
+
+ pub fn add_label(&self, name: &str, colour: &str) -> LibraryId {
+ if let Some(ref conn) = self.dbconn {
+ if let Ok(c) = conn.execute("INSERT INTO labels (name,color) \
+ VALUES (:1, :2);",
+ &[&name, &colour]) {
+ if c != 1 {
+ return -1;
+ }
+ let label_id = conn.last_insert_rowid();
+ dbg_out!("last row inserted {}", label_id);
+ return label_id;
+ }
+ }
+ -1
+ }
+
+ pub fn update_label(&self, label_id: LibraryId, name: &str,
+ colour: &str) -> bool {
+ if let Some(ref conn) = self.dbconn {
+ if let Ok(_) = conn.execute("UPDATE labels SET name=:2, color=:3 \
+ FROM labels WHERE id=:1;",
+ &[&label_id, &name, &colour]) {
+ // XXX check success.
+ return true;
+ }
+ }
+ false
+
+ }
+
+ pub fn delete_label(&self, label_id: LibraryId) -> bool {
+ if let Some(ref conn) = self.dbconn {
+ if let Ok(_) = conn.execute("DELETE FROM labels WHERE id=:1;",
+ &[&label_id]) {
+ // XXX check success.
+ return true;
+ }
+ }
+ false
+ }
+
fn get_xmp_ids_in_queue(&self) -> Option<Vec<LibraryId>> {
if let Some(ref conn) = self.dbconn {
if let Ok(mut stmt) = conn.prepare("SELECT id FROM xmp_update_queue;") {
@@ -510,6 +729,10 @@ impl Library {
None
}
+ pub fn write_metadata(&self, id: LibraryId) -> bool {
+ self.rewrite_xmp_for_id(id, true)
+ }
+
fn rewrite_xmp_for_id(&self, id: LibraryId, write_xmp: bool) -> bool {
// XXX
// Rework this so that:
@@ -587,6 +810,24 @@ impl Library {
}
}
+#[no_mangle]
+pub extern fn engine_db_library_new(path: *const c_char, notif_id: u64) -> *mut Library {
+ let l = Box::new(
+ Library::new(PathBuf::from(&*unsafe { CStr::from_ptr(path) }.to_string_lossy()),
+ notif_id));
+ Box::into_raw(l)
+}
+
+#[no_mangle]
+pub extern fn engine_db_library_delete(l: *mut Library) {
+ unsafe { Box::from_raw(l); }
+}
+
+#[no_mangle]
+pub extern fn engine_db_library_ok(l: &Library) -> bool {
+ l.is_ok()
+}
+
#[cfg(test)]
mod test {
use std::path::Path;
@@ -611,7 +852,7 @@ mod test {
fn library_works() {
use super::Library;
- let lib = Library::new(Path::new("."), 0);
+ let lib = Library::new(PathBuf::from("."), 0);
let _autodelete = AutoDelete::new(lib.dbpath());
assert!(lib.is_ok());
diff --git a/src/engine/db/mod.rs b/src/engine/db/mod.rs
index b946445..7b40054 100644
--- a/src/engine/db/mod.rs
+++ b/src/engine/db/mod.rs
@@ -23,6 +23,7 @@ pub mod keyword;
pub mod label;
pub mod libfile;
pub mod libfolder;
+pub mod libmetadata;
pub mod library;
pub type LibraryId = i64;
diff --git a/src/engine/db/properties-def.hpp b/src/engine/db/properties-def.hpp
index ecd56de..373c594 100644
--- a/src/engine/db/properties-def.hpp
+++ b/src/engine/db/properties-def.hpp
@@ -44,7 +44,7 @@ DEFINE_PROPERTY(NpExifExposureBiasProp, MAKE_METADATA_IDX(META_NS_EXIF, META_EXI
DEFINE_PROPERTY(NpExifFlashFiredProp, MAKE_METADATA_IDX(META_NS_EXIF, META_EXIF_FLASHFIRED), NS_EXIF,
"Flash/exif:Fired", int32_t)
DEFINE_PROPERTY(NpExifAuxFlashCompensationProp, MAKE_METADATA_IDX(META_NS_EXIF,
META_EXIF_AUX_FLASHCOMPENSATION), NS_EXIF_AUX, "FlashCompensation", int32_t)
DEFINE_PROPERTY(NpExifWbProp, MAKE_METADATA_IDX(META_NS_EXIF, META_EXIF_WB), NS_EXIF, "WhiteBalance",
int32_t)
-DEFINE_PROPERTY(NpExifDateTimeOriginalProp, MAKE_METADATA_IDX(META_NS_EXIF, META_EXIF_DATETIMEORIGINAL),
NS_EXIF, "DateTimeOriginal", fwk::Date)
+DEFINE_PROPERTY(NpExifDateTimeOriginalProp, MAKE_METADATA_IDX(META_NS_EXIF, META_EXIF_DATETIMEORIGINAL),
NS_EXIF, "DateTimeOriginal", fwk::DatePtr)
DEFINE_PROPERTY(NpExifFocalLengthProp, MAKE_METADATA_IDX(META_NS_EXIF, META_EXIF_FOCALLENGTH), NS_EXIF,
"FocalLength", int32_t)
DEFINE_PROPERTY(NpExifGpsLongProp, MAKE_METADATA_IDX(META_NS_EXIF, META_EXIF_GPSLONGITUDE), NS_EXIF,
"GPSLongitude", std::string)
DEFINE_PROPERTY(NpExifGpsLatProp, MAKE_METADATA_IDX(META_NS_EXIF, META_EXIF_GPSLATITUDE), NS_EXIF,
"GPSLatitude", std::string)
diff --git a/src/engine/importer/cameraimporter.cpp b/src/engine/importer/cameraimporter.cpp
index 96a49ca..433de13 100644
--- a/src/engine/importer/cameraimporter.cpp
+++ b/src/engine/importer/cameraimporter.cpp
@@ -19,6 +19,8 @@
*/
#include <glibmm/miscutils.h>
+#include <giomm/file.h>
+
#include "cameraimporter.hpp"
#include "fwk/base/debug.hpp"
diff --git a/src/engine/library/commands.hpp b/src/engine/library/commands.hpp
index 2f99878..73b1910 100644
--- a/src/engine/library/commands.hpp
+++ b/src/engine/library/commands.hpp
@@ -18,65 +18,34 @@
*/
+#pragma once
-#ifndef __LIBRARY_COMMANDS_H__
-#define __LIBRARY_COMMANDS_H__
-
-#include "op.hpp"
#include "fwk/utils/files.hpp"
#include "engine/db/library.hpp"
-namespace eng {
-
-/** Marshalling and demarshalling of commands ops */
-class Commands
-{
-public:
-
- // commands: execute an op
-// static void cmdQueryFiles(const Library::Ptr & lib);
-// static void cmdUpdateFiles(const Library::Ptr & lib);
-
- static void cmdListAllFolders(const Library::Ptr & lib);
- static void cmdListAllKeywords(const Library::Ptr & lib);
- static void cmdImportFile(const Library::Ptr & lib,
- const std::string & path,
- LibraryManaged manage);
- static void cmdImportFiles(const Library::Ptr & lib,
- const std::string & folder,
- const fwk::FileList::Ptr & files,
- LibraryManaged manage);
- static void cmdQueryFolderContent(const Library::Ptr & lib,
- library_id_t folder_id);
- static void cmdCountFolder(const Library::Ptr & lib,
- library_id_t folder_id);
- static void cmdQueryKeywordContent(const Library::Ptr & lib,
- library_id_t keyword_id);
- static void cmdRequestMetadata(const Library::Ptr & lib,
- library_id_t file_id);
- static void cmdSetMetadata(const Library::Ptr & lib,
- library_id_t file_id, fwk::PropertyIndex meta,
- const fwk::PropertyValue & value);
- static void cmdWriteMetadata(const Library::Ptr & lib,
- library_id_t file_id);
- static void cmdMoveFileToFolder(const Library::Ptr & lib,
- library_id_t file_id, library_id_t from_folder_id,
- library_id_t to_folder_id);
- static void cmdListAllLabels(const Library::Ptr & lib);
- static void cmdCreateLabel(const Library::Ptr & lib, const std::string & s,
- const std::string & color);
- static void cmdDeleteLabel(const Library::Ptr & lib,
- int label_id);
- static void cmdUpdateLabel(const Library::Ptr & lib,
- eng::library_id_t label_id, const std::string & name,
- const std::string & color);
- static void cmdProcessXmpUpdateQueue(const Library::Ptr & lib, bool write_xmp);
-};
-
+extern "C" {
+ bool cmd_list_all_keywords(eng::Library* lib);
+ bool cmd_list_all_folders(eng::Library* lib);
+ bool cmd_import_file(eng::Library* lib, const char* path, eng::LibraryManaged);
+ bool cmd_import_files(eng::Library* lib, const char* folder, fwk::FileList* files,
+ eng::LibraryManaged);
+ bool cmd_request_metadata(eng::Library* lib, eng::library_id_t id);
+ bool cmd_query_folder_content(eng::Library* lib, eng::library_id_t folder_id);
+ bool cmd_count_folder(eng::Library* lib, eng::library_id_t folder_id);
+ bool cmd_query_keyword_content(eng::Library* lib, eng::library_id_t id);
+ bool cmd_write_metadata(eng::Library* lib, eng::library_id_t id);
+ bool cmd_move_file_to_folder(eng::Library* lib, eng::library_id_t id,
+ eng::library_id_t from, eng::library_id_t to);
+ bool cmd_set_metadata(eng::Library* lib, eng::library_id_t id, fwk::PropertyIndex meta,
+ const fwk::PropertyValue* value);
+ bool cmd_list_all_labels(eng::Library* lib);
+ bool cmd_create_label(eng::Library* lib, const char* name, const char* colour);
+ bool cmd_delete_label(eng::Library* lib, eng::library_id_t id);
+ bool cmd_update_label(eng::Library* lib, eng::library_id_t id, const char* name,
+ const char* colour);
+ bool cmd_process_xmp_update_queue(eng::Library* lib, bool write_xmp);
}
-
-#endif
/*
Local Variables:
mode:c++
diff --git a/src/engine/library/commands.rs b/src/engine/library/commands.rs
new file mode 100644
index 0000000..4b8d4c6
--- /dev/null
+++ b/src/engine/library/commands.rs
@@ -0,0 +1,239 @@
+/*
+ * niepce - engine/library/commands.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 std::path::Path;
+
+use engine::db::LibraryId;
+use engine::db::library::{
+ Library,
+ Managed
+};
+use engine::db::filebundle::FileBundle;
+use engine::db::label::Label;
+use engine::db::libfolder::LibFolder;
+use super::notification::Notification as LibNotification;
+use super::notification::{
+ Content,
+ FileMove,
+ FolderCount,
+ MetadataChange,
+};
+use root::eng::LibFile as CLibFile;
+use root::eng::NiepceProperties as Np;
+use root::fwk::{
+ FileList,
+ PropertyValue
+};
+
+#[no_mangle]
+pub fn cmd_list_all_keywords(lib: &Library) -> bool {
+ let list = lib.get_all_keywords();
+ // XXX change this to "LoadKeywords"
+ for kw in list {
+ lib.notify(Box::new(LibNotification::AddedKeyword(kw)));
+ }
+ true
+}
+
+#[no_mangle]
+pub fn cmd_list_all_folders(lib: &Library) -> bool {
+ let list = lib.get_all_folders();
+ // XXX change this to "LoadedFodlers"
+ for folder in list {
+ lib.notify(Box::new(LibNotification::AddedFolder(folder)));
+ }
+ true
+}
+
+#[no_mangle]
+pub fn cmd_import_file(lib: &Library, file_path: *const c_char, manage: Managed) -> bool {
+ dbg_assert!(manage == Managed::NO, "managing file is currently unsupported");
+
+ let path = String::from(unsafe { CStr::from_ptr(file_path) }.to_string_lossy());
+
+ let mut bundle = FileBundle::new();
+ bundle.add(&path);
+
+ let folder = Path::new(&path).parent().unwrap_or(Path::new(""));
+
+ let libfolder: LibFolder;
+ match lib.get_folder(&*folder.to_string_lossy()) {
+ Some(lf) =>
+ libfolder = lf,
+ _ => {
+ if let Some(lf) = lib.add_folder(&*folder.to_string_lossy()) {
+ libfolder = lf.clone();
+ lib.notify(Box::new(LibNotification::AddedFolder(lf)));
+ } else {
+ return false;
+ }
+ }
+ }
+
+ lib.add_bundle(libfolder.id(), &bundle, manage);
+ lib.notify(Box::new(LibNotification::AddedFile));
+ true
+}
+
+#[no_mangle]
+pub fn cmd_import_files(lib: &Library, folder: *const c_char, files: &mut FileList,
+ manage: Managed) -> bool {
+ dbg_assert!(manage == Managed::NO, "managing file is currently unsupported");
+
+ let bundles = FileBundle::filter_bundles(files);
+ let libfolder: LibFolder;
+ let folder = unsafe { CStr::from_ptr(folder) }.to_string_lossy();
+ match lib.get_folder(&folder) {
+ Some(lf) =>
+ libfolder = lf,
+ _ => {
+ if let Some(lf) = lib.add_folder(&folder) {
+ libfolder = lf.clone();
+ lib.notify(Box::new(LibNotification::AddedFolder(lf)));
+ } else {
+ return false;
+ }
+ }
+ }
+ let folder_id = libfolder.id();
+ for bundle in bundles {
+ lib.add_bundle(folder_id, &bundle, manage.clone());
+ }
+ lib.notify(Box::new(LibNotification::AddedFiles));
+ true
+}
+
+#[no_mangle]
+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)));
+ return true;
+ }
+ false
+}
+
+#[no_mangle]
+pub fn cmd_query_folder_content(lib: &Library, folder_id: LibraryId) -> bool {
+ let fl = lib.get_folder_content(folder_id);
+ let mut value = Box::new(
+ LibNotification::FolderContentQueried(unsafe { Content::new(folder_id) }));
+ if let LibNotification::FolderContentQueried(ref mut content) = *value {
+ for f in fl {
+ unsafe { content.push(Box::into_raw(Box::new(f)) as *mut CLibFile) };
+ }
+ }
+ lib.notify(value);
+ true
+}
+
+#[no_mangle]
+pub fn cmd_set_metadata(lib: &Library, id: LibraryId, meta: Np,
+ value: &PropertyValue) -> bool {
+ lib.set_metadata(id, meta, value);
+ lib.notify(Box::new(LibNotification::MetadataChanged(
+ MetadataChange{id: id, meta: meta as u32, value: value.clone()})));
+ true
+}
+
+#[no_mangle]
+pub fn cmd_count_folder(lib: &Library, folder_id: LibraryId) -> bool {
+ let count = lib.count_folder(folder_id);
+ lib.notify(Box::new(LibNotification::FolderCounted(
+ FolderCount{folder: folder_id, count: count})));
+ true
+}
+
+#[no_mangle]
+pub fn cmd_query_keyword_content(lib: &Library, keyword_id: LibraryId) -> bool {
+ let fl = lib.get_keyword_content(keyword_id);
+ let mut content = unsafe { Content::new(keyword_id) };
+ for f in fl {
+ unsafe { content.push(Box::into_raw(Box::new(f)) as *mut CLibFile) };
+ }
+ lib.notify(Box::new(LibNotification::KeywordContentQueried(content)));
+ true
+}
+
+#[no_mangle]
+pub fn cmd_write_metadata(lib: &Library, file_id: LibraryId) -> bool {
+ lib.write_metadata(file_id)
+}
+
+#[no_mangle]
+pub fn cmd_move_file_to_folder(lib: &Library, file_id: LibraryId, from: LibraryId,
+ to: LibraryId) -> bool {
+
+ if lib.move_file_to_folder(file_id, to) {
+ lib.notify(Box::new(LibNotification::FileMoved(
+ FileMove{file: file_id, from: from, to: to})));
+ lib.notify(Box::new(LibNotification::FolderCountChanged(
+ FolderCount{folder: from, count: -1})));
+ lib.notify(Box::new(LibNotification::FolderCountChanged(
+ FolderCount{folder: to, count: 1})));
+ return true;
+ }
+ false
+}
+
+#[no_mangle]
+pub fn cmd_list_all_labels(lib: &Library) -> bool {
+ let l = lib.get_all_labels();
+ // XXX change this notification type
+ for label in l {
+ lib.notify(Box::new(LibNotification::AddedLabel(label)));
+ }
+ true
+}
+
+#[no_mangle]
+pub fn cmd_create_label(lib: &Library, name: *const c_char, colour: *const c_char) -> bool {
+ let name = unsafe { CStr::from_ptr(name) }.to_string_lossy();
+ let colour = unsafe { CStr::from_ptr(colour) }.to_string_lossy();
+ let id = lib.add_label(&name, &colour);
+ if id != -1 {
+ let l = Label::new(id, &name, &colour);
+ lib.notify(Box::new(LibNotification::AddedLabel(l)));
+ }
+ true
+}
+
+#[no_mangle]
+pub fn cmd_delete_label(lib: &Library, label_id: LibraryId) -> bool {
+ lib.delete_label(label_id);
+ lib.notify(Box::new(LibNotification::LabelDeleted(label_id)));
+ true
+}
+
+#[no_mangle]
+pub fn cmd_update_label(lib: &Library, label_id: LibraryId, name: *const c_char,
+ colour: *const c_char) -> bool {
+ let name = unsafe { CStr::from_ptr(name) }.to_string_lossy();
+ let colour = unsafe { CStr::from_ptr(colour) }.to_string_lossy();
+ lib.update_label(label_id, &name, &colour);
+ let label = Label::new(label_id, &name, &colour);
+ lib.notify(Box::new(LibNotification::LabelChanged(label)));
+ true
+}
+
+#[no_mangle]
+pub fn cmd_process_xmp_update_queue(lib: &Library, write_xmp: bool) -> bool {
+ lib.process_xmp_update_queue(write_xmp)
+}
diff --git a/src/engine/library/mod.rs b/src/engine/library/mod.rs
new file mode 100644
index 0000000..d36c58e
--- /dev/null
+++ b/src/engine/library/mod.rs
@@ -0,0 +1,4 @@
+
+
+pub mod commands;
+pub mod notification;
diff --git a/src/engine/library/notification.cpp b/src/engine/library/notification.cpp
index 4444a98..5c13b14 100644
--- a/src/engine/library/notification.cpp
+++ b/src/engine/library/notification.cpp
@@ -18,55 +18,39 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "fwk/base/debug.hpp"
-#include "niepce/notifications.hpp"
#include "engine/library/notification.hpp"
#include "engine/db/keyword.hpp"
+#include "fwk/base/debug.hpp"
#include "fwk/toolkit/notificationcenter.hpp"
+#include "niepce/notifications.hpp"
namespace {
-void notify(uint64_t notif_id, eng::LibNotification&& ln)
+/**
+ * Wrap a pointer (from Rust) into a shared_ptr<>
+ */
+eng::LibNotificationPtr
+engine_library_notification_wrap(eng::LibNotification* n)
+{
+ return eng::LibNotificationPtr(n, &engine_library_notification_delete);
+}
+}
+
+extern "C" void
+engine_library_notify(uint64_t notif_id,
+ eng::LibNotification* notification)
{
+ auto ln = engine_library_notification_wrap(notification);
auto wnc = fwk::NotificationCenter::get_nc(notif_id);
auto nc = wnc.lock();
if (nc) {
DBG_OUT("notif");
// pass the notification
- fwk::Notification::Ptr n(new fwk::Notification(niepce::NOTIFICATION_LIB));
+ fwk::Notification::Ptr n(
+ new fwk::Notification(niepce::NOTIFICATION_LIB));
n->setData(boost::any(ln));
nc->post(std::move(n));
} else {
DBG_OUT("try to send a notification without notification center");
}
}
-
-}
-
-// Rust glue
-extern "C" {
-
-void lib_notification_notify_new_lib_created(uint64_t notif_id)
-{
- eng::LibNotification ln =
- eng::LibNotification::make<eng::LibNotification::Type::NEW_LIBRARY_CREATED>({});
- notify(notif_id, std::move(ln));
-}
-
-void lib_notification_notify_xmp_needs_update(uint64_t notif_id)
-{
- eng::LibNotification ln =
- eng::LibNotification::make<eng::LibNotification::Type::XMP_NEEDS_UPDATE>({});
- notify(notif_id, std::move(ln));
-}
-
-void lib_notification_notify_kw_added(uint64_t notif_id, eng::Keyword* keyword)
-{
- eng::KeywordPtr kw = eng::keyword_wrap(keyword);
- eng::LibNotification ln =
- eng::LibNotification::make<eng::LibNotification::Type::ADDED_KEYWORD>({kw});
- notify(notif_id, std::move(ln));
-}
-
-
-}
diff --git a/src/engine/library/notification.hpp b/src/engine/library/notification.hpp
index f124c66..256af83 100644
--- a/src/engine/library/notification.hpp
+++ b/src/engine/library/notification.hpp
@@ -20,190 +20,95 @@
#pragma once
-#include <boost/variant.hpp>
+#include <memory>
-#include "engine/library/clienttypes.hpp"
-#include "engine/db/libfolder.hpp"
#include "engine/db/libfile.hpp"
-#include "engine/db/libmetadata.hpp"
-#include "engine/db/keyword.hpp"
-#include "engine/db/label.hpp"
+#include "engine/db/librarytypes.hpp"
+#include "engine/library/clienttypes.hpp"
namespace eng {
-
-class LibNotification
-{
-public:
- enum class Type {
- NONE = 0,
- NEW_LIBRARY_CREATED,
- ADDED_FOLDERS,
- ADDED_FILES,
- ADDED_KEYWORDS,
- ADDED_KEYWORD,
- ADDED_LABELS,
- FOLDER_CONTENT_QUERIED,
- KEYWORD_CONTENT_QUERIED,
- METADATA_QUERIED,
- METADATA_CHANGED,
- LABEL_CHANGED,
- LABEL_DELETED,
- XMP_NEEDS_UPDATE,
- FOLDER_COUNTED,
- FOLDER_COUNT_CHANGE,
- FILE_MOVED
- };
-
- struct None {
- };
-
- struct Id {
- library_id_t id;
- };
-
- struct AddedFolders {
- LibFolderListPtr folders;
- };
-
- struct AddedKeyword {
- KeywordPtr keyword;
- };
-
- struct AddedKeywords {
- KeywordListPtr keywords;
- };
-
- struct AddedLabels {
- Label::ListPtr labels;
- };
-
- struct FileMoved {
- library_id_t file;
- library_id_t from;
- library_id_t to;
- };
-
- struct QueriedContent {
- library_id_t container;
- LibFileListPtr files;
- };
-
- struct MetadataContent {
- library_id_t file;
- LibMetadata::Ptr metadata;
- };
-
- typedef metadata_desc_t MetadataChange;
-
- struct FolderCount {
- library_id_t folder;
- int32_t count;
- };
-
- struct LabelChange {
- eng::Label::Ptr label;
- };
-
- // specialise this class template to map the notification parameter type
- // with the notification type.
- // By default type is None.
- template<Type t> struct ParamType {
- typedef None Type;
- };
-
- typedef boost::variant<None, Id, AddedFolders,
- AddedLabels, AddedKeyword, AddedKeywords,
- QueriedContent,
- MetadataContent, MetadataChange,
- LabelChange,
- FileMoved, FolderCount> Param;
-
- Type type;
-
- // Instanciate a notification. Will use the ParamType template to enforce the
- // parameter type.
- template<LibNotification::Type t>
- static LibNotification make(typename LibNotification::ParamType<t>::Type&& p)
- {
- return LibNotification(t, p);
- }
- // Extract the parameter.
- template<LibNotification::Type t>
- const typename LibNotification::ParamType<t>::Type& get() const
- {
- return boost::get<typename LibNotification::ParamType<t>::Type>(param);
- }
-private:
- Param param;
-
- LibNotification(Type t, Param&& p)
- : type(t), param(p) {}
+class Label;
+class LibMetadata;
+class LibFolder;
+class Keyword;
+
+class LibNotification;
+typedef std::shared_ptr<LibNotification> LibNotificationPtr;
+
+enum class LibNotificationType {
+ NONE = 0,
+ NEW_LIBRARY_CREATED,
+ ADDED_FOLDER,
+ ADDED_FILE,
+ ADDED_FILES,
+ ADDED_KEYWORD,
+ ADDED_LABEL,
+ FOLDER_CONTENT_QUERIED,
+ KEYWORD_CONTENT_QUERIED,
+ METADATA_QUERIED,
+ METADATA_CHANGED,
+ LABEL_CHANGED,
+ LABEL_DELETED,
+ XMP_NEEDS_UPDATE,
+ FOLDER_COUNTED,
+ FOLDER_COUNT_CHANGE,
+ FILE_MOVED
};
-template<>
-struct LibNotification::ParamType<LibNotification::Type::ADDED_FOLDERS> {
- typedef AddedFolders Type;
+struct LnFileMove {
+ library_id_t file;
+ library_id_t from;
+ library_id_t to;
};
-template<>
-struct LibNotification::ParamType<LibNotification::Type::ADDED_KEYWORDS> {
- typedef AddedKeywords Type;
+struct LnFolderCount {
+ library_id_t folder;
+ int64_t count;
};
-template<>
-struct LibNotification::ParamType<LibNotification::Type::ADDED_KEYWORD> {
- typedef AddedKeyword Type;
-};
+struct QueriedContent {
+ library_id_t container;
+ LibFileListPtr files;
-template<>
-struct LibNotification::ParamType<LibNotification::Type::ADDED_LABELS> {
- typedef AddedLabels Type;
+ QueriedContent(library_id_t container);
+ void push(LibFile*);
};
+}
-template<>
-struct LibNotification::ParamType<LibNotification::Type::FOLDER_CONTENT_QUERIED> {
- typedef QueriedContent Type;
-};
+extern "C" {
-template<>
-struct LibNotification::ParamType<LibNotification::Type::KEYWORD_CONTENT_QUERIED> {
- typedef QueriedContent Type;
-};
+eng::LibNotificationType
+engine_library_notification_type(const eng::LibNotification* n);
-template<>
-struct LibNotification::ParamType<LibNotification::Type::METADATA_QUERIED> {
- typedef MetadataContent Type;
-};
+// if METADATA_CHANGE return the inner id. otherwise directly attached id.
+eng::library_id_t
+engine_library_notification_get_id(const eng::LibNotification* n);
-template<>
-struct LibNotification::ParamType<LibNotification::Type::METADATA_CHANGED> {
- typedef MetadataChange Type;
-};
+const eng::Label*
+engine_library_notification_get_label(const eng::LibNotification* n);
-template<>
-struct LibNotification::ParamType<LibNotification::Type::LABEL_CHANGED> {
- typedef LabelChange Type;
-};
+const eng::LnFileMove*
+engine_library_notification_get_filemoved(const eng::LibNotification* n);
-template<>
-struct LibNotification::ParamType<LibNotification::Type::LABEL_DELETED> {
- typedef Id Type;
-};
+const eng::LibMetadata*
+engine_library_notification_get_libmetadata(const eng::LibNotification* n);
-template<>
-struct LibNotification::ParamType<LibNotification::Type::FOLDER_COUNTED> {
- typedef FolderCount Type;
-};
+const eng::LnFolderCount*
+engine_library_notification_get_folder_count(const eng::LibNotification* n);
-template<>
-struct LibNotification::ParamType<LibNotification::Type::FOLDER_COUNT_CHANGE> {
- typedef FolderCount Type;
-};
+const eng::metadata_desc_t*
+engine_library_notification_get_metadatachange(const eng::LibNotification* n);
-template<>
-struct LibNotification::ParamType<LibNotification::Type::FILE_MOVED> {
- typedef FileMoved Type;
-};
+const eng::LibFolder*
+engine_library_notification_get_libfolder(const eng::LibNotification* n);
+
+const eng::Keyword*
+engine_library_notification_get_keyword(const eng::LibNotification* n);
+
+const eng::QueriedContent*
+engine_library_notification_get_content(const eng::LibNotification* n);
+void engine_library_notification_delete(eng::LibNotification* n);
+void engine_library_notify(uint64_t notify_id, eng::LibNotification* n);
}
diff --git a/src/engine/library/notification.rs b/src/engine/library/notification.rs
new file mode 100644
index 0000000..f211497
--- /dev/null
+++ b/src/engine/library/notification.rs
@@ -0,0 +1,203 @@
+/*
+ * niepce - engine/library/notification.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_void;
+use engine::db::LibraryId;
+use engine::db::label::Label;
+use engine::db::libfolder::LibFolder;
+use engine::db::libmetadata::LibMetadata;
+use engine::db::keyword::Keyword;
+
+use root::eng::LibNotificationType as NotificationType;
+pub use root::eng::LnFileMove as FileMove;
+pub use root::eng::LnFolderCount as FolderCount;
+pub use root::eng::QueriedContent as Content;
+pub use root::eng::metadata_desc_t as MetadataChange;
+
+pub enum Notification {
+ AddedFile,
+ AddedFiles,
+ AddedFolder(LibFolder),
+ AddedKeyword(Keyword),
+ AddedLabel(Label),
+ FileMoved(FileMove),
+ FolderContentQueried(Content),
+ FolderCounted(FolderCount),
+ FolderCountChanged(FolderCount),
+ KeywordContentQueried(Content),
+ LabelChanged(Label),
+ LabelDeleted(LibraryId),
+ LibCreated,
+ MetadataChanged(MetadataChange),
+ MetadataQueried(LibMetadata),
+ XmpNeedsUpdate,
+}
+
+#[cfg(not(test))]
+extern "C" {
+ // actually a *mut Notification
+ pub fn engine_library_notify(notif_id: u64, n: *mut c_void);
+}
+
+#[cfg(test)]
+#[no_mangle]
+pub fn engine_library_notify(notif_id: u64, n: *mut c_void) {
+ // stub for tests
+}
+
+#[no_mangle]
+pub fn engine_library_notification_delete(n: *mut Notification) {
+ unsafe { Box::from_raw(n); }
+}
+
+
+#[no_mangle]
+pub fn engine_library_notification_type(n: &Notification) -> NotificationType {
+ match *n {
+ Notification::AddedFile => NotificationType::ADDED_FILE,
+ Notification::AddedFiles => NotificationType::ADDED_FILES,
+ Notification::AddedFolder(_) => NotificationType::ADDED_FOLDER,
+ Notification::AddedKeyword(_) => NotificationType::ADDED_KEYWORD,
+ Notification::AddedLabel(_) => NotificationType::ADDED_LABEL,
+ Notification::FileMoved(_) => NotificationType::FILE_MOVED,
+ Notification::FolderContentQueried(_) => NotificationType::FOLDER_CONTENT_QUERIED,
+ Notification::FolderCounted(_) => NotificationType::FOLDER_COUNTED,
+ Notification::FolderCountChanged(_) => NotificationType::FOLDER_COUNT_CHANGE,
+ Notification::KeywordContentQueried(_) => NotificationType::KEYWORD_CONTENT_QUERIED,
+ Notification::LabelChanged(_) => NotificationType::LABEL_CHANGED,
+ Notification::LabelDeleted(_) => NotificationType::LABEL_DELETED,
+ Notification::LibCreated => NotificationType::NEW_LIBRARY_CREATED,
+ Notification::MetadataChanged(_) => NotificationType::METADATA_CHANGED,
+ Notification::MetadataQueried(_) => NotificationType::METADATA_QUERIED,
+ Notification::XmpNeedsUpdate => NotificationType::XMP_NEEDS_UPDATE,
+ }
+}
+
+#[no_mangle]
+pub fn engine_library_notification_get_id(n: &Notification) -> LibraryId {
+ match *n {
+ Notification::MetadataChanged(ref changed) => {
+ changed.id
+ },
+ Notification::LabelDeleted(id) => {
+ id
+ },
+ _ => {
+ unreachable!()
+ }
+ }
+}
+
+#[no_mangle]
+pub fn engine_library_notification_get_label(n: &Notification) -> *const Label {
+ match *n {
+ Notification::AddedLabel(ref l) => {
+ l
+ },
+ _ => {
+ unreachable!()
+ }
+ }
+}
+
+#[no_mangle]
+pub fn engine_library_notification_get_filemoved(n: &Notification) -> *const FileMove {
+ match *n {
+ Notification::FileMoved(ref m) => {
+ m
+ },
+ _ => {
+ unreachable!()
+ }
+ }
+}
+
+#[no_mangle]
+pub fn engine_library_notification_get_libmetadata(n: &Notification) -> *const LibMetadata {
+ match *n {
+ Notification::MetadataQueried(ref m) => {
+ m
+ },
+ _ => {
+ unreachable!()
+ }
+ }
+}
+
+#[no_mangle]
+pub fn engine_library_notification_get_folder_count(n: &Notification) -> *const FolderCount {
+ match *n {
+ Notification::FolderCountChanged(ref c) |
+ Notification::FolderCounted(ref c) => {
+ c
+ },
+ _ => {
+ unreachable!()
+ }
+ }
+}
+
+#[no_mangle]
+pub fn engine_library_notification_get_metadatachange(n: &Notification) -> *const MetadataChange {
+ match *n {
+ Notification::MetadataChanged(ref c) => {
+ c
+ },
+ _ => {
+ unreachable!()
+ }
+ }
+}
+
+#[no_mangle]
+pub fn engine_library_notification_get_libfolder(n: &Notification) -> *const LibFolder {
+ match *n {
+ Notification::AddedFolder(ref f) => {
+ f
+ },
+ _ => {
+ unreachable!()
+ }
+ }
+}
+
+#[no_mangle]
+pub fn engine_library_notification_get_keyword(n: &Notification) -> *const Keyword {
+ match *n {
+ Notification::AddedKeyword(ref f) => {
+ f
+ },
+ _ => {
+ unreachable!()
+ }
+ }
+}
+
+#[no_mangle]
+pub fn engine_library_notification_get_content(n: &Notification) -> *const Content {
+ match *n {
+ Notification::FolderContentQueried(ref c) |
+ Notification::KeywordContentQueried(ref c) => {
+ c
+ },
+ _ => {
+ unreachable!()
+ }
+ }
+}
diff --git a/src/engine/library/op.cpp b/src/engine/library/op.cpp
index d3afaa1..578afe6 100644
--- a/src/engine/library/op.cpp
+++ b/src/engine/library/op.cpp
@@ -23,13 +23,13 @@
namespace eng {
-Op::Op(tid_t _id, const function_t & func)
+Op::Op(tid_t _id, const Function & func)
: m_id(_id),
m_function(func)
{
}
-void Op::operator() (const Library::Ptr &l)
+void Op::operator() (Library* l)
{
if(m_function) {
m_function(l);
diff --git a/src/engine/library/op.hpp b/src/engine/library/op.hpp
index 6767422..e66b4ec 100644
--- a/src/engine/library/op.hpp
+++ b/src/engine/library/op.hpp
@@ -34,20 +34,20 @@ class Op
{
public:
typedef std::unique_ptr< Op > Ptr;
- typedef std::function<void (const Library::Ptr &)> function_t;
+ typedef std::function<bool (Library*)> Function;
- Op(tid_t id, const function_t & func);
+ Op(tid_t id, const Function & func);
tid_t id() const
{ return m_id; }
- void operator() (const Library::Ptr &);
- const function_t & fn() const
+ void operator() (Library*);
+ const Function & fn() const
{ return m_function; }
protected:
private:
tid_t m_id;
- function_t m_function;
+ Function m_function;
};
}
diff --git a/src/engine/library/test_opqueue.cpp b/src/engine/library/test_opqueue.cpp
index 8bc7e1e..f0010d6 100644
--- a/src/engine/library/test_opqueue.cpp
+++ b/src/engine/library/test_opqueue.cpp
@@ -30,7 +30,7 @@ int test_main(int, char *[])
{
OpQueue q;
- Op::Ptr p(new Op(1, [](const Library::Ptr &){}));
+ Op::Ptr p(new Op(1, [](Library*){ return false; }));
BOOST_CHECK(q.empty());
diff --git a/src/engine/library/thumbnailcache.cpp b/src/engine/library/thumbnailcache.cpp
index 0309be7..cdddd1e 100644
--- a/src/engine/library/thumbnailcache.cpp
+++ b/src/engine/library/thumbnailcache.cpp
@@ -44,10 +44,10 @@ ThumbnailCache::~ThumbnailCache()
{
}
-void ThumbnailCache::request(const LibFileListPtr & fl)
+void ThumbnailCache::request(const LibFileList& fl)
{
clear();
- std::for_each(fl->begin(), fl->end(),
+ std::for_each(fl.begin(), fl.end(),
[this] (const auto& f) {
ThumbnailTask::Ptr task(new ThumbnailTask(f, 160, 160));
this->schedule(task);
diff --git a/src/engine/library/thumbnailcache.hpp b/src/engine/library/thumbnailcache.hpp
index ab73e84..14a2e85 100644
--- a/src/engine/library/thumbnailcache.hpp
+++ b/src/engine/library/thumbnailcache.hpp
@@ -58,7 +58,7 @@ public:
ThumbnailCache(const std::string & dir, uint64_t notif_id);
~ThumbnailCache();
- void request(const LibFileListPtr & fl);
+ void request(const LibFileList& fl);
static bool is_thumbnail_cached(const std::string & file, const std::string & thumb);
diff --git a/src/engine/mod.rs b/src/engine/mod.rs
index 8f653fc..dffa614 100644
--- a/src/engine/mod.rs
+++ b/src/engine/mod.rs
@@ -18,4 +18,4 @@
*/
pub mod db;
-
+pub mod library;
diff --git a/src/fwk/base/colour.cpp b/src/fwk/base/colour.cpp
index ba2e6cf..f91d846 100644
--- a/src/fwk/base/colour.cpp
+++ b/src/fwk/base/colour.cpp
@@ -17,53 +17,48 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-#include <vector>
-
-#include <boost/algorithm/string/classification.hpp>
-#include <boost/algorithm/string/split.hpp>
-#include <boost/format.hpp>
-#include <boost/lexical_cast.hpp>
-
#include "fwk/base/colour.hpp"
+#include "fwk/base/rust.hpp"
-namespace fwk {
-
+// Rust glue.
- RgbColour::RgbColour(value_type r, value_type g, value_type b)
- {
- at(0) = r;
- at(1) = g;
- at(2) = b;
- }
+extern "C" {
+fwk::RgbColour* fwk_rgbcolour_new(uint16_t r, uint16_t g, uint16_t b);
+fwk::RgbColour* fwk_rgbcolour_clone(const fwk::RgbColour*);
+void fwk_rgbcolour_delete(fwk::RgbColour*);
+}
- RgbColour::RgbColour(const std::string & s)
- {
- std::vector<std::string> components;
- boost::split(components, s, boost::is_any_of(" "));
- if(components.size() >= 3) {
- try {
- for(int i = 0; i < 3; ++i) {
- at(i) = boost::lexical_cast<value_type>(components[i]);
- }
- return;
- }
- catch(...) {
+namespace fwk {
- }
- }
- // fallback in case of failure
- at(0) = 0;
- at(1) = 0;
- at(2) = 0;
- }
+RgbColourPtr rgbcolour_new(uint16_t r, uint16_t g, uint16_t b)
+{
+ return rgbcolour_wrap(fwk_rgbcolour_new(r, g, b));
+}
+RgbColourPtr rgbcolour_clone(const RgbColour* c)
+{
+ return rgbcolour_wrap(fwk_rgbcolour_clone(c));
+}
- std::string RgbColour::to_string() const
- {
- return str(boost::format("%1% %2% %3%") % at(0) % at(1) % at(2));
- }
+RgbColourPtr rgbcolour_wrap(RgbColour* c)
+{
+ return RgbColourPtr(c, &fwk_rgbcolour_delete);
+}
+std::string rgbcolour_to_string(uint16_t r, uint16_t g, uint16_t b)
+{
+ RgbColour* colour = fwk_rgbcolour_new(r, g, b);
+ std::string s = rgbcolour_to_string(colour);
+ fwk_rgbcolour_delete(colour);
+ return s;
+}
+std::string rgbcolour_to_string(const RgbColour* c)
+{
+ char* p = fwk_rgbcolour_to_string(c);
+ std::string s(p);
+ rust_cstring_delete(p);
+ return s;
+}
}
diff --git a/src/fwk/base/colour.hpp b/src/fwk/base/colour.hpp
index ecb6fed..e758969 100644
--- a/src/fwk/base/colour.hpp
+++ b/src/fwk/base/colour.hpp
@@ -1,7 +1,7 @@
/*
* niepce - fwk/base/colour.hpp
*
- * Copyright (C) 2009-2013 Hubert Figuiere
+ * Copyright (C) 2009-2017 Hubert Figuiere
*
* 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
@@ -17,32 +17,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#pragma once
-
-#ifndef __FWK_BASE_COLOUR_HPP_
-#define __FWK_BASE_COLOUR_HPP_
-
-#include <stdint.h>
-
+#include <memory>
#include <string>
-#include <array>
namespace fwk {
- /** A RgbColour tuple (3 components, 16bpp)
- * To be used only for UI.
- */
- class RgbColour
- : public std::array<uint16_t, 3>
- {
- public:
- RgbColour(value_type r = 0, value_type g = 0, value_type b = 0);
- explicit RgbColour(const std::string & );
+class RgbColour;
+typedef std::shared_ptr<RgbColour> RgbColourPtr;
- std::string to_string() const;
- };
+RgbColourPtr rgbcolour_new(uint16_t r, uint16_t g, uint16_t b);
+RgbColourPtr rgbcolour_clone(const RgbColour*);
+RgbColourPtr rgbcolour_wrap(RgbColour*);
+std::string rgbcolour_to_string(uint16_t r, uint16_t g, uint16_t b);
+std::string rgbcolour_to_string(const RgbColour*);
}
-
-#endif
+extern "C" {
+uint16_t fwk_rgbcolour_component(const fwk::RgbColour*, int32_t idx);
+char* fwk_rgbcolour_to_string(const fwk::RgbColour*);
+}
diff --git a/src/fwk/base/date.cpp b/src/fwk/base/date.cpp
index 2cc2d20..a481561 100644
--- a/src/fwk/base/date.cpp
+++ b/src/fwk/base/date.cpp
@@ -22,9 +22,34 @@
#include "date.hpp"
#include "debug.hpp"
+#include "rust.hpp"
+
+// rust glue
+extern "C" {
+void fwk_date_delete(fwk::Date*);
+char* fwk_date_to_string(const fwk::Date*);
+}
namespace fwk {
+DatePtr date_wrap(fwk::Date* date)
+{
+ return DatePtr(date, fwk_date_delete);
+}
+
+std::string date_to_string(const Date* d)
+{
+ DBG_ASSERT(d, "d is nullptr");
+ if (!d) {
+ return "";
+ }
+ char* p = fwk_date_to_string(d);
+ std::string s(p);
+ rust_cstring_delete(p);
+ return s;
+}
+
+#if 0
time_t make_time_value(const Date & d)
{
time_t date = 0;
@@ -46,6 +71,7 @@ time_t make_time_value(const Date & d)
return date;
}
+#endif
bool make_xmp_date_time(time_t t, XmpDateTime& xmp_dt)
{
@@ -71,6 +97,7 @@ bool make_xmp_date_time(time_t t, XmpDateTime& xmp_dt)
return true;
}
+#if 0
Date::Date(const XmpDateTime& dt, const Timezone* tz)
: m_datetime(dt)
, m_tz(tz)
@@ -96,7 +123,7 @@ std::string Date::to_string() const
return buffer;
}
-
+#endif
}
/*
diff --git a/src/fwk/base/date.hpp b/src/fwk/base/date.hpp
index 89481b3..4d41668 100644
--- a/src/fwk/base/date.hpp
+++ b/src/fwk/base/date.hpp
@@ -1,7 +1,7 @@
/*
* niepce - fwk/base/date.hpp
*
- * Copyright (C) 2012-2013 Hubert Figuiere
+ * Copyright (C) 2012-2017 Hubert Figuiere
*
* 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
@@ -17,9 +17,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __FWK_BASE_DATE_HPP
-#define __FWK_BASE_DATE_HPP
+#pragma once
+#include <memory>
#include <string>
#include <exempi/xmp.h>
@@ -34,28 +34,11 @@ class Timezone;
*/
bool make_xmp_date_time(time_t t, XmpDateTime& xmp_dt);
-/**
- * Class to deal with ISO8601 string dates as used by XMP.
- * Bonus: with a timezone.
- */
-class Date
-{
-public:
- Date(const XmpDateTime& dt, const Timezone* tz = nullptr);
- Date(const time_t dt, const Timezone* tz = nullptr);
-
- std::string to_string() const;
- const XmpDateTime& xmp_date() const
- { return m_datetime; }
-
-private:
- XmpDateTime m_datetime;
- // weak pointer.
- const Timezone* m_tz;
-};
-
-time_t make_time_value(const Date &);
+class Date;
+typedef std::shared_ptr<Date> DatePtr;
+DatePtr date_wrap(Date*);
+std::string date_to_string(const Date*);
}
/*
@@ -67,4 +50,3 @@ time_t make_time_value(const Date &);
fill-column:99
End:
*/
-#endif
diff --git a/src/fwk/base/date.rs b/src/fwk/base/date.rs
index 5d45555..e252332 100644
--- a/src/fwk/base/date.rs
+++ b/src/fwk/base/date.rs
@@ -19,6 +19,7 @@
use exempi;
use libc;
+use std::ffi::CString;
use std::ptr;
use std::time::{
SystemTime,
@@ -129,6 +130,16 @@ pub fn make_xmp_date_time(t: Time, xmp_dt: &mut exempi::DateTime) -> bool {
return true;
}
+#[no_mangle]
+pub fn fwk_date_delete(date: *mut Date) {
+ unsafe { Box::from_raw(date); }
+}
+
+#[no_mangle]
+pub fn fwk_date_to_string(date: &Date) -> *mut libc::c_char {
+ CString::new(date.to_string().as_bytes()).unwrap().into_raw()
+}
+
#[cfg(test)]
mod test {
use super::Date;
diff --git a/src/fwk/base/propertybag.cpp b/src/fwk/base/propertybag.cpp
index 64b6072..36b3ae5 100644
--- a/src/fwk/base/propertybag.cpp
+++ b/src/fwk/base/propertybag.cpp
@@ -38,16 +38,52 @@ bool is_string(const PropertyValue & v)
return v.type() == typeid(std::string);
}
+bool is_string_array(const PropertyValue & v)
+{
+ return v.type() == typeid(StringArray);
+}
+
+bool is_date(const PropertyValue & v)
+{
+ return v.type() == typeid(DatePtr);
+}
+
int get_integer(const PropertyValue & v)
{
return is_empty(v) ? 0 : boost::get<int>(v);
}
+const Date* get_date(const PropertyValue & v)
+{
+ return boost::get<DatePtr>(v).get();
+}
const std::string & get_string(const PropertyValue & v)
{
return boost::get<std::string>(v);
}
+const char* get_string_cstr(const PropertyValue & v)
+{
+ return boost::get<std::string>(v).c_str();
+}
+
+// Rust glue
+const fwk::StringArray & get_string_array(const PropertyValue & v)
+{
+ return boost::get<fwk::StringArray>(v);
+}
+
+size_t string_array_len(const fwk::StringArray &v)
+{
+ return v.size();
+}
+
+const char* string_array_at_cstr(const fwk::StringArray &v, size_t i)
+{
+ return v[i].c_str();
+}
+// end
+
bool PropertyBag::set_value_for_property(PropertyIndex idx, const PropertyValue & value)
{
bool removed = (m_bag.erase(idx) == 1);
diff --git a/src/fwk/base/propertybag.hpp b/src/fwk/base/propertybag.hpp
index 111689a..8f56cf1 100644
--- a/src/fwk/base/propertybag.hpp
+++ b/src/fwk/base/propertybag.hpp
@@ -38,7 +38,39 @@ typedef uint32_t PropertyIndex;
typedef boost::blank EmptyValue;
typedef std::vector<std::string> StringArray;
/** EmptyValue will be the default type */
-typedef boost::variant<EmptyValue, int, std::string, StringArray, Date> PropertyValue;
+class PropertyValue
+ : private boost::variant<EmptyValue, int, std::string, StringArray, DatePtr>
+{
+public:
+#if !RUST_BINDGEN
+ typedef boost::variant<EmptyValue, int, std::string, StringArray, DatePtr> _inner;
+
+ PropertyValue()
+ : _inner()
+ {
+ }
+ template<class T>
+ PropertyValue(const T& data)
+ : _inner(data)
+ {
+ }
+
+ _inner& get_variant()
+ { return *this; }
+ const _inner& get_variant() const
+ { return *this; }
+#endif
+ friend bool is_empty(const PropertyValue & v);
+ friend bool is_integer(const PropertyValue & v);
+ friend bool is_string(const PropertyValue & v);
+ friend bool is_string_array(const PropertyValue & v);
+ friend bool is_date(const PropertyValue & v);
+ friend int get_integer(const PropertyValue & v);
+ friend const Date* get_date(const PropertyValue & v);
+ friend const std::string & get_string(const PropertyValue & v);
+ friend const char* get_string_cstr(const PropertyValue & v);
+ friend const fwk::StringArray & get_string_array(const PropertyValue & v);
+};
typedef std::set<PropertyIndex> PropertySet;
@@ -47,10 +79,19 @@ bool is_empty(const PropertyValue & v);
/** Return if it is an integer */
bool is_integer(const PropertyValue & v);
bool is_string(const PropertyValue & v);
+bool is_string_array(const PropertyValue & v);
+bool is_date(const PropertyValue & v);
+const Date* get_date(const PropertyValue & v);
/** Return the integer value (or 0 if empty) */
int get_integer(const PropertyValue & v);
/** Return the string value */
const std::string & get_string(const PropertyValue & v);
+const char* get_string_cstr(const PropertyValue & v);
+
+// Rust glue
+const fwk::StringArray & get_string_array(const PropertyValue & v);
+size_t string_array_len(const fwk::StringArray &);
+const char* string_array_at_cstr(const fwk::StringArray &, size_t);
/** a property bag
* It is important that the values for PropertyIndex be properly name spaced
diff --git a/src/fwk/base/rgbcolour.rs b/src/fwk/base/rgbcolour.rs
index 0812dce..56aed43 100644
--- a/src/fwk/base/rgbcolour.rs
+++ b/src/fwk/base/rgbcolour.rs
@@ -1,14 +1,33 @@
+/*
+ * niepce - fwk/base/rgbcolour.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::CString;
use std::num::ParseIntError;
use std::str::FromStr;
#[repr(C)]
#[derive(Clone,Default)]
pub struct RgbColour {
- r: u16,
- g: u16,
- b: u16
+ pub r: u16,
+ pub g: u16,
+ pub b: u16
}
#[derive(Debug)]
@@ -22,7 +41,7 @@ pub enum ColourParseError {
}
impl From<ParseIntError> for ColourParseError {
- fn from(e: ParseIntError) -> ColourParseError {
+ fn from(_: ParseIntError) -> ColourParseError {
ColourParseError::ParseIntError
}
}
@@ -49,3 +68,39 @@ impl FromStr for RgbColour {
Ok(RgbColour::new(r, g, b))
}
}
+
+impl ToString for RgbColour {
+ fn to_string(&self) -> String {
+ format!("{} {} {}", self.r, self.g, self.b)
+ }
+}
+
+#[no_mangle]
+pub fn fwk_rgbcolour_to_string(c: &RgbColour) -> *mut c_char {
+ CString::new(c.to_string().as_bytes()).unwrap().into_raw()
+}
+
+#[no_mangle]
+pub fn fwk_rgbcolour_delete(c: *mut RgbColour) {
+ unsafe { Box::from_raw(c); }
+}
+
+#[no_mangle]
+pub fn fwk_rgbcolour_component(c: &RgbColour, idx: i32) -> u16 {
+ match idx {
+ 0 => c.r,
+ 1 => c.g,
+ 2 => c.b,
+ _ => unreachable!()
+ }
+}
+
+#[no_mangle]
+pub fn fwk_rgbcolour_new(r: u16, g: u16, b: u16) -> *mut RgbColour {
+ Box::into_raw(Box::new(RgbColour::new(r, g, b)))
+}
+
+#[no_mangle]
+pub fn fwk_rgbcolour_clone(c: &RgbColour) -> *mut RgbColour {
+ Box::into_raw(Box::new(c.clone()))
+}
diff --git a/src/fwk/base/rust.hpp b/src/fwk/base/rust.hpp
new file mode 100644
index 0000000..6beb923
--- /dev/null
+++ b/src/fwk/base/rust.hpp
@@ -0,0 +1,12 @@
+
+
+#pragma once
+
+#include <memory>
+
+namespace rust {
+
+
+}
+
+extern "C" void rust_cstring_delete(char*);
diff --git a/src/fwk/base/t/testpropertybag.cpp b/src/fwk/base/t/testpropertybag.cpp
index c653c11..a516de7 100644
--- a/src/fwk/base/t/testpropertybag.cpp
+++ b/src/fwk/base/t/testpropertybag.cpp
@@ -27,7 +27,7 @@ int test_main( int, char *[] ) // note the name!
{
fwk::PropertyValue v;
- BOOST_CHECK(v.type() == typeid(fwk::EmptyValue));
+ BOOST_CHECK(v.get_variant().type() == typeid(fwk::EmptyValue));
BOOST_CHECK(is_empty(v));
BOOST_CHECK(get_integer(v) == 0);
diff --git a/src/fwk/toolkit/gdkutils.cpp b/src/fwk/toolkit/gdkutils.cpp
index 67f06d4..780e55b 100644
--- a/src/fwk/toolkit/gdkutils.cpp
+++ b/src/fwk/toolkit/gdkutils.cpp
@@ -83,15 +83,16 @@ namespace fwk {
Gdk::RGBA rgbcolour_to_gdkcolor(const fwk::RgbColour & colour)
{
Gdk::RGBA gdkcolour;
- gdkcolour.set_rgba_u(colour[0], colour[1], colour[2]);
+ gdkcolour.set_rgba_u(fwk_rgbcolour_component(&colour, 0),
+ fwk_rgbcolour_component(&colour, 1),
+ fwk_rgbcolour_component(&colour, 2));
return gdkcolour;
}
- fwk::RgbColour gdkcolor_to_rgbcolour(const Gdk::RGBA & colour)
+ fwk::RgbColourPtr gdkcolor_to_rgbcolour(const Gdk::RGBA & colour)
{
- fwk::RgbColour rgbcolour(colour.get_red_u(), colour.get_green_u(), colour.get_blue_u());
- return rgbcolour;
+ return fwk::rgbcolour_new(colour.get_red_u(), colour.get_green_u(), colour.get_blue_u());
}
diff --git a/src/fwk/toolkit/gdkutils.hpp b/src/fwk/toolkit/gdkutils.hpp
index 092ca85..a1b1f62 100644
--- a/src/fwk/toolkit/gdkutils.hpp
+++ b/src/fwk/toolkit/gdkutils.hpp
@@ -38,7 +38,7 @@ namespace fwk {
int
exif_orientation);
Gdk::RGBA rgbcolour_to_gdkcolor(const fwk::RgbColour & colour);
- fwk::RgbColour gdkcolor_to_rgbcolour(const Gdk::RGBA & colour);
+ fwk::RgbColourPtr gdkcolor_to_rgbcolour(const Gdk::RGBA & colour);
}
#endif
diff --git a/src/fwk/toolkit/metadatawidget.cpp b/src/fwk/toolkit/metadatawidget.cpp
index ff2fe48..d4db88b 100644
--- a/src/fwk/toolkit/metadatawidget.cpp
+++ b/src/fwk/toolkit/metadatawidget.cpp
@@ -325,7 +325,7 @@ bool MetaDataWidget::set_string_array_data(Gtk::Widget* w, const PropertyValue &
{
try {
AutoFlag flag(m_update);
- fwk::StringArray tokens = boost::get<fwk::StringArray>(value);
+ fwk::StringArray tokens = boost::get<fwk::StringArray>(value.get_variant());
static_cast<fwk::TokenTextView*>(w)->set_tokens(tokens);
}
@@ -383,10 +383,10 @@ bool MetaDataWidget::set_date_data(Gtk::Widget* w, const PropertyValue & value)
{
try {
AutoFlag flag(m_update);
- fwk::Date date = boost::get<fwk::Date>(value);
- static_cast<Gtk::Label*>(w)->set_text(date.to_string());
+ fwk::DatePtr date = boost::get<fwk::DatePtr>(value.get_variant());
+ static_cast<Gtk::Label*>(w)->set_text(fwk::date_to_string(date.get()));
- DBG_OUT("setting date data %s", date.to_string().c_str());
+ DBG_OUT("setting date data %s", fwk::date_to_string(date.get()).c_str());
}
catch(...) {
return false;
@@ -452,7 +452,7 @@ bool MetaDataWidget::on_text_changed(GdkEventFocus*,
if(m_update) {
return true;
}
- emit_metadata_changed(prop,
+ emit_metadata_changed(prop,
fwk::PropertyValue(b->get_text()));
return true;
}
diff --git a/src/fwk/utils/Makefile.am b/src/fwk/utils/Makefile.am
index 6e38035..b88dc9f 100644
--- a/src/fwk/utils/Makefile.am
+++ b/src/fwk/utils/Makefile.am
@@ -1,18 +1,16 @@
-DIST_SUBDIRS = db
-
AM_CPPFLAGS = -I$(top_srcdir)/src/ \
@FRAMEWORK_CFLAGS@
TESTS = testfiles testxmp \
testpathutils \
- teststringutils test_db test_db2 test_db3 test_db4 testufrawmeta
+ teststringutils testufrawmeta
EXTRA_DIST = test.xmp test2.ufraw MODULES_HOWTO
check_PROGRAMS = testfiles testxmp \
testpathutils \
- teststringutils test_db test_db2 test_db3 test_db4 testufrawmeta
+ teststringutils testufrawmeta
testfiles_SOURCES = testfiles.cpp
@@ -39,27 +37,6 @@ testpathutils_SOURCES = t/testpathutils.cpp
testpathutils_LDADD = libniepceutils.a \
@FRAMEWORK_LIBS@
-
-test_db_SOURCES = db/test_db.cpp
-test_db_LDADD = libniepceutils.a \
- ../base/libfwkbase.a \
- @FRAMEWORK_LIBS@
-
-test_db2_SOURCES = db/test_db2.cpp
-test_db2_LDADD = libniepceutils.a \
- ../base/libfwkbase.a \
- @FRAMEWORK_LIBS@
-
-test_db3_SOURCES = db/test_db3.cpp
-test_db3_LDADD = libniepceutils.a \
- ../base/libfwkbase.a \
- @FRAMEWORK_LIBS@
-
-test_db4_SOURCES = db/test_db4.cpp
-test_db4_LDADD = libniepceutils.a \
- ../base/libfwkbase.a \
- @FRAMEWORK_LIBS@
-
noinst_LIBRARIES = libniepceutils.a
libniepceutils_a_SOURCES = \
@@ -75,11 +52,6 @@ libniepceutils_a_SOURCES = \
thread.hpp thread.cpp worker.hpp \
pathutils.hpp pathutils.cpp \
databinder.hpp databinder.cpp \
- db/iconnectiondriver.hpp db/iconnectionmanagerdriver.hpp \
- db/insertstatement.cpp db/insertstatement.hpp \
- db/sqlstatement.cpp db/sqlstatement.hpp \
- db/sqlite/sqlitecnxdrv.cpp db/sqlite/sqlitecnxdrv.hpp \
- db/sqlite/sqlitecnxmgrdrv.cpp db/sqlite/sqlitecnxmgrdrv.hpp \
dynamicmodule.hpp dynamicmodule.cpp \
modulefactory.hpp \
modulemanager.hpp modulemanager.cpp \
diff --git a/src/fwk/utils/exempi.cpp b/src/fwk/utils/exempi.cpp
index 12a808a..8ccd79a 100644
--- a/src/fwk/utils/exempi.cpp
+++ b/src/fwk/utils/exempi.cpp
@@ -17,239 +17,45 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
#include <string.h>
#include <time.h>
#include <boost/lexical_cast.hpp>
-#include <glib.h>
#include <giomm/file.h>
+#include <glib.h>
#include <exempi/xmp.h>
#include <exempi/xmpconsts.h>
-#include "fwk/base/debug.hpp"
-#include "fwk/base/date.hpp"
#include "exempi.hpp"
+#include "fwk/base/date.hpp"
+#include "fwk/base/debug.hpp"
#include "pathutils.hpp"
namespace xmp {
-const char * NIEPCE_XMP_NAMESPACE = "http://xmlns.figuiere.net/ns/niepce/1.0";
-const char * NIEPCE_XMP_NS_PREFIX = "niepce";
-
-const char * UFRAW_INTEROP_NAMESPACE = "http://xmlns.figuiere.net/ns/ufraw_interop/1.0";
-const char * UFRAW_INTEROP_NS_PREFIX = "ufrint";
-
-}
-
-namespace fwk {
-
-ExempiManager::ExempiManager(const ns_defs_t* namespaces)
-{
- if(xmp_init()) {
- xmp_register_namespace(xmp::UFRAW_INTEROP_NAMESPACE,
- xmp::UFRAW_INTEROP_NS_PREFIX, nullptr);
- xmp_register_namespace(xmp::NIEPCE_XMP_NAMESPACE,
- xmp::NIEPCE_XMP_NS_PREFIX, nullptr);
-
- if(namespaces != nullptr) {
- for(auto iter = namespaces; iter->ns != nullptr; iter++) {
- // TODO check the return code
- xmp_register_namespace(iter->ns,
- iter->prefix, nullptr);
- }
- }
- }
-}
-
-
-ExempiManager::~ExempiManager()
-{
- xmp_terminate();
-}
-
-
-XmpMeta::XmpMeta()
- : m_xmp(),
- m_keyword_fetched(false)
-{
- m_xmp = xmp_new_empty();
-}
-
-/** @param file the path to the file to open
- * @param sidecar_only we only want the sidecar.
- * It will locate the XMP sidecar for the file.
- */
-XmpMeta::XmpMeta(const std::string & file, bool sidecar_only)
- : m_xmp(nullptr),
- m_keyword_fetched(false)
-{
- if(!sidecar_only) {
- DBG_OUT("trying to load the XMP from the file");
- xmp::ScopedPtr<XmpFilePtr>
- xmpfile(xmp_files_open_new(file.c_str(), XMP_OPEN_READ));
- if(xmpfile != nullptr) {
- m_xmp = xmp_files_get_new_xmp(xmpfile);
- if(xmpfile == nullptr) {
- ERR_OUT("xmpfile is nullptr");
- }
- }
- }
-
- if(m_xmp == nullptr) {
- gsize len = 0;
- char * buffer = nullptr;
- std::string sidecar = fwk::path_replace_extension(file, ".xmp");
-
- try {
- DBG_OUT("creating xmpmeta from %s", sidecar.c_str());
- Glib::RefPtr<Gio::File> f = Gio::File::create_for_path(sidecar);
- std::string etag_out;
- f->load_contents(buffer, len, etag_out);
- }
- catch(const Glib::Exception & e) {
- ERR_OUT("loading XMP failed: %s", e.what().c_str());
- }
- if(buffer) {
- m_xmp = xmp_new_empty();
- if(!xmp_parse(m_xmp, buffer, len)) {
- xmp_free(m_xmp);
- m_xmp = nullptr;
- }
- g_free(buffer);
- }
- }
-}
-
-XmpMeta::~XmpMeta()
-{
- if(m_xmp) {
- xmp_free(m_xmp);
- }
-}
-
-std::string XmpMeta::serialize_inline() const
-{
- std::string buf;
- xmp::ScopedPtr<XmpStringPtr> output(xmp_string_new());
- if(xmp_serialize_and_format(m_xmp, output,
- XMP_SERIAL_OMITPACKETWRAPPER | XMP_SERIAL_OMITALLFORMATTING,
- 0, "", "", 0)) {
- buf = xmp_string_cstr(output);
- }
- return buf;
-}
-
-std::string XmpMeta::serialize() const
-{
- std::string buf;
- xmp::ScopedPtr<XmpStringPtr> output(xmp_string_new());
- if(xmp_serialize_and_format(m_xmp, output,
- XMP_SERIAL_OMITPACKETWRAPPER,
- 0, "\n", " ", 0)) {
- buf = xmp_string_cstr(output);
- }
- return buf;
-}
-
-void XmpMeta::unserialize(const char * buffer)
-{
- if(!buffer)
- return;
- xmp_parse(m_xmp, buffer, strlen(buffer));
-}
-
-
-int32_t XmpMeta::orientation() const
-{
- int32_t _orientation = 0;
- int err = 0;
- if(!xmp_get_property_int32(m_xmp, NS_TIFF, "Orientation",
- &_orientation, nullptr)
- && ((err = xmp_get_error()) != 0)) {
- ERR_OUT("get \"Orientation\" property failed: %d", xmp_get_error());
- }
- return _orientation;
-}
-
+const char* NIEPCE_XMP_NAMESPACE = "http://xmlns.figuiere.net/ns/niepce/1.0";
+const char* NIEPCE_XMP_NS_PREFIX = "niepce";
-std::string XmpMeta::label() const
-{
- std::string _label;
- xmp::ScopedPtr<XmpStringPtr> value(xmp_string_new());
- if(xmp_get_property(m_xmp, NS_XAP, "Label", value, nullptr)) {
- _label = xmp_string_cstr(value);
- }
- return _label;
+const char* UFRAW_INTEROP_NAMESPACE =
+ "http://xmlns.figuiere.net/ns/ufraw_interop/1.0";
+const char* UFRAW_INTEROP_NS_PREFIX = "ufrint";
}
+extern "C" {
-int32_t XmpMeta::rating() const
-{
- int32_t _rating = -1;
- int err = 0;
- if(!xmp_get_property_int32(m_xmp, NS_XAP, "Rating", &_rating, nullptr)
- && ((err = xmp_get_error()) != 0)) {
- ERR_OUT("get \"Rating\" property failed: %d", err);
- }
- return _rating;
-}
-
-int32_t XmpMeta::flag() const
-{
- int32_t _flag = 0;
- int err = 0;
- if(!xmp_get_property_int32(m_xmp, xmp::NIEPCE_XMP_NAMESPACE, "Flag",
- &_flag, nullptr)
- && ((err = xmp_get_error()) != 0)) {
- ERR_OUT("get \"Flag\" property failed: %d", err);
- }
- return _flag;
-}
-
-fwk::Date XmpMeta::creation_date() const
-{
- XmpDateTime value;
- int err = 0;
- if(xmp_get_property_date(m_xmp, NS_EXIF, "DateTimeOriginal",
- &value, nullptr)) {
- return fwk::Date(value);
- }
- else if((err = xmp_get_error()) != 0) {
- ERR_OUT("get \"DateTimeOriginal\" property failed: %d", err);
- }
- return Date(0);
-}
-
-std::string XmpMeta::creation_date_str() const
-{
- std::string s;
- xmp::ScopedPtr<XmpStringPtr> value(xmp_string_new());
- if(xmp_get_property(m_xmp, NS_EXIF, "DateTimeOriginal",
- value, nullptr)) {
- s = xmp_string_cstr(value);
- }
- return s;
+fwk::ExempiManager* fwk_exempi_manager_new();
+void fwk_exempi_manager_delete(fwk::ExempiManager*);
}
+namespace fwk {
-const std::vector< std::string > & XmpMeta::keywords() const
+ExempiManagerPtr exempi_manager_new()
{
- if(!m_keyword_fetched) {
- xmp::ScopedPtr<XmpIteratorPtr>
- iter(xmp_iterator_new(m_xmp, NS_DC, "subject",
- XMP_ITER_JUSTLEAFNODES));
- xmp::ScopedPtr<XmpStringPtr> value(xmp_string_new());
- while(xmp_iterator_next(iter, nullptr, nullptr, value, nullptr)) {
- m_keywords.push_back(xmp_string_cstr(value));
- }
- m_keyword_fetched = true;
- }
- return m_keywords;
+ return ExempiManagerPtr(fwk_exempi_manager_new(),
+ &fwk_exempi_manager_delete);
}
-
}
/*
diff --git a/src/fwk/utils/exempi.hpp b/src/fwk/utils/exempi.hpp
index 2bd9190..327a7f9 100644
--- a/src/fwk/utils/exempi.hpp
+++ b/src/fwk/utils/exempi.hpp
@@ -87,65 +87,24 @@ namespace fwk {
class Date;
-class ExempiManager
-{
-public:
- NON_COPYABLE(ExempiManager);
-
- struct ns_defs_t {
- const char *ns;
- const char *prefix;
- };
- /** construct with namespaces to initialize */
- ExempiManager(const ns_defs_t * namespaces = 0);
- ~ExempiManager();
-};
+class XmpMeta;
+class ExempiManager;
+typedef std::shared_ptr<ExempiManager> ExempiManagerPtr;
-/** a high-level wrapper for xmp */
-class XmpMeta
-{
-public:
- NON_COPYABLE(XmpMeta);
-
- XmpMeta();
- XmpMeta(const std::string& for_file, bool sidecar_only);
- virtual ~XmpMeta();
-
- bool isOk() const
- { return m_xmp != nullptr; }
- XmpPtr xmp() const
- { return m_xmp; }
- /** serialize the XMP inline */
- std::string serialize_inline() const;
- /** serialize the XMP (for the sidecar) */
- std::string serialize() const;
- /** load the XMP from the unserialized buffer
- * (NUL terminated)
- */
- void unserialize(const char *);
-
- int32_t orientation() const;
- std::string label() const;
- /** return the rating, -1 is not found (not set) */
- int32_t rating() const;
- int32_t flag() const;
- fwk::Date creation_date() const;
- std::string creation_date_str() const;
- const std::vector< std::string > & keywords() const;
+ExempiManagerPtr exempi_manager_new();
-private:
+}
- XmpPtr m_xmp;
- // caches
- mutable bool m_keyword_fetched;
- mutable std::vector< std::string > m_keywords;
-};
+extern "C" {
+ double fwk_gps_coord_from_xmp(const char* value);
+ int32_t fwk_xmp_meta_get_orientation(const fwk::XmpMeta*);
+ int32_t fwk_xmp_meta_get_rating(const fwk::XmpMeta*);
+ // the pointer must be released by calling rust_cstring_delete()
+ char* fwk_xmp_meta_get_label(const fwk::XmpMeta*);
+ fwk::Date* fwk_xmp_meta_get_creation_date(const fwk::XmpMeta*);
}
-// implemented in Rust
-extern "C" double fwk_gps_coord_from_xmp(const char* value);
-
/*
Local Variables:
mode:c++
diff --git a/src/fwk/utils/exempi.rs b/src/fwk/utils/exempi.rs
index 2f53046..8cd688e 100644
--- a/src/fwk/utils/exempi.rs
+++ b/src/fwk/utils/exempi.rs
@@ -17,9 +17,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+use libc::c_char;
+use std::ffi::CString;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
+use std::ptr;
use exempi;
use exempi::Xmp;
use fwk::Date;
@@ -31,10 +34,10 @@ static UFRAW_INTEROP_NAMESPACE: &'static str = "http://xmlns.figuiere.net/ns/ufr
static UFRAW_INTEROP_NS_PREFIX: &'static str = "ufrint";
-static NS_TIFF: &'static str = "http://ns.adobe.com/tiff/1.0/";
-static NS_XAP: &'static str = "http://ns.adobe.com/xap/1.0/";
-static NS_EXIF: &'static str = "http://ns.adobe.com/exif/1.0/";
-static NS_DC: &'static str = "http://purl.org/dc/elements/1.1/";
+pub static NS_TIFF: &'static str = "http://ns.adobe.com/tiff/1.0/";
+pub static NS_XAP: &'static str = "http://ns.adobe.com/xap/1.0/";
+pub static NS_EXIF: &'static str = "http://ns.adobe.com/exif/1.0/";
+pub static NS_DC: &'static str = "http://purl.org/dc/elements/1.1/";
pub struct NsDef {
ns: String,
@@ -68,7 +71,7 @@ impl Drop for ExempiManager {
pub struct XmpMeta {
- xmp: Xmp,
+ pub xmp: Xmp,
keywords: Vec<String>,
keywords_fetched: bool,
}
@@ -146,7 +149,7 @@ impl XmpMeta {
}
pub fn label(&self) -> Option<String> {
- let mut flags: exempi::PropFlags = exempi::PropFlags::empty();
+ let mut flags: exempi::PropFlags = exempi::PROP_NONE;
if let Some(xmpstring) = self.xmp.get_property(NS_XAP, "Label", &mut flags) {
return Some(String::from(xmpstring.to_str()));
}
@@ -154,7 +157,7 @@ impl XmpMeta {
}
pub fn rating(&self) -> Option<i32> {
- let mut flags: exempi::PropFlags = exempi::PropFlags::empty();
+ let mut flags: exempi::PropFlags = exempi::PROP_NONE;
return self.xmp.get_property_i32(NS_XAP, "Rating", &mut flags);
}
@@ -268,6 +271,48 @@ pub fn gps_coord_from_xmp(xmps: &str) -> Option<f64> {
None
}
+#[no_mangle]
+pub fn fwk_exempi_manager_new() -> *mut ExempiManager {
+ return Box::into_raw(Box::new(ExempiManager::new(None)))
+}
+
+#[no_mangle]
+pub fn fwk_exempi_manager_delete(em: *mut ExempiManager) {
+ unsafe { Box::from_raw(em); }
+}
+
+#[no_mangle]
+pub fn fwk_xmp_meta_get_orientation(xmp: &XmpMeta) -> i32 {
+ if let Some(o) = xmp.orientation() {
+ return o;
+ }
+ 0
+}
+
+#[no_mangle]
+pub fn fwk_xmp_meta_get_rating(xmp: &XmpMeta) -> i32 {
+ if let Some(r) = xmp.rating() {
+ return r;
+ }
+ 0
+}
+
+
+#[no_mangle]
+pub fn fwk_xmp_meta_get_label(xmp: &XmpMeta) -> *mut c_char {
+ if let Some(s) = xmp.label() {
+ return CString::new(s.as_bytes()).unwrap().into_raw()
+ }
+ ptr::null_mut()
+}
+
+#[no_mangle]
+pub fn fwk_xmp_meta_get_creation_date(xmp: &XmpMeta) -> *mut Date {
+ if let Some(d) = xmp.creation_date() {
+ return Box::into_raw(Box::new(d));
+ }
+ ptr::null_mut()
+}
#[cfg(test)]
mod tests {
diff --git a/src/fwk/utils/files.cpp b/src/fwk/utils/files.cpp
index 6e787f1..c136b0f 100644
--- a/src/fwk/utils/files.cpp
+++ b/src/fwk/utils/files.cpp
@@ -73,6 +73,22 @@ FileList::FileList( const _impltype_t & v )
{
}
+const FileList::value_type::value_type*
+FileList::at_cstr(size_type index) const
+{
+ return _impltype_t::at(index).c_str();
+}
+
+FileList::size_type FileList::size() const
+{
+ return _impltype_t::size();
+}
+
+void FileList::sort()
+{
+ std::sort(_impltype_t::begin(), _impltype_t::end());
+}
+
FileList::Ptr FileList::getFilesFromDirectory(const FileList::value_type& p, std::function<bool (const
Glib::RefPtr<Gio::FileInfo>&)> filter)
{
// if(!exists( p ) ) {
diff --git a/src/fwk/utils/files.hpp b/src/fwk/utils/files.hpp
index ca36219..9b999b4 100644
--- a/src/fwk/utils/files.hpp
+++ b/src/fwk/utils/files.hpp
@@ -21,16 +21,20 @@
#ifndef __UTILS_FILES_H__
#define __UTILS_FILES_H__
-#include <list>
+#include <algorithm>
+#include <vector>
#include <string>
#include <memory>
#include <functional>
+#if !RUST_BINDGEN
#include <giomm/fileinfo.h>
+#endif
namespace fwk {
+#if !RUST_BINDGEN
/** wrapper around g_dir_make_tmp() */
std::string make_tmp_dir(const std::string& base);
@@ -38,14 +42,18 @@ bool filter_none(const Glib::RefPtr<Gio::FileInfo> & file);
bool filter_ext(const Glib::RefPtr<Gio::FileInfo> & file,
const std::string & ext);
bool filter_xmp_out(const Glib::RefPtr<Gio::FileInfo> & file);
+#endif
+
+class FileList;
+typedef std::shared_ptr<FileList> FileListPtr;
class FileList
- : private std::list<std::string>
+ : private std::vector<std::string>
{
public:
- typedef std::shared_ptr< FileList > Ptr;
+ typedef FileListPtr Ptr;
- typedef std::list< std::string > _impltype_t;
+ typedef std::vector<std::string> _impltype_t;
typedef _impltype_t::value_type value_type;
typedef _impltype_t::iterator iterator;
typedef _impltype_t::const_iterator const_iterator;
@@ -55,9 +63,14 @@ public:
{}
FileList(const _impltype_t&);
+#if !RUST_BINDGEN
static Ptr getFilesFromDirectory(const value_type& dir,
std::function<bool (const Glib::RefPtr<Gio::FileInfo>&)> filter);
+#endif
+ value_type at(size_type index) const
+ { return _impltype_t::at(index); }
+ const value_type::value_type* at_cstr(size_type index) const;
const_iterator begin() const
{ return _impltype_t::cbegin(); }
const_iterator end() const
@@ -66,10 +79,8 @@ public:
{ return _impltype_t::cbegin(); }
const_iterator cend() const
{ return _impltype_t::cend(); }
- size_type size() const
- { return _impltype_t::size(); }
- void sort()
- { _impltype_t::sort(); }
+ size_type size() const;
+ void sort();
void push_back(const value_type & v)
{ _impltype_t::push_back(v); }
};
diff --git a/src/lib.rs b/src/lib.rs
index d495a93..b50bfe3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -29,3 +29,11 @@ pub mod fwk;
pub mod engine;
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
+
+use libc::c_char;
+use std::ffi::CString;
+
+#[no_mangle]
+pub fn rust_cstring_delete(string: *mut c_char) {
+ unsafe { CString::from_raw(string); }
+}
diff --git a/src/libraryclient/Makefile.am b/src/libraryclient/Makefile.am
index 44d23a6..f9c2877 100644
--- a/src/libraryclient/Makefile.am
+++ b/src/libraryclient/Makefile.am
@@ -9,10 +9,11 @@ TESTS = test_worker
TEST_LIBS = \
liblibraryclient.a \
$(top_builddir)/src/engine/libniepceengine.a \
+ $(top_builddir)/target/debug/libniepce_rust.a \
+ $(top_builddir)/src/engine/libniepceengineglue.a \
$(top_builddir)/src/fwk/utils/libniepceutils.a \
$(top_builddir)/src/fwk/toolkit/libniepceframework.a \
$(top_builddir)/src/fwk/base/libfwkbase.a \
- $(top_builddir)/target/debug/libniepce_rust.a \
@BOOST_UNIT_TEST_FRAMEWORK_LIBS@ \
@FRAMEWORK_LIBS@ \
@OPENRAW_LIBS@ \
diff --git a/src/libraryclient/clientimpl.cpp b/src/libraryclient/clientimpl.cpp
index df41836..23238ec 100644
--- a/src/libraryclient/clientimpl.cpp
+++ b/src/libraryclient/clientimpl.cpp
@@ -25,9 +25,8 @@
#include "clientimpl.hpp"
#include "locallibraryserver.hpp"
-using fwk::FileList;
+using fwk::FileListPtr;
using eng::Op;
-using eng::Commands;
using eng::LibraryManaged;
using eng::tid_t;
@@ -61,7 +60,7 @@ bool ClientImpl::ok() const
@param func the function to schedule
@return the tid
*/
-tid_t ClientImpl::schedule_op(const Op::function_t & func)
+tid_t ClientImpl::schedule_op(const Op::Function & func)
{
tid_t id = LibraryClient::newTid();
Op::Ptr op(new Op(id, func));
@@ -71,44 +70,44 @@ tid_t ClientImpl::schedule_op(const Op::function_t & func)
tid_t ClientImpl::getAllKeywords()
{
- return schedule_op(&Commands::cmdListAllKeywords);
+ return schedule_op(&cmd_list_all_keywords);
}
tid_t ClientImpl::getAllFolders()
{
- return schedule_op(&Commands::cmdListAllFolders);
+ return schedule_op(&cmd_list_all_folders);
}
tid_t ClientImpl::queryFolderContent(eng::library_id_t folder_id)
{
return schedule_op([folder_id](const auto& lib) {
- Commands::cmdQueryFolderContent(lib, folder_id);
- });
+ return cmd_query_folder_content(lib, folder_id);
+ });
}
tid_t ClientImpl::countFolder(eng::library_id_t folder_id)
{
return schedule_op([folder_id](const auto& lib) {
- Commands::cmdCountFolder(lib, folder_id);
- });
+ return cmd_count_folder(lib, folder_id);
+ });
}
tid_t ClientImpl::queryKeywordContent(eng::library_id_t keyword_id)
{
return schedule_op([keyword_id](const auto& lib) {
- Commands::cmdQueryKeywordContent(lib, keyword_id);
- });
+ return cmd_query_keyword_content(lib, keyword_id);
+ });
}
tid_t ClientImpl::requestMetadata(eng::library_id_t file_id)
{
return schedule_op([file_id](const auto& lib) {
- Commands::cmdRequestMetadata(lib, file_id);
- });
+ return cmd_request_metadata(lib, file_id);
+ });
}
@@ -116,15 +115,15 @@ tid_t ClientImpl::setMetadata(eng::library_id_t file_id, int meta,
const fwk::PropertyValue & value)
{
return schedule_op([file_id, meta, value](const auto& lib) {
- Commands::cmdSetMetadata(lib, file_id, meta, value);
- });
+ return cmd_set_metadata(lib, file_id, meta, &value);
+ });
}
tid_t ClientImpl::write_metadata(eng::library_id_t file_id)
{
return schedule_op([file_id](const auto& lib) {
- Commands::cmdWriteMetadata(lib, file_id);
- });
+ return cmd_write_metadata(lib, file_id);
+ });
}
tid_t ClientImpl::moveFileToFolder(eng::library_id_t file_id,
@@ -132,29 +131,29 @@ tid_t ClientImpl::moveFileToFolder(eng::library_id_t file_id,
eng::library_id_t to_folder_id)
{
return schedule_op([file_id, from_folder_id, to_folder_id](const auto& lib) {
- Commands::cmdMoveFileToFolder(lib, file_id, from_folder_id, to_folder_id);
- });
+ return cmd_move_file_to_folder(lib, file_id, from_folder_id, to_folder_id);
+ });
}
tid_t ClientImpl::getAllLabels()
{
- return schedule_op(&Commands::cmdListAllLabels);
+ return schedule_op(&cmd_list_all_labels);
}
tid_t ClientImpl::createLabel(const std::string & s, const std::string & colour)
{
return schedule_op([s, colour](const auto& lib) {
- Commands::cmdCreateLabel(lib, s, colour);
- });
+ return cmd_create_label(lib, s.c_str(), colour.c_str());
+ });
}
tid_t ClientImpl::deleteLabel(int label_id)
{
return schedule_op([label_id](const auto& lib) {
- Commands::cmdDeleteLabel(lib, label_id);
- });
+ return cmd_delete_label(lib, label_id);
+ });
}
tid_t ClientImpl::updateLabel(eng::library_id_t label_id,
@@ -162,34 +161,34 @@ tid_t ClientImpl::updateLabel(eng::library_id_t label_id,
const std::string & new_colour)
{
return schedule_op([label_id, new_name, new_colour](const auto& lib) {
- Commands::cmdUpdateLabel(lib, label_id, new_name, new_colour);
- });
+ return cmd_update_label(lib, label_id, new_name.c_str(), new_colour.c_str());
+ });
}
tid_t ClientImpl::processXmpUpdateQueue(bool write_xmp)
{
return schedule_op([write_xmp](const auto& lib) {
- Commands::cmdProcessXmpUpdateQueue(lib, write_xmp);
- });
+ return cmd_process_xmp_update_queue(lib, write_xmp);
+ });
}
tid_t ClientImpl::importFile(const std::string & path, LibraryManaged manage)
{
return schedule_op([path, manage](const auto& lib) {
- Commands::cmdImportFile(lib, path, manage);
- });
+ return cmd_import_file(lib, path.c_str(), manage);
+ });
}
tid_t ClientImpl::importFromDirectory(const std::string & dir, LibraryManaged manage)
{
- FileList::Ptr files;
+ FileListPtr files;
- files = FileList::getFilesFromDirectory(dir, &fwk::filter_none);
+ files = fwk::FileList::getFilesFromDirectory(dir, &fwk::filter_none);
return schedule_op([dir, files, manage](const auto& lib) {
- Commands::cmdImportFiles(lib, dir, files, manage);
- });
+ return cmd_import_files(lib, dir.c_str(), files.get(), manage);
+ });
}
}
diff --git a/src/libraryclient/clientimpl.hpp b/src/libraryclient/clientimpl.hpp
index 69a7863..e068a3c 100644
--- a/src/libraryclient/clientimpl.hpp
+++ b/src/libraryclient/clientimpl.hpp
@@ -72,7 +72,7 @@ protected:
std::unique_ptr<LocalLibraryServer> m_localLibrary;
private:
/** do the dirty work of scheduling the op */
- eng::tid_t schedule_op(const eng::Op::function_t & func);
+ eng::tid_t schedule_op(const eng::Op::Function & func);
};
}
diff --git a/src/libraryclient/locallibraryserver.cpp b/src/libraryclient/locallibraryserver.cpp
index 9e449cf..f468ae6 100644
--- a/src/libraryclient/locallibraryserver.cpp
+++ b/src/libraryclient/locallibraryserver.cpp
@@ -27,6 +27,7 @@ namespace libraryclient {
void LocalLibraryServer::execute(const Op::Ptr& _op)
{
- (*_op)(m_library);
+ (*_op)(m_library.get());
}
+
}
diff --git a/src/libraryclient/locallibraryserver.hpp b/src/libraryclient/locallibraryserver.hpp
index fbafb46..8897c0c 100644
--- a/src/libraryclient/locallibraryserver.hpp
+++ b/src/libraryclient/locallibraryserver.hpp
@@ -1,7 +1,7 @@
/*
- * niepce - libraryclient/locallibraryserver.h
+ * niepce - libraryclient/locallibraryserver.hpp
*
- * Copyright (C) 2007-2013 Hubert Figuiere
+ * Copyright (C) 2007-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
@@ -29,21 +29,21 @@ namespace libraryclient {
class LocalLibraryServer : public fwk::Worker<eng::Op> {
public:
- /** create the local server for the library whose dir is specified */
- LocalLibraryServer(const std::string& dir,
- uint64_t notif_id)
- : fwk::Worker<eng::Op>()
- , m_library(eng::Library::Ptr(new eng::Library(dir, notif_id)))
+ /** create the local server for the library whose dir is specified */
+ LocalLibraryServer(const std::string& dir, uint64_t notif_id)
+ : fwk::Worker<eng::Op>()
+ , m_library(eng::library_new(dir.c_str(), notif_id))
{
}
- bool ok() const { return m_library && m_library->ok(); }
+ bool ok() const { return m_library && engine_db_library_ok(m_library.get()); }
protected:
- virtual void execute(const ptr_t& _op) override;
+ virtual void execute(const ptr_t& _op) override;
private:
- eng::Library::Ptr m_library;
+ eng::LibraryPtr m_library;
};
+
}
#endif
diff --git a/src/libraryclient/test_worker.cpp b/src/libraryclient/test_worker.cpp
index e942738..fcea80a 100644
--- a/src/libraryclient/test_worker.cpp
+++ b/src/libraryclient/test_worker.cpp
@@ -40,11 +40,11 @@ int test_main(int, char *[])
BOOST_CHECK(ptempl);
{
fwk::DirectoryDisposer d(ptempl);
- LocalLibraryServer w(std::string("") + ptempl, fwk::NotificationCenter::Ptr());
+ LocalLibraryServer w(std::string("") + ptempl, 0);
BOOST_CHECK(w._tasks().empty());
- Op::Ptr p(new Op(0, [](const Library::Ptr &){}));
+ Op::Ptr p(new Op(0, [](Library*){ return false; }));
w.schedule(p);
}
return 0;
diff --git a/src/libraryclient/uidataprovider.cpp b/src/libraryclient/uidataprovider.cpp
index 466df21..68757ba 100644
--- a/src/libraryclient/uidataprovider.cpp
+++ b/src/libraryclient/uidataprovider.cpp
@@ -28,23 +28,20 @@
namespace libraryclient {
-void UIDataProvider::updateLabel(const eng::Label::Ptr & l)
+void UIDataProvider::updateLabel(const eng::Label & l)
{
// TODO: will work as long as we have 5 labels or something.
- for(auto iter : m_labels) {
- if(iter->id() == l->id()) {
- iter->set_label(l->label());
- iter->set_colour(l->colour());
+ for (auto & label : m_labels) {
+ if (engine_db_label_id(label.get()) == engine_db_label_id(&l)) {
+ label = eng::label_clone(&l);
}
}
}
-void UIDataProvider::addLabels(const eng::Label::ListPtr & l)
+void UIDataProvider::addLabel(const eng::Label & l)
{
- for(auto iter : *l) {
- m_labels.push_back(eng::Label::Ptr(new eng::Label(*iter)));
- }
+ m_labels.push_back(eng::label_clone(&l));
}
@@ -54,7 +51,7 @@ void UIDataProvider::deleteLabel(int id)
for(auto iter = m_labels.begin();
iter != m_labels.end(); ++iter) {
- if((*iter)->id() == id) {
+ if (engine_db_label_id(iter->get()) == id) {
DBG_OUT("remove label %d", id);
iter = m_labels.erase(iter);
break;
@@ -62,14 +59,15 @@ void UIDataProvider::deleteLabel(int id)
}
}
-fwk::Option<fwk::RgbColour> UIDataProvider::colourForLabel(int id) const
+fwk::Option<fwk::RgbColourPtr> UIDataProvider::colourForLabel(int id) const
{
- for(auto iter : m_labels) {
- if(iter->id() == id) {
- return fwk::Option<fwk::RgbColour>(iter->colour());
+ for(auto label : m_labels) {
+ if (engine_db_label_id(label.get()) == id) {
+ return fwk::Option<fwk::RgbColourPtr>(
+ fwk::rgbcolour_clone(engine_db_label_colour(label.get())));
}
}
- return fwk::Option<fwk::RgbColour>();
+ return fwk::Option<fwk::RgbColourPtr>();
}
diff --git a/src/libraryclient/uidataprovider.hpp b/src/libraryclient/uidataprovider.hpp
index 4d85dfd..19f479d 100644
--- a/src/libraryclient/uidataprovider.hpp
+++ b/src/libraryclient/uidataprovider.hpp
@@ -23,12 +23,9 @@
#include <stdint.h>
#include "fwk/base/option.hpp"
+#include "fwk/base/colour.hpp"
#include "engine/db/label.hpp"
-namespace fwk {
-class RgbColour;
-}
-
namespace libraryclient {
class UIDataProvider
@@ -36,14 +33,14 @@ class UIDataProvider
public:
// label management
- void updateLabel(const eng::Label::Ptr &);
- void addLabels(const eng::Label::ListPtr & l);
+ void updateLabel(const eng::Label &);
+ void addLabel(const eng::Label & l);
void deleteLabel(int id);
- fwk::Option<fwk::RgbColour> colourForLabel(int id) const;
- const eng::Label::List & getLabels() const
+ fwk::Option<fwk::RgbColourPtr> colourForLabel(int id) const;
+ const eng::LabelList & getLabels() const
{ return m_labels; }
private:
- eng::Label::List m_labels;
+ eng::LabelList m_labels;
};
}
diff --git a/src/niepce/Makefile.am b/src/niepce/Makefile.am
index 1729e56..cb1a261 100644
--- a/src/niepce/Makefile.am
+++ b/src/niepce/Makefile.am
@@ -24,6 +24,7 @@ niepce_LDADD = \
$(top_builddir)/target/debug/libniepce_rust.a \
$(top_builddir)/src/engine/libniepceengine.a \
$(top_builddir)/src/fwk/utils/libniepceutils.a \
+ $(top_builddir)/src/engine/libniepceengineglue.a \
@FRAMEWORK_LIBS@ \
@GPHOTO_LIBS@ \
@BABL_LIBS@ \
diff --git a/src/niepce/main.cpp b/src/niepce/main.cpp
index 663e6c6..5dc7195 100644
--- a/src/niepce/main.cpp
+++ b/src/niepce/main.cpp
@@ -38,7 +38,7 @@ int main(int argc, char ** argv)
fwk::utils::init();
- fwk::ExempiManager ex_manager(nullptr);
+ fwk::ExempiManagerPtr manager = fwk::exempi_manager_new();
fwk::Application::Ptr app = ui::NiepceApplication::create(argc, argv);
return fwk::Application::main(app,
diff --git a/src/niepce/modules/map/mapmodule.cpp b/src/niepce/modules/map/mapmodule.cpp
index 43896d2..56b6fc5 100644
--- a/src/niepce/modules/map/mapmodule.cpp
+++ b/src/niepce/modules/map/mapmodule.cpp
@@ -20,8 +20,10 @@
#include <gtkmm/box.h>
#include "fwk/base/debug.hpp"
+#include "fwk/utils/exempi.hpp"
#include "fwk/toolkit/application.hpp"
#include "engine/db/properties.hpp"
+#include "engine/db/libmetadata.hpp"
#include "mapmodule.hpp"
namespace mapm {
@@ -69,17 +71,17 @@ MapModule::on_lib_notification(const eng::LibNotification &ln)
if (!m_active) {
return;
}
- switch(ln.type) {
- case eng::LibNotification::Type::METADATA_QUERIED:
+ switch(engine_library_notification_type(&ln)) {
+ case eng::LibNotificationType::METADATA_QUERIED:
{
- auto lm = ln.get<eng::LibNotification::Type::METADATA_QUERIED>().metadata;
+ auto lm = engine_library_notification_get_libmetadata(&ln);
DBG_OUT("received metadata in MapModule");
if (lm) {
fwk::PropertyBag properties;
const fwk::PropertySet propset = { eng::NpExifGpsLongProp,
eng::NpExifGpsLatProp };
- lm->to_properties(propset, properties);
+ eng::libmetadata_to_properties(lm, propset, properties);
double latitude, longitude;
latitude = longitude = NAN;
auto result = properties.get_value_for_property(eng::NpExifGpsLongProp);
diff --git a/src/niepce/notificationcenter.cpp b/src/niepce/notificationcenter.cpp
index 264bc1c..77128a8 100644
--- a/src/niepce/notificationcenter.cpp
+++ b/src/niepce/notificationcenter.cpp
@@ -20,6 +20,7 @@
#include <boost/any.hpp>
#include "fwk/base/debug.hpp"
+#include "engine/library/notification.hpp"
#include "niepce/notifications.hpp"
#include "niepce/notificationcenter.hpp"
@@ -41,16 +42,15 @@ void NotificationCenter::dispatch_notification(const fwk::Notification::Ptr &n)
switch(n->type()) {
case NOTIFICATION_LIB:
{
- eng::LibNotification ln
- = boost::any_cast<eng::LibNotification>(n->data());
- signal_lib_notification (ln);
+ auto ln = boost::any_cast<eng::LibNotificationPtr>(n->data());
+ signal_lib_notification(*ln);
break;
}
case NOTIFICATION_THUMBNAIL:
{
eng::ThumbnailNotification tn
= boost::any_cast<eng::ThumbnailNotification>(n->data());
- signal_thumbnail_notification (tn);
+ signal_thumbnail_notification(tn);
break;
}
default:
diff --git a/src/niepce/notificationcenter.hpp b/src/niepce/notificationcenter.hpp
index 46713d8..7afe4c8 100644
--- a/src/niepce/notificationcenter.hpp
+++ b/src/niepce/notificationcenter.hpp
@@ -26,6 +26,7 @@
#include "fwk/toolkit/notificationcenter.hpp"
#include "engine/db/library.hpp"
+#include "engine/library/notification.hpp"
#include "engine/library/thumbnailnotification.hpp"
diff --git a/src/niepce/ui/dialogs/editlabels.cpp b/src/niepce/ui/dialogs/editlabels.cpp
index 74a5e0d..4e20050 100644
--- a/src/niepce/ui/dialogs/editlabels.cpp
+++ b/src/niepce/ui/dialogs/editlabels.cpp
@@ -69,9 +69,10 @@ void EditLabels::setup_widget()
m_entries[i] = labelentry;
if(has_label) {
- Gdk::RGBA colour = fwk::rgbcolour_to_gdkcolor(m_labels[i]->colour());
+ Gdk::RGBA colour = fwk::rgbcolour_to_gdkcolor(
+ *engine_db_label_colour(m_labels[i].get()));
colourbutton->set_rgba(colour);
- labelentry->set_text(m_labels[i]->label());
+ labelentry->set_text(engine_db_label_label(m_labels[i].get()));
}
colourbutton->signal_color_set().connect(
sigc::bind(sigc::mem_fun(*this, &EditLabels::label_colour_changed), i));
@@ -107,16 +108,18 @@ void EditLabels::update_labels(int /*response*/)
continue;
}
std::string new_colour
- = fwk::gdkcolor_to_rgbcolour(m_colours[i]->get_rgba()).to_string();
+ = fwk::rgbcolour_to_string(
+ fwk::gdkcolor_to_rgbcolour(m_colours[i]->get_rgba()).get());
if(!undo) {
undo = fwk::Application::app()->begin_undo(_("Change Labels"));
}
auto libclient = m_lib_client;
if(has_label) {
- std::string current_name = m_labels[i]->label();
- std::string current_colour = m_labels[i]->colour().to_string();
- auto label_id = m_labels[i]->id();
+ std::string current_name = engine_db_label_label(m_labels[i].get());
+ std::string current_colour =
+ fwk::rgbcolour_to_string(engine_db_label_colour(m_labels[i].get()));
+ auto label_id = engine_db_label_id(m_labels[i].get());
undo->new_command<void>(
[libclient, new_name, new_colour, label_id] () {
diff --git a/src/niepce/ui/dialogs/editlabels.hpp b/src/niepce/ui/dialogs/editlabels.hpp
index dac3f61..2a3cd0e 100644
--- a/src/niepce/ui/dialogs/editlabels.hpp
+++ b/src/niepce/ui/dialogs/editlabels.hpp
@@ -46,7 +46,7 @@ private:
void label_name_changed(size_t idx);
void label_colour_changed(size_t idx);
void update_labels(int /*response*/);
- const eng::Label::List& m_labels;
+ const eng::LabelList& m_labels;
std::array<Gtk::ColorButton*, 5> m_colours;
std::array<Gtk::Entry*, 5> m_entries;
std::array<bool, 5> m_status;
diff --git a/src/niepce/ui/gridviewmodule.cpp b/src/niepce/ui/gridviewmodule.cpp
index ac299a0..5ffd0a6 100644
--- a/src/niepce/ui/gridviewmodule.cpp
+++ b/src/niepce/ui/gridviewmodule.cpp
@@ -54,21 +54,25 @@ GridViewModule::~GridViewModule()
void
GridViewModule::on_lib_notification(const eng::LibNotification &ln)
{
- switch(ln.type) {
- case eng::LibNotification::Type::METADATA_QUERIED:
+ switch(engine_library_notification_type(&ln)) {
+ case eng::LibNotificationType::METADATA_QUERIED:
{
- auto lm = ln.get<eng::LibNotification::Type::METADATA_QUERIED>();
+ auto lm = engine_library_notification_get_libmetadata(&ln);
DBG_OUT("received metadata");
- m_metapanecontroller->display(lm.file, lm.metadata);
+ if (lm) {
+ m_metapanecontroller->display(engine_libmetadata_get_id(lm), lm);
+ } else {
+ ERR_OUT("Invalid LibMetadata (nullptr)");
+ }
break;
}
- case eng::LibNotification::Type::METADATA_CHANGED:
+ case eng::LibNotificationType::METADATA_CHANGED:
{
DBG_OUT("metadata changed");
- auto m = ln.get<eng::LibNotification::Type::METADATA_CHANGED>();
- if(m.id == m_metapanecontroller->displayed_file()) {
+ auto id = engine_library_notification_get_id(&ln);
+ if(id && id == m_metapanecontroller->displayed_file()) {
// FIXME: actually just update the metadata
- m_shell.getLibraryClient()->requestMetadata(m.id);
+ m_shell.getLibraryClient()->requestMetadata(id);
}
break;
}
@@ -80,7 +84,7 @@ GridViewModule::on_lib_notification(const eng::LibNotification &ln)
void GridViewModule::display_none()
{
- m_metapanecontroller->display(0, eng::LibMetadata::Ptr());
+ m_metapanecontroller->display(0, nullptr);
}
diff --git a/src/niepce/ui/imageliststore.cpp b/src/niepce/ui/imageliststore.cpp
index d4a82b2..b14bb32 100644
--- a/src/niepce/ui/imageliststore.cpp
+++ b/src/niepce/ui/imageliststore.cpp
@@ -90,24 +90,23 @@ Gtk::TreePath ImageListStore::get_path_from_id(eng::library_id_t id)
void ImageListStore::on_lib_notification(const eng::LibNotification &ln)
{
- switch (ln.type) {
- case eng::LibNotification::Type::FOLDER_CONTENT_QUERIED:
- case eng::LibNotification::Type::KEYWORD_CONTENT_QUERIED:
+ switch (engine_library_notification_type(&ln)) {
+ case eng::LibNotificationType::FOLDER_CONTENT_QUERIED:
+ case eng::LibNotificationType::KEYWORD_CONTENT_QUERIED:
{
- auto param = ln.get<eng::LibNotification::Type::FOLDER_CONTENT_QUERIED>();
- auto l = param.files;
- if (ln.type == eng::LibNotification::Type::FOLDER_CONTENT_QUERIED) {
- m_current_folder = param.container;
+ auto param = engine_library_notification_get_content(&ln);
+ const auto& l = param->files;
+ if (engine_library_notification_type(&ln) == eng::LibNotificationType::FOLDER_CONTENT_QUERIED) {
+ m_current_folder = param->container;
m_current_keyword = 0;
- } else if (ln.type == eng::LibNotification::Type::KEYWORD_CONTENT_QUERIED) {
+ } else if (engine_library_notification_type(&ln) ==
eng::LibNotificationType::KEYWORD_CONTENT_QUERIED) {
m_current_folder = 0;
- m_current_keyword = param.container;
+ m_current_keyword = param->container;
}
- DBG_OUT("received folder content file # %lu", l->size());
+ DBG_OUT("received folder content file # %lu %p %p", l->size());
// clear the map before the list.
m_idmap.clear();
clear();
- eng::LibFileList::const_iterator iter = l->begin();
for_each(l->begin(), l->end(),
[this] (const eng::LibFilePtr & f) {
Gtk::TreeModel::iterator riter = append();
@@ -120,46 +119,49 @@ void ImageListStore::on_lib_notification(const eng::LibNotification &ln)
m_idmap[engine_db_libfile_id(f.get())] = riter;
});
// at that point clear the cache because the icon view is populated.
- getLibraryClient()->thumbnailCache().request(l);
+ getLibraryClient()->thumbnailCache().request(*l);
break;
}
- case eng::LibNotification::Type::FILE_MOVED:
+ case eng::LibNotificationType::FILE_MOVED:
{
DBG_OUT("File moved. Current folder %ld", m_current_folder);
- auto param = ln.get<eng::LibNotification::Type::FILE_MOVED>();
+ auto param = engine_library_notification_get_filemoved(&ln);
if (m_current_folder == 0) {
return;
}
- if (param.from == m_current_folder) {
+ if (param->from == m_current_folder) {
// remove from list
DBG_OUT("from this folder");
- auto iter = get_iter_from_id(param.file);
+ auto iter = get_iter_from_id(param->file);
if (iter) {
iter = erase(iter);
}
- } else if (param.to == m_current_folder) {
+ } else if (param->to == m_current_folder) {
// XXX add to list. but this isn't likely to happen atm.
}
+ break;
}
- case eng::LibNotification::Type::METADATA_CHANGED:
+ case eng::LibNotificationType::METADATA_CHANGED:
{
- auto m = ln.get<eng::LibNotification::Type::METADATA_CHANGED>();
- fwk::PropertyIndex prop = m.meta;
+ auto m = engine_library_notification_get_metadatachange(&ln);
+ const fwk::PropertyIndex& prop = m->meta;
DBG_OUT("metadata changed %s", eng::_propertyName(prop));
// only interested in a few props
if(is_property_interesting(prop)) {
- std::map<eng::library_id_t, Gtk::TreeIter>::const_iterator iter = m_idmap.find(m.id);
+ std::map<eng::library_id_t, Gtk::TreeIter>::const_iterator iter =
+ m_idmap.find(m->id);
if(iter != m_idmap.end()) {
Gtk::TreeRow row = *(iter->second);
//
eng::LibFilePtr file = row[m_columns.m_libfile];
- engine_db_libfile_set_property(file.get(), prop, boost::get<int32_t>(m.value));
+ engine_db_libfile_set_property(
+ file.get(), prop, boost::get<int32_t>(m->value.get_variant()));
row[m_columns.m_libfile] = file;
}
}
break;
}
- case eng::LibNotification::Type::XMP_NEEDS_UPDATE:
+ case eng::LibNotificationType::XMP_NEEDS_UPDATE:
{
fwk::Configuration & cfg = fwk::Application::app()->config();
int write_xmp = false;
diff --git a/src/niepce/ui/imageliststore.hpp b/src/niepce/ui/imageliststore.hpp
index a3d889f..396d712 100644
--- a/src/niepce/ui/imageliststore.hpp
+++ b/src/niepce/ui/imageliststore.hpp
@@ -29,6 +29,7 @@
#include "fwk/toolkit/controller.hpp"
#include "engine/db/libfile.hpp"
#include "engine/db/library.hpp"
+#include "engine/library/notification.hpp"
#include "engine/library/thumbnailnotification.hpp"
#include "libraryclient/libraryclient.hpp"
diff --git a/src/niepce/ui/librarycellrenderer.cpp b/src/niepce/ui/librarycellrenderer.cpp
index 11f41ee..3535f28 100644
--- a/src/niepce/ui/librarycellrenderer.cpp
+++ b/src/niepce/ui/librarycellrenderer.cpp
@@ -276,7 +276,7 @@ LibraryCellRenderer::render_vfunc(const Cairo::RefPtr<Cairo::Context>& cr,
auto result = m_shell.get_ui_data_provider()->colourForLabel(label_id);
DBG_ASSERT(!result.empty(), "colour not found");
if (!result.empty()) {
- drawLabel(cr, left, result.unwrap(), r);
+ drawLabel(cr, left, *result.unwrap(), r);
}
}
}
diff --git a/src/niepce/ui/metadatapanecontroller.cpp b/src/niepce/ui/metadatapanecontroller.cpp
index d5d9b6f..a44e679 100644
--- a/src/niepce/ui/metadatapanecontroller.cpp
+++ b/src/niepce/ui/metadatapanecontroller.cpp
@@ -143,14 +143,14 @@ void MetaDataPaneController::on_metadata_changed(const fwk::PropertyBag & props,
}
-void MetaDataPaneController::display(eng::library_id_t file_id, const eng::LibMetadata::Ptr & meta)
+void MetaDataPaneController::display(eng::library_id_t file_id, const eng::LibMetadata* meta)
{
m_fileid = file_id;
DBG_OUT("displaying metadata");
fwk::PropertyBag properties;
if(meta) {
const fwk::PropertySet & propset = get_property_set();
- meta->to_properties(propset, properties);
+ libmetadata_to_properties(meta, propset, properties);
}
std::for_each(m_widgets.begin(), m_widgets.end(),
[properties] (auto w) {
diff --git a/src/niepce/ui/metadatapanecontroller.hpp b/src/niepce/ui/metadatapanecontroller.hpp
index 936557d..a9c3afe 100644
--- a/src/niepce/ui/metadatapanecontroller.hpp
+++ b/src/niepce/ui/metadatapanecontroller.hpp
@@ -44,7 +44,7 @@ public:
MetaDataPaneController();
~MetaDataPaneController();
virtual Gtk::Widget * buildWidget() override;
- void display(eng::library_id_t file_id, const eng::LibMetadata::Ptr & meta);
+ void display(eng::library_id_t file_id, const eng::LibMetadata* meta);
eng::library_id_t displayed_file() const
{ return m_fileid; }
diff --git a/src/niepce/ui/niepcewindow.cpp b/src/niepce/ui/niepcewindow.cpp
index 664b619..5bcfdf3 100644
--- a/src/niepce/ui/niepcewindow.cpp
+++ b/src/niepce/ui/niepcewindow.cpp
@@ -326,36 +326,48 @@ void NiepceWindow::on_open_library()
void NiepceWindow::create_initial_labels()
{
// TODO make this parametric from resources
- m_libClient->createLabel(_("Label 1"), fwk::RgbColour(55769, 9509, 4369).to_string()); /* 217, 37, 17 */
- m_libClient->createLabel(_("Label 2"), fwk::RgbColour(24929, 55769, 4369).to_string()); /* 97, 217, 17 */
- m_libClient->createLabel(_("Label 3"), fwk::RgbColour(4369, 50629, 55769).to_string()); /* 17, 197, 217
*/
- m_libClient->createLabel(_("Label 4"), fwk::RgbColour(35209, 4369, 55769).to_string()); /* 137, 17, 217
*/
- m_libClient->createLabel(_("Label 5"), fwk::RgbColour(55769, 35209, 4369).to_string()); /* 217, 137, 17
*/
+ m_libClient->createLabel(_("Label 1"), fwk::rgbcolour_to_string(55769, 9509, 4369)); /* 217, 37, 17 */
+ m_libClient->createLabel(_("Label 2"), fwk::rgbcolour_to_string(24929, 55769, 4369)); /* 97, 217, 17 */
+ m_libClient->createLabel(_("Label 3"), fwk::rgbcolour_to_string(4369, 50629, 55769)); /* 17, 197, 217 */
+ m_libClient->createLabel(_("Label 4"), fwk::rgbcolour_to_string(35209, 4369, 55769)); /* 137, 17, 217 */
+ m_libClient->createLabel(_("Label 5"), fwk::rgbcolour_to_string(55769, 35209, 4369)); /* 217, 137, 17 */
}
-void NiepceWindow::on_lib_notification(const eng::LibNotification & ln)
+void NiepceWindow::on_lib_notification(const eng::LibNotification& ln)
{
- switch(ln.type) {
- case eng::LibNotification::Type::NEW_LIBRARY_CREATED:
+ switch(engine_library_notification_type(&ln)) {
+ case eng::LibNotificationType::NEW_LIBRARY_CREATED:
create_initial_labels();
break;
- case eng::LibNotification::Type::ADDED_LABELS:
+ case eng::LibNotificationType::ADDED_LABEL:
{
- auto l = ln.get<eng::LibNotification::Type::ADDED_LABELS>();
- m_libClient->getDataProvider()->addLabels(l.labels);
+ auto l = engine_library_notification_get_label(&ln);
+ if (l) {
+ m_libClient->getDataProvider()->addLabel(*l);
+ } else {
+ ERR_OUT("Invalid label (nullptr)");
+ }
break;
}
- case eng::LibNotification::Type::LABEL_CHANGED:
+ case eng::LibNotificationType::LABEL_CHANGED:
{
- auto l = ln.get<eng::LibNotification::Type::LABEL_CHANGED>();
- m_libClient->getDataProvider()->updateLabel(l.label);
+ auto l = engine_library_notification_get_label(&ln);
+ if (l) {
+ m_libClient->getDataProvider()->updateLabel(*l);
+ } else {
+ ERR_OUT("Invalid label (nullptr)");
+ }
break;
}
- case eng::LibNotification::Type::LABEL_DELETED:
+ case eng::LibNotificationType::LABEL_DELETED:
{
- auto id = ln.get<eng::LibNotification::Type::LABEL_DELETED>();
- m_libClient->getDataProvider()->deleteLabel(id.id);
+ auto id = engine_library_notification_get_id(&ln);
+ if (id) {
+ m_libClient->getDataProvider()->deleteLabel(id);
+ } else {
+ ERR_OUT("Invalid ID");
+ }
break;
}
default:
diff --git a/src/niepce/ui/niepcewindow.hpp b/src/niepce/ui/niepcewindow.hpp
index 8454ae7..cb022d5 100644
--- a/src/niepce/ui/niepcewindow.hpp
+++ b/src/niepce/ui/niepcewindow.hpp
@@ -32,6 +32,7 @@
#include "fwk/toolkit/appframe.hpp"
#include "fwk/toolkit/configdatabinder.hpp"
#include "engine/db/label.hpp"
+#include "engine/library/notification.hpp"
#include "libraryclient/libraryclient.hpp"
#include "ui/moduleshell.hpp"
#include "ui/workspacecontroller.hpp"
diff --git a/src/niepce/ui/selectioncontroller.cpp b/src/niepce/ui/selectioncontroller.cpp
index 98ebc2c..9fb9d28 100644
--- a/src/niepce/ui/selectioncontroller.cpp
+++ b/src/niepce/ui/selectioncontroller.cpp
@@ -224,8 +224,8 @@ bool SelectionController::_set_metadata(const std::string & undo_label,
if (!result.empty()) {
value = result.unwrap();
- if(value.type() != typeid(fwk::EmptyValue)) {
- DBG_ASSERT(value.type() == iter.second.type(),
+ if(value.get_variant().type() != typeid(fwk::EmptyValue)) {
+ DBG_ASSERT(value.get_variant().type() == iter.second.get_variant().type(),
"Value type mismatch");
}
}
diff --git a/src/niepce/ui/workspacecontroller.cpp b/src/niepce/ui/workspacecontroller.cpp
index 0fe83bf..a6d637e 100644
--- a/src/niepce/ui/workspacecontroller.cpp
+++ b/src/niepce/ui/workspacecontroller.cpp
@@ -27,6 +27,7 @@
#include "fwk/base/debug.hpp"
#include "niepce/notifications.hpp"
#include "engine/db/librarytypes.hpp"
+#include "engine/library/notification.hpp"
#include "libraryclient/libraryclient.hpp"
#include "fwk/toolkit/application.hpp"
#include "niepcewindow.hpp"
@@ -83,57 +84,43 @@ fwk::Configuration::Ptr WorkspaceController::getLibraryConfig() const
void WorkspaceController::on_lib_notification(const eng::LibNotification &ln)
{
DBG_OUT("notification for workspace");
- switch(ln.type) {
- case eng::LibNotification::Type::ADDED_FOLDERS:
+ switch(engine_library_notification_type(&ln)) {
+ case eng::LibNotificationType::ADDED_FOLDER:
{
- auto l = ln.get<eng::LibNotification::Type::ADDED_FOLDERS>().folders;
- DBG_OUT("received added folders # %lu", l->size());
- for_each(l->cbegin(), l->cend(),
- [this] (const eng::LibFolderPtr& f) {
- this->add_folder_item(f);
- });
+ auto f = engine_library_notification_get_libfolder(&ln);
+ this->add_folder_item(f);
break;
}
- case eng::LibNotification::Type::ADDED_KEYWORD:
+ case eng::LibNotificationType::ADDED_KEYWORD:
{
- auto k = ln.get<eng::LibNotification::Type::ADDED_KEYWORD>().keyword;
- DBG_ASSERT(static_cast<bool>(k), "keyword must not be NULL");
+ auto k = engine_library_notification_get_keyword(&ln);
+ DBG_ASSERT(k, "keyword must not be NULL");
add_keyword_item(k);
break;
}
- case eng::LibNotification::Type::ADDED_KEYWORDS:
+ case eng::LibNotificationType::FOLDER_COUNTED:
{
- auto l = ln.get<eng::LibNotification::Type::ADDED_KEYWORDS>().keywords;
- DBG_ASSERT(static_cast<bool>(l), "keyword list must not be NULL");
- for_each(l->cbegin(), l->cend(),
- [this] (const eng::KeywordPtr& k) {
- this->add_keyword_item(k);
- });
- break;
- }
- case eng::LibNotification::Type::FOLDER_COUNTED:
- {
- auto count = ln.get<eng::LibNotification::Type::FOLDER_COUNTED>();
- DBG_OUT("count for folder %Ld is %d", (long long)count.folder, count.count);
+ auto count = engine_library_notification_get_folder_count(&ln);
+ DBG_OUT("count for folder %Ld is %d", (long long)count->folder, count->count);
std::map<eng::library_id_t, Gtk::TreeIter>::const_iterator iter
- = m_folderidmap.find(count.folder);
+ = m_folderidmap.find(count->folder);
if(iter != m_folderidmap.cend()) {
Gtk::TreeRow row = *(iter->second);
- row[m_librarycolumns.m_count_n] = count.count;
- row[m_librarycolumns.m_count] = std::to_string(count.count);
+ row[m_librarycolumns.m_count_n] = count->count;
+ row[m_librarycolumns.m_count] = std::to_string(count->count);
}
break;
}
- case eng::LibNotification::Type::FOLDER_COUNT_CHANGE:
+ case eng::LibNotificationType::FOLDER_COUNT_CHANGE:
{
- auto count = ln.get<eng::LibNotification::Type::FOLDER_COUNT_CHANGE>();
- DBG_OUT("count change for folder %Ld is %d", (long long)count.folder, count.count);
+ auto count = engine_library_notification_get_folder_count(&ln);
+ DBG_OUT("count change for folder %Ld is %d", (long long)count->folder, count->count);
std::map<eng::library_id_t, Gtk::TreeIter>::const_iterator iter
- = m_folderidmap.find(count.folder);
+ = m_folderidmap.find(count->folder);
if(iter != m_folderidmap.cend()) {
Gtk::TreeRow row = *(iter->second);
- int new_count = row[m_librarycolumns.m_count_n] + count.count;
+ int new_count = row[m_librarycolumns.m_count_n] + count->count;
row[m_librarycolumns.m_count_n] = new_count;
row[m_librarycolumns.m_count] = std::to_string(new_count);
}
@@ -209,39 +196,39 @@ void WorkspaceController::on_row_collapsed(const Gtk::TreeIter& iter,
}
-void WorkspaceController::add_keyword_item(const eng::KeywordPtr & k)
+void WorkspaceController::add_keyword_item(const eng::Keyword* k)
{
auto children = m_keywordsNode->children();
bool was_empty = children.empty();
auto iter = add_item(m_treestore, children,
m_icons[ICON_KEYWORD],
- engine_db_keyword_keyword(k.get()),
- engine_db_keyword_id(k.get()), KEYWORD_ITEM);
+ engine_db_keyword_keyword(k),
+ engine_db_keyword_id(k), KEYWORD_ITEM);
// getLibraryClient()->countKeyword(f->id());
- m_keywordsidmap[engine_db_keyword_id(k.get())] = iter;
+ m_keywordsidmap[engine_db_keyword_id(k)] = iter;
if(was_empty) {
expand_from_cfg("workspace_keywords_expanded", m_keywordsNode);
}
}
-void WorkspaceController::add_folder_item(const eng::LibFolderPtr & f)
+void WorkspaceController::add_folder_item(const eng::LibFolder* f)
{
int icon_idx = ICON_ROLL;
- if(engine_db_libfolder_virtual_type(f.get()) == (int32_t)eng::LibFolderVirtualType::TRASH) {
+ if(engine_db_libfolder_virtual_type(f) == (int32_t)eng::LibFolderVirtualType::TRASH) {
icon_idx = ICON_TRASH;
- getLibraryClient()->set_trash_id(engine_db_libfolder_id(f.get()));
+ getLibraryClient()->set_trash_id(engine_db_libfolder_id(f));
}
auto children = m_folderNode->children();
bool was_empty = children.empty();
auto iter = add_item(m_treestore, children,
m_icons[icon_idx],
- engine_db_libfolder_name(f.get()),
- engine_db_libfolder_id(f.get()), FOLDER_ITEM);
- if(engine_db_libfolder_expanded(f.get())) {
+ engine_db_libfolder_name(f),
+ engine_db_libfolder_id(f), FOLDER_ITEM);
+ if(engine_db_libfolder_expanded(f)) {
m_librarytree.expand_row(m_treestore->get_path(iter), false);
}
- getLibraryClient()->countFolder(engine_db_libfolder_id(f.get()));
- m_folderidmap[engine_db_libfolder_id(f.get())] = iter;
+ getLibraryClient()->countFolder(engine_db_libfolder_id(f));
+ m_folderidmap[engine_db_libfolder_id(f)] = iter;
// expand if needed. Because Gtk is stupid and doesn't expand empty
if(was_empty) {
expand_from_cfg("workspace_folders_expanded", m_folderNode);
diff --git a/src/niepce/ui/workspacecontroller.hpp b/src/niepce/ui/workspacecontroller.hpp
index 3430a6f..b2a2733 100644
--- a/src/niepce/ui/workspacecontroller.hpp
+++ b/src/niepce/ui/workspacecontroller.hpp
@@ -98,9 +98,9 @@ private:
fwk::Configuration::Ptr getLibraryConfig() const;
/** add a folder item to the treeview */
- void add_folder_item(const eng::LibFolderPtr & f);
+ void add_folder_item(const eng::LibFolder* f);
/** add a keyword item to the treeview */
- void add_keyword_item(const eng::KeywordPtr & k);
+ void add_keyword_item(const eng::Keyword* k);
/** add a tree item in the treeview
* @param treestore the treestore to add to
* @param childrens the children subtree to add to
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]