[niepce] eng+rust: LibMetadata::to_properties now implemented in Rust



commit c200bbb47fd67b0ab7101babfdc4752c90f1c0c7
Author: Hubert Figuière <hub figuiere net>
Date:   Sun Sep 24 19:36:41 2017 -0400

    eng+rust: LibMetadata::to_properties now implemented in Rust
    
    - PropertySet is now a Rust type

 src/engine/db/libmetadata.cpp            |  113 ++----------------------------
 src/engine/db/libmetadata.hpp            |   14 ++---
 src/engine/db/libmetadata.rs             |   98 ++++++++++++++++++++++++--
 src/fwk/base/mod.rs                      |   18 +++++
 src/fwk/base/propertybag.cpp             |   10 +++
 src/fwk/base/propertybag.hpp             |   12 ++--
 src/fwk/mod.rs                           |    1 +
 src/niepce/modules/map/mapmodule.cpp     |    9 ++-
 src/niepce/ui/metadatapanecontroller.cpp |   18 +++---
 src/niepce/ui/metadatapanecontroller.hpp |    2 +-
 src/rust_bindings.hpp                    |    1 +
 11 files changed, 152 insertions(+), 144 deletions(-)
---
diff --git a/src/engine/db/libmetadata.cpp b/src/engine/db/libmetadata.cpp
index 681cec4..f05efb8 100644
--- a/src/engine/db/libmetadata.cpp
+++ b/src/engine/db/libmetadata.cpp
@@ -61,122 +61,21 @@ IndexToXmp property_index_to_xmp(fwk::PropertyIndex index)
     PropsToXmpMap::const_iterator iter = propmap.find(index);
     if (iter == propmap.end()) {
         // not found
-        return {ns : nullptr, property : nullptr};
+        return {ns: nullptr, property: nullptr};
     }
     if (iter->second.first == NULL || iter->second.second == NULL) {
         // no XMP equivalent
-        return {ns : nullptr, property : nullptr};
+        return {ns: nullptr, property: nullptr};
     }
-    return {ns : iter->second.first, property : iter->second.second};
+    return {ns: iter->second.first, property: iter->second.second};
 }
 
-bool get_meta_data(const LibMetadata *meta, fwk::PropertyIndex p,
-                   fwk::PropertyValuePtr &value)
+fwk::PropertyBagPtr libmetadata_to_properties(const LibMetadata* meta,
+                                              const fwk::PropertySet& propset)
 {
-    const PropsToXmpMap &propmap = props_to_xmp_map();
-    PropsToXmpMap::const_iterator iter = propmap.find(p);
-    if (iter == propmap.end()) {
-        // not found
-        return false;
-    }
-    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(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;
-        v = xmp_string_cstr(xmp_value);
-        if (v) {
-            value = fwk::property_value_new(v);
-            return true;
-        }
-    }
-    // not found in XMP
-    return false;
+    return fwk::property_bag_wrap(ffi::engine_libmetadata_to_properties(meta, &propset));
 }
 
