[niepce] Date property



commit d470ccf9db5fe72b2bd28c0a89cc6fa47c889580
Author: Hub Figuiere <hub figuiere net>
Date:   Wed Feb 1 17:02:46 2012 -0800

    Date property

 .gitignore                                |    1 +
 src/engine/db/libmetadata.cpp             |   38 +++--
 src/engine/db/library.cpp                 |    8 +-
 src/engine/db/properties-def.hpp          |    2 +-
 src/fwk/base/Makefile.am                  |   13 +-
 src/fwk/base/date.cpp                     |  106 ++++++++++
 src/fwk/base/date.hpp                     |   66 +++++++
 src/fwk/base/propertybag.hpp              |    8 +-
 src/fwk/base/t/testdate.cpp               |   50 +++++
 src/fwk/base/t/testfractions.cpp          |    2 +-
 src/fwk/toolkit/metadatawidget.cpp        |  296 ++++++++++++++++++-----------
 src/fwk/toolkit/metadatawidget.hpp        |   20 ++-
 src/fwk/utils/exempi.cpp                  |   23 +--
 src/fwk/utils/exempi.hpp                  |    6 +-
 src/niepce/modules/interfaces/Makefile.am |    1 +
 15 files changed, 486 insertions(+), 154 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 47f495a..ed19e7b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,6 +36,7 @@ po/Makefile.in.in
 src/fwk/base/testmoniker
 src/fwk/base/testgeometry
 src/fwk/base/testfractions
+src/fwk/base/testdate
 src/fwk/utils/test_db
 src/fwk/utils/test_db2
 src/fwk/utils/test_db3
