[niepce: 13/17] Token text view for keywords.



commit 62dd488116868fb0030d433a55893248b9cd741b
Author: Hub Figuiere <hub figuiere net>
Date:   Sun Jan 8 20:10:33 2012 -0800

    Token text view for keywords.

 src/engine/db/libmetadata.cpp             |   37 +++++++++++++++------
 src/engine/db/properties-def.hpp          |    2 +-
 src/fwk/base/propertybag.hpp              |    6 +++-
 src/fwk/toolkit/Makefile.am               |    1 +
 src/fwk/toolkit/metadatawidget.cpp        |   48 ++++++++++++++++++++++++++-
 src/fwk/toolkit/metadatawidget.hpp        |    3 ++
 src/fwk/toolkit/widgets/tokentextview.cpp |   49 ++++++++++++++++++++++++++++
 src/fwk/toolkit/widgets/tokentextview.hpp |   50 +++++++++++++++++++++++++++++
 8 files changed, 182 insertions(+), 14 deletions(-)
---
diff --git a/src/engine/db/libmetadata.cpp b/src/engine/db/libmetadata.cpp
index e044567..6d79641 100644
--- a/src/engine/db/libmetadata.cpp
+++ b/src/engine/db/libmetadata.cpp
@@ -1,7 +1,7 @@
 /*
  * niepce - db/libmetadata.cpp
  *
- * Copyright (C) 2008 Hubert Figuiere
+ * Copyright (C) 2008,2012 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
@@ -49,7 +49,9 @@ const PropsToXmpMap & props_to_xmp_map()
     return s_props_map;
 }
 
-bool LibMetadata::property_index_to_xmp(fwk::PropertyIndex index, const char * & ns, const char * & property)
+bool
+LibMetadata::property_index_to_xmp(fwk::PropertyIndex index, 
+                                   const char * & ns, const char * & property)
 {
     const PropsToXmpMap & propmap = props_to_xmp_map();
      PropsToXmpMap::const_iterator iter = propmap.find(index);
@@ -75,7 +77,8 @@ LibMetadata::LibMetadata(library_id_t _id)
 }
 
 
-bool LibMetadata::setMetaData(fwk::PropertyIndex meta, const fwk::PropertyValue & value)
+bool LibMetadata::setMetaData(fwk::PropertyIndex meta, 
+                              const fwk::PropertyValue & value)
 {
     const char * ns = NULL;
     const char * property = NULL;
@@ -93,11 +96,25 @@ bool LibMetadata::setMetaData(fwk::PropertyIndex meta, const fwk::PropertyValue
             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);
+                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);
+            for(fwk::StringArray::const_iterator iter = v.begin(); 
+                iter != v.end(); ++iter) {
+                /*result = */xmp_append_array_item(xmp(), ns, property, 
+                                                   XMP_PROP_VALUE_IS_ARRAY,
+                                                   iter->c_str(), 0);
             }
         }
         if(!result) {
-            ERR_OUT("error setting property %s:%s %d", ns, property, xmp_get_error());
+            ERR_OUT("error setting property %s:%s %d", ns, property, 
+                    xmp_get_error());
         }
     }
     else {
@@ -107,7 +124,8 @@ bool LibMetadata::setMetaData(fwk::PropertyIndex meta, const fwk::PropertyValue
 }
 
 
-bool LibMetadata::getMetaData(fwk::PropertyIndex p, fwk::PropertyValue & value) const
+bool LibMetadata::getMetaData(fwk::PropertyIndex p, 
+                              fwk::PropertyValue & value) const
 {
     const PropsToXmpMap & propmap = props_to_xmp_map();
     PropsToXmpMap::const_iterator iter = propmap.find(p);
@@ -165,18 +183,17 @@ void LibMetadata::to_properties(const fwk::PropertySet & propset,
             xmp::ScopedPtr<XmpIteratorPtr> 
                 iter(xmp_iterator_new(xmp(), NS_DC,
                                       "subject", XMP_ITER_JUSTLEAFNODES));
-            std::vector<std::string> vec;
+            fwk::StringArray vec;
             while(xmp_iterator_next(iter, NULL, NULL, value, NULL)) {
                 vec.push_back(xmp_string_cstr(value));
             }
-            std::string v = fwk::join(vec, ", ");
             properties.set_value_for_property(NpIptcKeywordsProp, 
-                                              fwk::PropertyValue(v));
+                                              fwk::PropertyValue(vec));
             break;
         }
         default:
             if(getMetaData(*iter, propval)) {
-                properties.set_value_for_property(*iter, propval);                
+                properties.set_value_for_property(*iter, propval);
             }
             else {
                 DBG_OUT("unknown prop %u", *iter);
diff --git a/src/engine/db/properties-def.hpp b/src/engine/db/properties-def.hpp
index 30f346c..de8f8b2 100644
--- a/src/engine/db/properties-def.hpp
+++ b/src/engine/db/properties-def.hpp
@@ -49,6 +49,6 @@ DEFINE_PROPERTY(NpExifFocalLengthProp, MAKE_METADATA_IDX(META_NS_EXIF, META_EXIF
 
 DEFINE_PROPERTY(NpIptcHeadlineProp, MAKE_METADATA_IDX(META_NS_IPTC, META_IPTC_HEADLINE), NS_PHOTOSHOP, "Headline", std::string)
 DEFINE_PROPERTY(NpIptcDescriptionProp, MAKE_METADATA_IDX(META_NS_IPTC, META_IPTC_DESCRIPTION), NS_DC, "description", std::string)
-DEFINE_PROPERTY(NpIptcKeywordsProp, MAKE_METADATA_IDX(META_NS_IPTC, META_IPTC_KEYWORDS), NS_DC, "subject", std::string)
+DEFINE_PROPERTY(NpIptcKeywordsProp, MAKE_METADATA_IDX(META_NS_IPTC, META_IPTC_KEYWORDS), NS_DC, "subject", fwk::StringArray)
 
 DEFINE_PROPERTY(NpNiepceFlagProp, MAKE_METADATA_IDX(META_NS_NIEPCE, META_NIEPCE_FLAG), xmp::NIEPCE_XMP_NAMESPACE, "Flag", int32_t)
diff --git a/src/fwk/base/propertybag.hpp b/src/fwk/base/propertybag.hpp
index 638c10f..15b0856 100644
--- a/src/fwk/base/propertybag.hpp
+++ b/src/fwk/base/propertybag.hpp
@@ -22,6 +22,9 @@
 #ifndef __FWK_PROPERTYBAG_HPP_
 #define __FWK_PROPERTYBAG_HPP_
 
+#include <stdint.h>
+#include <string>
+#include <vector>
 #include <map>
 #include <set>
 #include <tr1/memory>
@@ -30,7 +33,8 @@
 namespace fwk {
 
 typedef uint32_t PropertyIndex;
-typedef boost::variant<int, std::string> PropertyValue;
+typedef std::vector<std::string> StringArray;
+typedef boost::variant<int, std::string, StringArray> PropertyValue;
 
 typedef std::set<PropertyIndex> PropertySet;
 
diff --git a/src/fwk/toolkit/Makefile.am b/src/fwk/toolkit/Makefile.am
index e31bfe2..bcea3f0 100644
--- a/src/fwk/toolkit/Makefile.am
+++ b/src/fwk/toolkit/Makefile.am
@@ -36,6 +36,7 @@ libniepceframework_a_SOURCES = configuration.hpp configuration.cpp \
 	widgets/editablehscale.hpp widgets/editablehscale.cpp \
 	widgets/dock.cpp widgets/dock.hpp \
 	widgets/notabtextview.hpp widgets/notabtextview.cpp \
+	widgets/tokentextview.hpp widgets/tokentextview.cpp \
 	dockable.hpp dockable.cpp \
 	metadatawidget.hpp metadatawidget.cpp \
 	undo.hpp undo.cpp \
diff --git a/src/fwk/toolkit/metadatawidget.cpp b/src/fwk/toolkit/metadatawidget.cpp
index ed1f436..f6dbe78 100644
--- a/src/fwk/toolkit/metadatawidget.cpp
+++ b/src/fwk/toolkit/metadatawidget.cpp
@@ -34,6 +34,7 @@
 #include "fwk/utils/stringutils.hpp"
 #include "fwk/toolkit/widgets/ratinglabel.hpp"
 #include "fwk/toolkit/widgets/notabtextview.hpp"
+#include "fwk/toolkit/widgets/tokentextview.hpp"
 
 // remove
 #include "engine/db/properties.hpp"
@@ -87,8 +88,20 @@ void MetaDataWidget::create_widgets_for_format(const MetaDataSectionFormat * fmt
             w = r;
             break;
         }
-        case META_DT_TEXT:
+        case META_DT_STRING_ARRAY:
         {
+            fwk::TokenTextView * ttv = Gtk::manage(new fwk::TokenTextView());
+            if(!current->readonly) {
+                ttv->signal_focus_out_event().connect(
+                    sigc::bind(
+                        sigc::mem_fun(*this, 
+                                      &MetaDataWidget::on_string_array_changed),
+                        ttv, current->id));
+            }
+            w = ttv;
+            break;
+        }
+        case META_DT_TEXT:
             if(current->readonly) {
                 Gtk::Label * l = Gtk::manage(new Gtk::Label());
                 l->set_alignment(0.0f, 0.5f);
@@ -106,7 +119,6 @@ void MetaDataWidget::create_widgets_for_format(const MetaDataSectionFormat * fmt
                 w = e;
             }
             break;
-        }
         default:
             if(current->readonly) {
                 Gtk::Label * l = Gtk::manage(new Gtk::Label());
@@ -152,9 +164,15 @@ void MetaDataWidget::clear_widget(std::pair<const PropertyIndex, Gtk::Widget *>
         e->set_text("");
         return;
     }
+    fwk::TokenTextView *ttv = dynamic_cast<fwk::TokenTextView*>(p.second);
+    if(ttv) {
+        ttv->set_tokens(fwk::TokenTextView::Tokens());
+        return;
+    }
     Gtk::TextView * tv = dynamic_cast<Gtk::TextView*>(p.second);
     if(tv) {
         tv->get_buffer()->set_text("");
+        return;
     }
     fwk::RatingLabel * rl = dynamic_cast<fwk::RatingLabel*>(p.second);
     if(rl) {
@@ -229,6 +247,18 @@ void MetaDataWidget::add_data(const MetaDataFormat * current,
             DBG_OUT("conversion of '%u' to int failed", current->id);
         }
         break;
+    case META_DT_STRING_ARRAY:
+        try {
+            AutoFlag flag(m_update);
+            fwk::StringArray tokens = boost::get<fwk::StringArray>(value);
+            
+            static_cast<fwk::TokenTextView*>(w)->set_tokens(tokens);
+        }
+        catch(...) {
+            DBG_OUT("conversion of '%u' from %s to StringArray failed", current->id,
+                    value.type().name());
+        }
+        break;
     case META_DT_TEXT:
         try {
             AutoFlag flag(m_update);
@@ -282,6 +312,20 @@ bool MetaDataWidget::on_text_changed(GdkEventFocus*,
     return true;
 }
 
+bool MetaDataWidget::on_string_array_changed(GdkEventFocus*, 
+                                             fwk::TokenTextView * ttv,
+                                             fwk::PropertyIndex prop)
+{
+    if(m_update) {
+        return true;
+    }
+    fwk::TokenTextView::Tokens tok;
+    ttv->get_tokens(tok);
+    emit_metadata_changed(prop, 
+                          fwk::PropertyValue(tok));
+    return true;
+}
+
 void MetaDataWidget::on_int_changed(int value, fwk::PropertyIndex prop)
 {
     if(m_update) {
diff --git a/src/fwk/toolkit/metadatawidget.hpp b/src/fwk/toolkit/metadatawidget.hpp
index 1594562..fde9299 100644
--- a/src/fwk/toolkit/metadatawidget.hpp
+++ b/src/fwk/toolkit/metadatawidget.hpp
@@ -61,6 +61,7 @@ struct MetaDataSectionFormat {
 
 
 class XmpMeta;
+class TokenTextView;
 
 class MetaDataWidget 
 	: public fwk::ToolboxItemWidget
@@ -77,6 +78,8 @@ public:
 protected:
     bool on_str_changed(GdkEventFocus*, Gtk::Entry *, fwk::PropertyIndex prop);
     bool on_text_changed(GdkEventFocus*, Glib::RefPtr<Gtk::TextBuffer> b, fwk::PropertyIndex prop);
+    bool on_string_array_changed(GdkEventFocus*, fwk::TokenTextView * ttv,
+                                 fwk::PropertyIndex prop);
     void on_int_changed(int, fwk::PropertyIndex prop);
 private:
     void clear_widget(std::pair<const PropertyIndex, Gtk::Widget *> & p);
diff --git a/src/fwk/toolkit/widgets/tokentextview.cpp b/src/fwk/toolkit/widgets/tokentextview.cpp
new file mode 100644
index 0000000..0e21a09
--- /dev/null
+++ b/src/fwk/toolkit/widgets/tokentextview.cpp
@@ -0,0 +1,49 @@
+/*
+ * niepce - fwk/toolkit/widgets/tokentextview.cpp
+ *
+ * Copyright (C) 2012 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
+ * 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 <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/split.hpp>
+#include "fwk/base/debug.hpp"
+#include "fwk/utils/stringutils.hpp"
+#include "tokentextview.hpp"
+
+namespace fwk {
+
+void TokenTextView::set_tokens(const Tokens & tokens)
+{
+    std::string v = fwk::join(tokens, ",");
+    get_buffer()->set_text(v);
+}
+
+void TokenTextView::get_tokens(Tokens & tokens)
+{
+    Glib::ustring t = get_buffer()->get_text();
+    boost::split(tokens, t.raw(), boost::is_any_of(","));
+}
+
+}
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0))
+  indent-tabs-mode:nil
+  fill-column:80
+  End:
+*/
diff --git a/src/fwk/toolkit/widgets/tokentextview.hpp b/src/fwk/toolkit/widgets/tokentextview.hpp
new file mode 100644
index 0000000..b2d8000
--- /dev/null
+++ b/src/fwk/toolkit/widgets/tokentextview.hpp
@@ -0,0 +1,50 @@
+/*
+ * niepce - fwk/toolkit/widgets/tokentextview.hpp
+ *
+ * Copyright (C) 2012 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
+ * 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/>.
+ */
+
+#ifndef __FWK_TOKENTEXTVIEW_HPP__
+#define __FWK_TOKENTEXTVIEW_HPP__
+
+#include <string>
+#include <vector>
+
+#include "fwk/toolkit/widgets/notabtextview.hpp"
+
+namespace fwk {
+
+class TokenTextView
+    : public NoTabTextView
+{
+public:
+    typedef std::vector<std::string> Tokens;
+    void set_tokens(const Tokens & tokens);
+    void get_tokens(Tokens & tokens);
+};
+
+}
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0))
+  indent-tabs-mode:nil
+  fill-column:80
+  End:
+*/
+#endif



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