-void libmetadata_to_properties(const LibMetadata *meta,
-                               const fwk::PropertySet &propset,
-                               fwk::PropertyBagPtr &props)
-{
-    if (!props) {
-        props = fwk::property_bag_new();
-    }
-    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:
-                fwk::set_value_for_property(
-                    *props, prop_id,
-                    *fwk::property_value_new(fwk_xmp_meta_get_rating(xmpmeta)));
-                break;
-            case NpXmpLabelProp: {
-                char *str = fwk_xmp_meta_get_label(xmpmeta);
-                if (str) {
-                    fwk::set_value_for_property(*props, prop_id,
-                                                *fwk::property_value_new(str));
-                    rust_cstring_delete(str);
-                } else {
-                    fwk::set_value_for_property(*props, prop_id,
-                                                *fwk::property_value_new(""));
-                }
-                break;
-            }
-            case NpTiffOrientationProp:
-                fwk::set_value_for_property(
-                    *props, prop_id,
-                    *fwk::property_value_new(fwk_xmp_meta_get_orientation(xmpmeta)));
-                break;
-            case NpExifDateTimeOriginalProp: {
-                fwk::DatePtr date =
-                    fwk::date_wrap(fwk_xmp_meta_get_creation_date(xmpmeta));
-                if (date) {
-                    fwk::set_value_for_property(*props, prop_id, *fwk::property_value_new(date));
-                }
-                break;
-            }
-            case NpIptcKeywordsProp: {
-                xmp::ScopedPtr<XmpIteratorPtr> iter(
-                    xmp_iterator_new(engine_libmetadata_get_xmp(meta), NS_DC,
-                                     "subject", XMP_ITER_JUSTLEAFNODES));
-                std::vector<std::string> 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::PropertyValuePtr v = fwk::property_value_new(vec);
-                // DBG_ASSERT(check_property_type(prop_id, v.type()), "wrong
-                // type");
-                fwk::set_value_for_property(*props, prop_id, *v);
-                break;
-            }
-            default: {
-                fwk::PropertyValuePtr propval;
-                if (get_meta_data(meta, prop_id, propval)) {
-                    // DBG_ASSERT(check_property_type(prop_id, propval.type()),
-                    // "wrong type");
-                    fwk::set_value_for_property(*props, 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 fc32282..273a2d9 100644
--- a/src/engine/db/libmetadata.hpp
+++ b/src/engine/db/libmetadata.hpp
@@ -36,23 +36,19 @@ namespace eng {
 class LibMetadata;
 #endif
 
-void libmetadata_to_properties(const LibMetadata *meta,
-                               const fwk::PropertySet &propset,
-                               fwk::PropertyBagPtr &props);
-
 struct IndexToXmp {
     const char *ns;
     const char *property;
 };
 IndexToXmp property_index_to_xmp(fwk::PropertyIndex index);
-}
 
-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);
+
+fwk::PropertyBagPtr libmetadata_to_properties(const LibMetadata *meta,
+                                              const fwk::PropertySet &propset);
+
 }
 
+
 /*
   Local Variables:
   mode:c++
diff --git a/src/engine/db/libmetadata.rs b/src/engine/db/libmetadata.rs
index 846b6f0..f80b332 100644
--- a/src/engine/db/libmetadata.rs
+++ b/src/engine/db/libmetadata.rs
@@ -18,16 +18,19 @@
  */
 
 use std::ffi::CStr;
+use std::mem::transmute;
 use rusqlite;
 use exempi;
 
 use fwk;
 use fwk::{
     PropertyValue,
+    PropertyBag,
+    PropertySet,
     XmpMeta,
     make_xmp_date_time
 };
-use fwk::utils::exempi::NS_XAP;
+use fwk::utils::exempi::{NS_XAP, NS_DC};
 use super::{
     FromDb,
     LibraryId
@@ -56,7 +59,6 @@ fn property_index_to_xmp(meta: Np) -> Option<IndexToXmp> {
     })
 }
 
-
 impl LibMetadata {
 
     pub fn new(id: LibraryId) -> LibMetadata {
@@ -77,6 +79,32 @@ impl LibMetadata {
         self.xmp.serialize_inline()
     }
 
+    fn get_metadata(&self, meta: Np) -> Option<PropertyValue> {
+
+        let index_to_xmp = property_index_to_xmp(meta);
+        if index_to_xmp.is_none() {
+            return None;
+        }
+        let index_to_xmp = index_to_xmp.unwrap();
+
+        let mut prop_flags = exempi::PROP_NONE;
+        let mut xmp_result = self.xmp.xmp.get_property(&index_to_xmp.ns, &index_to_xmp.property,
+                                                       &mut prop_flags);
+        if xmp_result.is_some() && prop_flags.contains(exempi::ARRAY_IS_ALTTEXT) {
+            let mut value = exempi::XmpString::new();
+            let mut actual_lang = exempi::XmpString::new();
+            if self.xmp.xmp.get_localized_text(&index_to_xmp.ns, &index_to_xmp.property, "",
+                                               "x-default", &mut actual_lang,
+                                               &mut value, &mut prop_flags) {
+                xmp_result = Some(value);
+            }
+        }
+        if xmp_result.is_some() {
+            return Some(PropertyValue::String(String::from(xmp_result.unwrap().to_str())));
+        }
+        None
+    }
+
     pub fn set_metadata(&mut self, meta: Np, value: &PropertyValue) -> bool {
         if let Some(ix) = property_index_to_xmp(meta) {
             match value {
@@ -122,6 +150,53 @@ impl LibMetadata {
         false
     }
 
+    pub fn to_properties(&self, propset: &PropertySet) -> PropertyBag {
+        let mut props = PropertyBag::new();
+        for prop_id in propset {
+            let prop_id_np: Np = unsafe { transmute(*prop_id) };
+            match prop_id_np {
+                Np::NpXmpRatingProp =>
+                    if let Some(rating) = self.xmp.rating() {
+                        props.set_value(*prop_id, PropertyValue::Int(rating));
+                    },
+                Np::NpXmpLabelProp =>
+                    if let Some(label) = self.xmp.label() {
+                        props.set_value(*prop_id, PropertyValue::String(label));
+                    },
+                Np::NpTiffOrientationProp =>
+                    if let Some(orientation) = self.xmp.orientation() {
+                        props.set_value(*prop_id, PropertyValue::Int(orientation));
+                    },
+                Np::NpExifDateTimeOriginalProp =>
+                    if let Some(date) = self.xmp.creation_date() {
+                        props.set_value(*prop_id, PropertyValue::Date(date));
+                    },
+                Np::NpIptcKeywordsProp => {
+                    let mut iter = exempi::XmpIterator::new(&self.xmp.xmp, NS_DC,
+                                                            "subject",
+                                                            exempi::ITER_JUST_LEAF_NODES);
+                    let mut keywords: Vec<String> = vec!();
+                    let mut schema = exempi::XmpString::new();
+                    let mut name = exempi::XmpString::new();
+                    let mut value = exempi::XmpString::new();
+                    let mut flags = exempi::IterFlags::empty();
+                    while iter.next(&mut schema, &mut name, &mut value, &mut flags) {
+                        keywords.push(String::from(value.to_str()));
+                    }
+                    props.set_value(*prop_id, PropertyValue::StringArray(keywords));
+                },
+                _ => {
+                    if let Some(propval) = self.get_metadata(prop_id_np) {
+                        props.set_value(*prop_id, propval);
+                    } else {
+                        dbg_out!("missing prop {}", prop_id);
+                    }
+                }
+            }
+        }
+        props
+    }
+
     pub fn touch(&mut self) -> bool {
         let mut xmpdate = exempi::DateTime::new();
         if make_xmp_date_time(fwk::Date::now(), &mut xmpdate) {
@@ -154,16 +229,23 @@ impl FromDb for LibMetadata {
 }
 
 #[no_mangle]
-pub fn engine_libmetadata_get_id(meta: &LibMetadata) -> LibraryId {
-    return meta.id;
+pub extern "C" fn engine_libmetadata_get_id(meta: &LibMetadata) -> LibraryId {
+    meta.id
+}
+
+#[no_mangle]
+pub extern "C" fn engine_libmetadata_get_xmp(meta: &LibMetadata) -> exempi::Xmp {
+    meta.xmp.xmp.clone()
 }
 
 #[no_mangle]
-pub fn engine_libmetadata_get_xmp(meta: &LibMetadata) -> exempi::Xmp {
-    return meta.xmp.xmp.clone();
+pub extern "C" fn engine_libmetadata_get_xmpmeta(meta: &LibMetadata) -> *const XmpMeta {
+    &meta.xmp
 }
 
 #[no_mangle]
-pub fn engine_libmetadata_get_xmpmeta(meta: &LibMetadata) -> *const XmpMeta {
-    return &meta.xmp;
+pub extern "C" fn engine_libmetadata_to_properties(meta: &LibMetadata, propset: &PropertySet)
+                                        -> *mut PropertyBag {
+    let result = Box::new(meta.to_properties(propset));
+    Box::into_raw(result)
 }
diff --git a/src/fwk/base/mod.rs b/src/fwk/base/mod.rs
index 799a9dc..f845971 100644
--- a/src/fwk/base/mod.rs
+++ b/src/fwk/base/mod.rs
@@ -17,6 +17,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+use std::collections::BTreeSet;
+
 pub mod date;
 #[macro_use]
 pub mod debug;
@@ -26,3 +28,19 @@ pub mod propertyvalue;
 pub mod rgbcolour;
 
 pub type PropertyIndex = u32;
+pub type PropertySet = BTreeSet<PropertyIndex>;
+
+#[no_mangle]
+pub extern "C" fn fwk_property_set_new() -> *mut PropertySet {
+    Box::into_raw(Box::new(PropertySet::new()))
+}
+
+#[no_mangle]
+pub extern "C" fn fwk_property_set_delete(set: *mut PropertySet) {
+    unsafe { Box::from_raw(set); }
+}
+
+#[no_mangle]
+pub extern "C" fn fwk_property_set_add(set: &mut PropertySet, v: PropertyIndex) {
+    set.insert(v);
+}
diff --git a/src/fwk/base/propertybag.cpp b/src/fwk/base/propertybag.cpp
index 8574119..2e2e034 100644
--- a/src/fwk/base/propertybag.cpp
+++ b/src/fwk/base/propertybag.cpp
@@ -23,6 +23,16 @@
 
 namespace fwk {
 
+PropertySetPtr property_set_wrap(PropertySet* s)
+{
+    return PropertySetPtr(s, &ffi::fwk_property_set_delete);
+}
+
+PropertySetPtr property_set_new()
+{
+    return property_set_wrap(ffi::fwk_property_set_new());
+}
+
 PropertyValuePtr property_value_wrap(PropertyValue* v)
 {
     return PropertyValuePtr(v, &ffi::fwk_property_value_delete);
diff --git a/src/fwk/base/propertybag.hpp b/src/fwk/base/propertybag.hpp
index 6b355de..ac535f9 100644
--- a/src/fwk/base/propertybag.hpp
+++ b/src/fwk/base/propertybag.hpp
@@ -34,8 +34,6 @@ namespace fwk {
 
 typedef uint32_t PropertyIndex;
 
-typedef std::set<PropertyIndex> PropertySet;
-
 #if !RUST_BINDGEN
 typedef std::shared_ptr<PropertyValue> PropertyValuePtr;
 
@@ -50,8 +48,13 @@ std::vector<std::string> property_value_get_string_array(const PropertyValue &va
 
 #if RUST_BINDGEN
 class PropertyBag;
+class PropertySet;
 #endif
 
+typedef std::shared_ptr<PropertySet> PropertySetPtr;
+
+PropertySetPtr property_set_new();
+
 /** a property bag
  * It is important that the values for PropertyIndex be properly name spaced
  * by the caller.
@@ -60,6 +63,7 @@ typedef std::shared_ptr<PropertyBag> PropertyBagPtr;
 
 #if !RUST_BINDGEN
 PropertyBagPtr property_bag_new();
+PropertyBagPtr property_bag_wrap(PropertyBag*);
 
 PropertyValuePtr property_bag_value(const PropertyBagPtr& bag, PropertyIndex key);
 
@@ -69,10 +73,6 @@ std::string property_value_get_string(const PropertyValue& v);
 bool set_value_for_property(PropertyBag&, PropertyIndex idx, const PropertyValue & value);
 /** return property or an empty option */
 fwk::Option<PropertyValuePtr> get_value_for_property(const PropertyBag&, PropertyIndex idx);
-/** return true if property exist */
-bool has_value_for_property(const PropertyBag&, PropertyIndex idx);
-/** return true if the property was removed */
-bool remove_value_for_property(PropertyBag&, PropertyIndex idx);
 #endif
 
 }
diff --git a/src/fwk/mod.rs b/src/fwk/mod.rs
index 9c5fe5d..581d3ed 100644
--- a/src/fwk/mod.rs
+++ b/src/fwk/mod.rs
@@ -30,6 +30,7 @@ pub use self::utils::exempi::{
 };
 pub use self::base::propertyvalue::PropertyValue;
 pub use self::base::propertybag::PropertyBag;
+pub use self::base::PropertySet;
 pub use self::base::fractions::{
     fraction_to_decimal
 };
diff --git a/src/niepce/modules/map/mapmodule.cpp b/src/niepce/modules/map/mapmodule.cpp
index 47847c0..a816268 100644
--- a/src/niepce/modules/map/mapmodule.cpp
+++ b/src/niepce/modules/map/mapmodule.cpp
@@ -78,10 +78,11 @@ MapModule::on_lib_notification(const eng::LibNotification &ln)
         DBG_OUT("received metadata in MapModule");
 
         if (lm) {
-            fwk::PropertyBagPtr properties;
-            const fwk::PropertySet propset = { eng::NpExifGpsLongProp,
-                                               eng::NpExifGpsLatProp };
-            eng::libmetadata_to_properties(lm, propset, properties);
+            fwk::PropertySetPtr propset = fwk::property_set_new();
+            ffi::fwk_property_set_add(propset.get(), eng::NpExifGpsLongProp);
+            ffi::fwk_property_set_add(propset.get(), eng::NpExifGpsLatProp);
+
+            fwk::PropertyBagPtr properties = eng::libmetadata_to_properties(lm, *propset);
             double latitude, longitude;
             latitude = longitude = NAN;
             auto result = fwk::get_value_for_property(*properties, eng::NpExifGpsLongProp);
diff --git a/src/niepce/ui/metadatapanecontroller.cpp b/src/niepce/ui/metadatapanecontroller.cpp
index 6e25e9f..fb8fb5f 100644
--- a/src/niepce/ui/metadatapanecontroller.cpp
+++ b/src/niepce/ui/metadatapanecontroller.cpp
@@ -79,17 +79,18 @@ MetaDataPaneController::get_format()
     return s_format;
 }
 
-const fwk::PropertySet & MetaDataPaneController::get_property_set()
+const fwk::PropertySet* MetaDataPaneController::get_property_set()
 {
-    static fwk::PropertySet propset;
-    if(propset.empty()) {
+    static fwk::PropertySet* propset = nullptr;
+    if(!propset) {
+        propset = ffi::fwk_property_set_new();
         const fwk::MetaDataSectionFormat * formats = get_format();
-        
+
         const fwk::MetaDataSectionFormat * current = formats;
         while(current->section) {
             const fwk::MetaDataFormat * format = current->formats;
             while(format && format->label) {
-                propset.insert(format->id);
+                ffi::fwk_property_set_add(propset, format->id);
                 format++;
             }
             current++;
@@ -98,9 +99,8 @@ const fwk::PropertySet & MetaDataPaneController::get_property_set()
     return propset;
 }
 
-  
 MetaDataPaneController::MetaDataPaneController()
-    : Dockable("Metadata", _("Image Properties"), 
+    : Dockable("Metadata", _("Image Properties"),
               "document-properties" /*, DockItem::DOCKED_STATE*/),
       m_fileid(0)
 {
@@ -149,8 +149,8 @@ void MetaDataPaneController::display(eng::library_id_t file_id, const eng::LibMe
     DBG_OUT("displaying metadata");
     fwk::PropertyBagPtr properties;
     if(meta) {
-        const fwk::PropertySet & propset = get_property_set();
-        eng::libmetadata_to_properties(meta, propset, properties);
+        const fwk::PropertySet* propset = get_property_set();
+        properties = eng::libmetadata_to_properties(meta, *propset);
     }
     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 2a6145a..03d0e44 100644
--- a/src/niepce/ui/metadatapanecontroller.hpp
+++ b/src/niepce/ui/metadatapanecontroller.hpp
@@ -56,7 +56,7 @@ private:
     std::vector<fwk::MetaDataWidget *> m_widgets;
 
     static const fwk::MetaDataSectionFormat * get_format();
-    static const fwk::PropertySet & get_property_set();
+    static const fwk::PropertySet* get_property_set();
 
     eng::library_id_t m_fileid;
 };
diff --git a/src/rust_bindings.hpp b/src/rust_bindings.hpp
index f68c5b2..fc3f95e 100644
--- a/src/rust_bindings.hpp
+++ b/src/rust_bindings.hpp
@@ -33,6 +33,7 @@ namespace fwk {
 
 typedef ffi::PropertyValue PropertyValue;
 typedef ffi::PropertyBag PropertyBag;
+typedef ffi::PropertySet PropertySet;
 typedef ffi::Date Date;
 
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]