diff --git a/src/engine/db/libmetadata.cpp b/src/engine/db/libmetadata.cpp
index 6d79641..918d0ba 100644
--- a/src/engine/db/libmetadata.cpp
+++ b/src/engine/db/libmetadata.cpp
@@ -54,7 +54,7 @@ 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);
+    PropsToXmpMap::const_iterator iter = propmap.find(index);
     if(iter == propmap.end()) {
         // not found
         return false;
@@ -104,14 +104,21 @@ bool LibMetadata::setMetaData(fwk::PropertyIndex meta,
         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);
+            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);
+                result = xmp_append_array_item(xmp(), ns, property, 
+                                               XMP_PROP_VALUE_IS_ARRAY,
+                                               iter->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());
@@ -165,19 +172,24 @@ void LibMetadata::to_properties(const fwk::PropertySet & propset,
     xmp::ScopedPtr<XmpStringPtr> value(xmp_string_new());
     fwk::PropertyValue propval;
     for(iter = propset.begin(); iter != propset.end(); ++iter) {
-        switch(*iter) {
+        fwk::PropertySet::key_type prop_id = *iter;
+        switch(prop_id) {
         case NpXmpRatingProp:
-            properties.set_value_for_property(NpXmpRatingProp,
+            properties.set_value_for_property(prop_id,
                                               fwk::PropertyValue(rating()));
             break;
         case NpXmpLabelProp:
-            properties.set_value_for_property(NpXmpLabelProp,
+            properties.set_value_for_property(prop_id,
                                               fwk::PropertyValue(label()));
             break;
         case NpTiffOrientationProp:
-            properties.set_value_for_property(NpTiffOrientationProp, 
+            properties.set_value_for_property(prop_id, 
                                               fwk::PropertyValue(orientation()));
             break;
+        case NpExifDateTimeOriginalProp:
+            properties.set_value_for_property(prop_id,
+                                              fwk::PropertyValue(creation_date()));
+            break;
         case NpIptcKeywordsProp:
         {
             xmp::ScopedPtr<XmpIteratorPtr> 
@@ -187,16 +199,16 @@ void LibMetadata::to_properties(const fwk::PropertySet & propset,
             while(xmp_iterator_next(iter, NULL, NULL, value, NULL)) {
                 vec.push_back(xmp_string_cstr(value));
             }
-            properties.set_value_for_property(NpIptcKeywordsProp, 
+            properties.set_value_for_property(prop_id,
                                               fwk::PropertyValue(vec));
             break;
         }
         default:
-            if(getMetaData(*iter, propval)) {
-                properties.set_value_for_property(*iter, propval);
+            if(getMetaData(prop_id, propval)) {
+                properties.set_value_for_property(prop_id, propval);
             }
             else {
-                DBG_OUT("unknown prop %u", *iter);
+                DBG_OUT("unknown prop %u", prop_id);
             }
             break;
         }
diff --git a/src/engine/db/library.cpp b/src/engine/db/library.cpp
index 5de502d..bdf4cfc 100644
--- a/src/engine/db/library.cpp
+++ b/src/engine/db/library.cpp
@@ -284,7 +284,7 @@ library_id_t Library::addFile(library_id_t folder_id, const std::string & file,
         rating = meta.rating();
         label = meta.label();
         flag = meta.flag();
-        time_t creation_date = meta.creation_date();
+        time_t creation_date = fwk::make_time_value(meta.creation_date());
         if(creation_date == -1) {
             creation_date = 0;
         }
@@ -896,6 +896,9 @@ bool Library::getXmpIdsInQueue(std::vector<library_id_t> & ids)
 
 bool Library::rewriteXmpForId(library_id_t id)
 {
+    /// DISABLED
+#if 0
+
     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 "
@@ -952,7 +955,8 @@ bool Library::rewriteXmpForId(library_id_t id)
     {
         DBG_OUT("db exception %s", e.what());
         return false;
-    }    
+    }
+#endif
     return true;
 }
 
diff --git a/src/engine/db/properties-def.hpp b/src/engine/db/properties-def.hpp
index de8f8b2..2e8d16c 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", int32_t)
+DEFINE_PROPERTY(NpExifDateTimeOriginalProp, MAKE_METADATA_IDX(META_NS_EXIF, META_EXIF_DATETIMEORIGINAL), NS_EXIF, "DateTimeOriginal", fwk::Date)
 DEFINE_PROPERTY(NpExifFocalLengthProp, MAKE_METADATA_IDX(META_NS_EXIF, META_EXIF_FOCALLENGTH), NS_EXIF, "FocalLength", int32_t)
 
 DEFINE_PROPERTY(NpIptcHeadlineProp, MAKE_METADATA_IDX(META_NS_IPTC, META_IPTC_HEADLINE), NS_PHOTOSHOP, "Headline", std::string)
diff --git a/src/fwk/base/Makefile.am b/src/fwk/base/Makefile.am
index a2b90c2..d5105df 100644
--- a/src/fwk/base/Makefile.am
+++ b/src/fwk/base/Makefile.am
@@ -1,14 +1,19 @@
 
 INCLUDES = -I$(top_srcdir)/src \
 	@BOOST_CPPFLAGS@ \
+	@EXEMPI_CFLAGS@ \
 	$(NULL)
 
 noinst_LIBRARIES = libfwkbase.a
 
 
-TESTS = testmoniker testgeometry
+TESTS = testmoniker testgeometry testfractions testdate
 
-check_PROGRAMS = testmoniker testgeometry
+check_PROGRAMS = testmoniker testgeometry testfractions testdate
+
+testdate_SOURCES = t/testdate.cpp
+testdate_LDADD = libfwkbase.a \
+	@LIBGLIBMM_LIBS@
 
 testmoniker_SOURCES = t/testmoniker.cpp
 testmoniker_LDADD = libfwkbase.a \
@@ -18,10 +23,14 @@ testgeometry_SOURCES = t/testgeometry.cpp
 testgeometry_LDADD = libfwkbase.a \
 	@LIBGLIBMM_LIBS@
 
+testfractions_SOURCES = t/testfractions.cpp
+testfractions_LDADD = libfwkbase.a \
+	@LIBGLIBMM_LIBS@
 
 
 libfwkbase_a_SOURCES = color.hpp color.cpp \
 	autoflag.hpp \
+	date.hpp date.cpp \
 	debug.hpp debug.cpp \
 	fractions.hpp fractions.cpp \
 	moniker.hpp moniker.cpp \
diff --git a/src/fwk/base/date.cpp b/src/fwk/base/date.cpp
new file mode 100644
index 0000000..b8fbac4
--- /dev/null
+++ b/src/fwk/base/date.cpp
@@ -0,0 +1,106 @@
+/*
+ * niepce - fwk/base/date.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/>.
+ */
+
+#include <stdio.h>
+#include <time.h>
+
+#include "date.hpp"
+#include "debug.hpp"
+
+namespace fwk {
+
+time_t make_time_value(const Date & d)
+{
+    time_t date = 0;
+
+    const XmpDateTime & value = d.xmp_date();
+    struct tm dt;
+    dt.tm_sec = value.second;
+    dt.tm_min = value.minute;
+    dt.tm_hour = value.hour;
+    dt.tm_mday = value.day;
+    dt.tm_mon = value.month;
+    dt.tm_year = value.year - 1900;
+    dt.tm_isdst = -1;
+    // this field is supposed to be a glibc extension. oh joy.
+    dt.tm_gmtoff = value.tzSign * ((value.tzHour * 3600) +
+                                   (value.tzMinute * 60));
+    date = mktime(&dt);
+    DBG_ASSERT(date != -1, "date is -1");
+
+    return date;
+}
+
+XmpDateTime& make_xmp_date_time(time_t t, XmpDateTime& xmp_dt)
+{
+    // FIXME find a better way. This should work.
+    struct tm gmt;
+    struct tm* pgmt = gmtime_r(&t, &gmt);
+    DBG_ASSERT(pgmt == &gmt, "gmtime failed");
+
+    xmp_dt.year = gmt.tm_year + 1900;
+    xmp_dt.month = gmt.tm_mon + 1;
+    xmp_dt.day = gmt.tm_mday;
+    xmp_dt.hour = gmt.tm_hour;
+    xmp_dt.minute = gmt.tm_min;
+    xmp_dt.second = gmt.tm_sec;
+    xmp_dt.tzSign = 0;
+    xmp_dt.tzHour = 0;
+    xmp_dt.tzMinute = 0;
+    xmp_dt.nanoSecond = 0;
+    return xmp_dt;
+}
+
+Date::Date(const XmpDateTime& dt, const Timezone* tz)
+    : m_datetime(dt)
+    , m_tz(tz)
+{
+}
+
+Date::Date(const time_t dt, const Timezone* tz)
+    : m_tz(tz)
+{
+    make_xmp_date_time(dt, m_datetime);
+}
+
+std::string Date::to_string() const
+{
+    char buffer[256];
+
+    snprintf(buffer, 256, "%u:%u:%d %u:%u:%u %c%u%u",
+             m_datetime.year, m_datetime.month,
+             m_datetime.day, m_datetime.hour,
+             m_datetime.minute, m_datetime.second,
+             m_datetime.tzSign >= 0 ? '+' : '-',
+             m_datetime.tzHour, m_datetime.tzMinute);
+    
+    return buffer;
+}
+
+}
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
diff --git a/src/fwk/base/date.hpp b/src/fwk/base/date.hpp
new file mode 100644
index 0000000..add14f0
--- /dev/null
+++ b/src/fwk/base/date.hpp
@@ -0,0 +1,66 @@
+/*
+ * niepce - fwk/base/date.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_BASE_DATE_HPP
+#define __FWK_BASE_DATE_HPP
+
+#include <string>
+
+#include <exempi/xmp.h>
+
+namespace fwk {
+
+class Timezone;
+
+XmpDateTime& 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 = NULL);
+    Date(const time_t dt, const Timezone* tz = NULL);
+
+    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 &);
+
+}
+
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+#endif
diff --git a/src/fwk/base/propertybag.hpp b/src/fwk/base/propertybag.hpp
index 15b0856..358fa69 100644
--- a/src/fwk/base/propertybag.hpp
+++ b/src/fwk/base/propertybag.hpp
@@ -1,7 +1,7 @@
 /*
  * niepce - fwk/base/propertybag.cpp
  *
- * Copyright (C) 2011 Hubert Figuiere
+ * Copyright (C) 2011-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
@@ -17,8 +17,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-
-
 #ifndef __FWK_PROPERTYBAG_HPP_
 #define __FWK_PROPERTYBAG_HPP_
 
@@ -30,11 +28,13 @@
 #include <tr1/memory>
 #include <boost/variant.hpp>
 
+#include "fwk/base/date.hpp"
+
 namespace fwk {
 
 typedef uint32_t PropertyIndex;
 typedef std::vector<std::string> StringArray;
-typedef boost::variant<int, std::string, StringArray> PropertyValue;
+typedef boost::variant<int, std::string, StringArray, Date> PropertyValue;
 
 typedef std::set<PropertyIndex> PropertySet;
 
diff --git a/src/fwk/base/t/testdate.cpp b/src/fwk/base/t/testdate.cpp
new file mode 100644
index 0000000..ac9865e
--- /dev/null
+++ b/src/fwk/base/t/testdate.cpp
@@ -0,0 +1,50 @@
+/*
+ * niepce - base/t/testdate.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/>.
+ */
+/** @brief unit test for date */
+
+#include <boost/test/minimal.hpp>
+
+#include <stdlib.h>
+#include <vector>
+#include <boost/rational.hpp>
+
+#include "fwk/base/date.hpp"
+
+int test_main( int, char *[] )             // note the name!
+{
+    fwk::Date d(0);
+    
+    XmpDateTime xmp_dt = d.xmp_date();
+    BOOST_CHECK(xmp_dt.year == 1970);
+    BOOST_CHECK(xmp_dt.month == 1);
+    BOOST_CHECK(xmp_dt.day == 1);
+    
+    printf("%s\n", d.to_string().c_str());
+    
+    return 0;
+}
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
diff --git a/src/fwk/base/t/testfractions.cpp b/src/fwk/base/t/testfractions.cpp
index caee8c2..9cc78fe 100644
--- a/src/fwk/base/t/testfractions.cpp
+++ b/src/fwk/base/t/testfractions.cpp
@@ -16,7 +16,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-/** @brief unit test for files */
+/** @brief unit test for fractions */
 
 #include <boost/test/minimal.hpp>
 
diff --git a/src/fwk/toolkit/metadatawidget.cpp b/src/fwk/toolkit/metadatawidget.cpp
index f6dbe78..c8a2c3e 100644
--- a/src/fwk/toolkit/metadatawidget.cpp
+++ b/src/fwk/toolkit/metadatawidget.cpp
@@ -37,7 +37,7 @@
 #include "fwk/toolkit/widgets/tokentextview.hpp"
 
 // remove
-#include "engine/db/properties.hpp"
+//#include "engine/db/properties.hpp"
 
 #include "metadatawidget.hpp"
 
@@ -60,10 +60,85 @@ void MetaDataWidget::set_data_format(const MetaDataSectionFormat * fmt)
     create_widgets_for_format(fmt);
 }
 
-void MetaDataWidget::create_widgets_for_format(const MetaDataSectionFormat * fmt)
+Gtk::Widget* 
+MetaDataWidget::create_star_rating_widget(bool readonly, uint32_t id)
+{
+    fwk::RatingLabel* r = Gtk::manage(new fwk::RatingLabel(0, !readonly));
+    if(!readonly) {
+        r->signal_changed.connect(
+            sigc::bind(
+                sigc::mem_fun(*this, 
+                              &MetaDataWidget::on_int_changed), 
+                id));
+    }
+    return r;
+}
+
+Gtk::Widget*
+MetaDataWidget::create_string_array_widget(bool readonly, uint32_t id)
+{
+    fwk::TokenTextView * ttv = Gtk::manage(new fwk::TokenTextView());
+    if(!readonly) {
+        ttv->signal_focus_out_event().connect(
+            sigc::bind(
+                sigc::mem_fun(*this, 
+                              &MetaDataWidget::on_string_array_changed),
+                ttv, id));
+    }
+    return ttv;
+}
+
+Gtk::Widget*
+MetaDataWidget::create_text_widget(bool readonly, uint32_t id)
+{
+    if(readonly) {
+        Gtk::Label * l = Gtk::manage(new Gtk::Label());
+        l->set_alignment(0.0f, 0.5f);
+        return l;
+    }
+
+    Gtk::TextView * e = Gtk::manage(new NoTabTextView());
+    e->set_editable(true);
+    e->set_wrap_mode(Gtk::WRAP_WORD);
+    e->signal_focus_out_event().connect(
+        sigc::bind(
+            sigc::mem_fun(*this, 
+                          &MetaDataWidget::on_text_changed),
+            e->get_buffer(), id));
+    return e;
+}
+
+Gtk::Widget*
+MetaDataWidget::create_string_widget(bool readonly, uint32_t id)
+{
+    if(readonly) {
+        Gtk::Label * l = Gtk::manage(new Gtk::Label());
+        l->set_alignment(0.0f, 0.5f);
+        return l;
+    }
+
+    Gtk::Entry * e = Gtk::manage(new Gtk::Entry());
+    e->set_has_frame(false); // TODO make that a custom widget
+    e->signal_focus_out_event().connect(
+        sigc::bind(
+            sigc::mem_fun(*this, 
+                          &MetaDataWidget::on_str_changed),
+            e, id));
+    return e;
+}
+
+Gtk::Widget*
+MetaDataWidget::create_date_widget(bool /*readonly*/, uint32_t id)
+{
+    // for now a date widget is just like a string. Read only
+    return create_string_widget(true, id);
+}
+
+void 
+MetaDataWidget::create_widgets_for_format(const MetaDataSectionFormat * fmt)
 {
     Gtk::Widget *w = NULL;
-    const MetaDataFormat * current = m_fmt->formats;
+    const MetaDataFormat * current = fmt->formats;
     int n_row = 0;
 
     while(current && current->label) {
@@ -73,68 +148,21 @@ void MetaDataWidget::create_widgets_for_format(const MetaDataSectionFormat * fmt
         labelw->set_alignment(0.0f, 0.5f);
         labelw->set_use_markup(true);
     
-        switch(current->type)
-        {
+        switch(current->type) {
         case META_DT_STAR_RATING:
-        {
-            fwk::RatingLabel * r = Gtk::manage(new fwk::RatingLabel(0, !current->readonly));
-            if(!current->readonly) {
-                r->signal_changed.connect(
-                    sigc::bind(
-                        sigc::mem_fun(*this, 
-                                      &MetaDataWidget::on_int_changed), 
-                        current->id));
-            }
-            w = r;
+            w = create_star_rating_widget(current->readonly, current->id);
             break;
-        }
         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;
+            w = create_string_array_widget(current->readonly, current->id);
             break;
-        }
         case META_DT_TEXT:
-            if(current->readonly) {
-                Gtk::Label * l = Gtk::manage(new Gtk::Label());
-                l->set_alignment(0.0f, 0.5f);
-                w = l;
-            }
-            else {
-                Gtk::TextView * e = Gtk::manage(new NoTabTextView());
-                e->set_editable(true);
-                e->set_wrap_mode(Gtk::WRAP_WORD);
-                e->signal_focus_out_event().connect(
-                    sigc::bind(
-                        sigc::mem_fun(*this, 
-                                      &MetaDataWidget::on_text_changed),
-                        e->get_buffer(), current->id));
-                w = e;
-            }
+            w = create_text_widget(current->readonly, current->id);
+            break;
+        case META_DT_DATE:
+            w = create_date_widget(current->readonly, current->id);
             break;
         default:
-            if(current->readonly) {
-                Gtk::Label * l = Gtk::manage(new Gtk::Label());
-                l->set_alignment(0.0f, 0.5f);
-                w = l;
-            }
-            else {
-                Gtk::Entry * e = Gtk::manage(new Gtk::Entry());
-                e->set_has_frame(false); // TODO make that a custom widget
-                e->signal_focus_out_event().connect(
-                    sigc::bind(
-                        sigc::mem_fun(*this, 
-                                      &MetaDataWidget::on_str_changed),
-                        e, current->id));
-                w = e;
-            }
+            w = create_string_widget(current->readonly, current->id);
             break;
         }
     
@@ -211,6 +239,99 @@ void MetaDataWidget::set_data_source(const fwk::PropertyBag & properties)
     }
 }
 
+bool MetaDataWidget::set_fraction_data(Gtk::Widget* w, const PropertyValue & value)
+{
+    try {
+        const std::string& str_value = boost::get<std::string>(value);
+        DBG_OUT("set fraction %s", str_value.c_str());
+        double decimal = fwk::fraction_to_decimal(str_value);
+        std::string frac = boost::lexical_cast<std::string>(decimal);
+        AutoFlag flag(m_update);
+        static_cast<Gtk::Label*>(w)->set_text(frac);
+    }
+    catch(...) {
+        return false;
+    }
+    return true;
+}
+
+bool MetaDataWidget::set_star_rating_data(Gtk::Widget* w, const PropertyValue & value)
+{
+    try {
+        int rating = boost::get<int>(value);
+        AutoFlag flag(m_update);
+        static_cast<fwk::RatingLabel*>(w)->set_rating(rating);
+    }
+    catch(...) {
+        return false;
+    }
+    return true;
+}
+
+bool MetaDataWidget::set_string_array_data(Gtk::Widget* w, const PropertyValue & value)
+{
+    try {
+        AutoFlag flag(m_update);
+        fwk::StringArray tokens = boost::get<fwk::StringArray>(value);
+        
+        static_cast<fwk::TokenTextView*>(w)->set_tokens(tokens);
+    }
+    catch(...) {
+        return false;
+    }
+    return true;
+}
+
+bool MetaDataWidget::set_text_data(Gtk::Widget* w, bool readonly,
+                                   const PropertyValue & value)
+{
+    try {
+        AutoFlag flag(m_update);
+        if(readonly) {
+            static_cast<Gtk::Label*>(w)->set_text(boost::get<std::string>(value));
+        }
+        else {
+            static_cast<Gtk::TextView*>(w)->get_buffer()->set_text(boost::get<std::string>(value));
+        }
+    }
+    catch(...) {
+        return false;
+    }
+    return true;    
+}
+
+bool MetaDataWidget::set_string_data(Gtk::Widget* w, bool readonly,
+                                     const PropertyValue & value)
+{
+    try {
+        AutoFlag flag(m_update);
+        if(readonly) {
+            static_cast<Gtk::Label*>(w)->set_text(boost::get<std::string>(value));
+        }
+        else {
+            static_cast<Gtk::Entry*>(w)->set_text(boost::get<std::string>(value));
+        }
+    }
+    catch(...) {
+        return false;
+    }
+    return true;
+}
+
+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());
+
+        DBG_OUT("setting date data %s\n", date.to_string().c_str());
+    }
+    catch(...) {
+        return false;
+    }
+    return true;
+}
 
 void MetaDataWidget::add_data(const MetaDataFormat * current,
                               const PropertyValue & value)
@@ -227,65 +348,22 @@ void MetaDataWidget::add_data(const MetaDataFormat * current,
 
     switch(current->type) {
     case META_DT_FRAC:
-        try {
-            double decimal = fwk::fraction_to_decimal(boost::get<std::string>(value));
-            std::string frac = boost::lexical_cast<std::string>(decimal);
-            AutoFlag flag(m_update);
-            static_cast<Gtk::Label*>(w)->set_text(frac);
-        }
-        catch(...) {
-            DBG_OUT("conversion of '%u' to frac failed", current->id);
-        }
+        set_fraction_data(w, value);
         break;
     case META_DT_STAR_RATING:
-        try {
-            int rating = boost::get<int>(value);
-            AutoFlag flag(m_update);
-            static_cast<fwk::RatingLabel*>(w)->set_rating(rating);
-        }
-        catch(...) {
-            DBG_OUT("conversion of '%u' to int failed", current->id);
-        }
+        set_star_rating_data(w, value);
         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());
-        }
+        set_string_array_data(w, value);
         break;
     case META_DT_TEXT:
-        try {
-            AutoFlag flag(m_update);
-            if(current->readonly) {
-                static_cast<Gtk::Label*>(w)->set_text(boost::get<std::string>(value));
-            }
-            else {
-                static_cast<Gtk::TextView*>(w)->get_buffer()->set_text(boost::get<std::string>(value));
-            }
-        }
-        catch(...) {
-            DBG_OUT("conversion of '%u' to int failed", current->id);
-        }
+        set_text_data(w, current->readonly, value);
+        break;
+    case META_DT_DATE:
+        set_date_data(w, value);
         break;
     default:
-        try {
-            AutoFlag flag(m_update);
-            if(current->readonly) {
-                static_cast<Gtk::Label*>(w)->set_text(boost::get<std::string>(value));
-            }
-            else {
-                static_cast<Gtk::Entry*>(w)->set_text(boost::get<std::string>(value));
-            }
-        }
-        catch(...) {
-            DBG_OUT("conversion of '%u' to string failed", current->id);
-        }
+        set_string_data(w, current->readonly, value);
         break;
     }
 }
diff --git a/src/fwk/toolkit/metadatawidget.hpp b/src/fwk/toolkit/metadatawidget.hpp
index fde9299..9792acb 100644
--- a/src/fwk/toolkit/metadatawidget.hpp
+++ b/src/fwk/toolkit/metadatawidget.hpp
@@ -20,7 +20,6 @@
 #ifndef __NIEPCE_FRAMEWORK_META_DATA_WIDGET_H__
 #define __NIEPCE_FRAMEWORK_META_DATA_WIDGET_H__
 
-
 #include <map>
 #include <string>
 
@@ -59,7 +58,6 @@ struct MetaDataSectionFormat {
     const MetaDataFormat * formats;
 };
 
-
 class XmpMeta;
 class TokenTextView;
 
@@ -84,6 +82,24 @@ protected:
 private:
     void clear_widget(std::pair<const PropertyIndex, Gtk::Widget *> & p);
     void create_widgets_for_format(const MetaDataSectionFormat * fmt);
+
+    // the widget factory
+    Gtk::Widget* create_star_rating_widget(bool readonly, uint32_t id);
+    Gtk::Widget* create_string_array_widget(bool readonly, uint32_t id);
+    Gtk::Widget* create_text_widget(bool readonly, uint32_t id);
+    Gtk::Widget* create_string_widget(bool readonly, uint32_t id);
+    Gtk::Widget* create_date_widget(bool readonly, uint32_t id);
+
+    // set data
+    bool set_fraction_data(Gtk::Widget* w, const PropertyValue & value);
+    bool set_star_rating_data(Gtk::Widget* w, const PropertyValue & value);
+    bool set_string_array_data(Gtk::Widget* w, const PropertyValue & value);
+    bool set_text_data(Gtk::Widget* w, bool readonly, 
+                       const PropertyValue & value);
+    bool set_string_data(Gtk::Widget* w, bool readonly,
+                         const PropertyValue & value);
+    bool set_date_data(Gtk::Widget* w, const PropertyValue & value);
+
     void emit_metadata_changed(fwk::PropertyIndex prop, const fwk::PropertyValue & value);
 
     Gtk::Table    m_table;
diff --git a/src/fwk/utils/exempi.cpp b/src/fwk/utils/exempi.cpp
index 6b32371..0fcc847 100644
--- a/src/fwk/utils/exempi.cpp
+++ b/src/fwk/utils/exempi.cpp
@@ -1,7 +1,7 @@
 /*
  * niepce - utils/exempi.cpp
  *
- * Copyright (C) 2007-2008 Hubert Figuiere
+ * Copyright (C) 2007-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
@@ -30,6 +30,7 @@
 #include <exempi/xmpconsts.h>
 
 #include "fwk/base/debug.hpp"
+#include "fwk/base/date.hpp"
 #include "exempi.hpp"
 #include "pathutils.hpp"
 
@@ -205,31 +206,17 @@ int32_t XmpMeta::flag() const
     return _flag;
 }
 
-
-time_t  XmpMeta::creation_date() const
+fwk::Date XmpMeta::creation_date() const
 {
-    time_t date = 0;
     XmpDateTime value;
     if(xmp_get_property_date(m_xmp, NS_EXIF, "DateTimeOriginal", 
                              &value, NULL)) {
-        struct tm dt;
-        dt.tm_sec = value.second;
-        dt.tm_min = value.minute;
-        dt.tm_hour = value.hour;
-        dt.tm_mday = value.day;
-        dt.tm_mon = value.month;
-        dt.tm_year = value.year - 1900;
-        dt.tm_isdst = -1;
-        // this field is supposed to be a glibc extension. oh joy.
-        dt.tm_gmtoff = value.tzSign * ((value.tzHour * 3600) +
-                                       (value.tzMinute * 60));
-        date = mktime(&dt);
-        DBG_ASSERT(date != -1, "date is -1");
+        return fwk::Date(value);
     }
     else {
         ERR_OUT("get \"DateTimeOriginal\" property failed: %d", xmp_get_error());
     }
-    return date;
+    return Date(0);
 }
 
 std::string XmpMeta::creation_date_str() const
diff --git a/src/fwk/utils/exempi.hpp b/src/fwk/utils/exempi.hpp
index df63f4c..278f38e 100644
--- a/src/fwk/utils/exempi.hpp
+++ b/src/fwk/utils/exempi.hpp
@@ -4,7 +4,7 @@
 /*
  * niepce - utils/exempi.h
  *
- * Copyright (C) 2007-2008 Hubert Figuiere
+ * Copyright (C) 2007-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
@@ -85,6 +85,8 @@ extern const char * UFRAW_INTEROP_NS_PREFIX;
 
 namespace fwk {
 
+class Date;
+
 class ExempiManager
     : public boost::noncopyable
 {
@@ -124,7 +126,7 @@ public:
     /** return the rating, -1 is not found (not set) */
     int32_t rating() const;
     int32_t flag() const;
-    time_t  creation_date() const;
+    fwk::Date  creation_date() const;
     std::string creation_date_str() const;
     const std::vector< std::string > & keywords() const;
 private:
diff --git a/src/niepce/modules/interfaces/Makefile.am b/src/niepce/modules/interfaces/Makefile.am
index e9bdfae..36476f7 100644
--- a/src/niepce/modules/interfaces/Makefile.am
+++ b/src/niepce/modules/interfaces/Makefile.am
@@ -1,6 +1,7 @@
 
 
 INCLUDES = -I$(top_srcdir)/src/ \
+	@EXEMPI_CFLAGS@ \
 	@LIBGLIBMM_CFLAGS@ \
 	@LIBGTKMM_CFLAGS@
 



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