[niepce] importer: show the picture thumbnails.



commit 8e6ec3e3810c414ad4e31099e1021478222ec1c2
Author: Hubert Figuière <hub figuiere net>
Date:   Mon May 15 21:23:25 2017 -0400

    importer: show the picture thumbnails.
    
    - move thumbnailing to fwk
    - Thumbnail class

 src/engine/Makefile.am                       |    1 -
 src/engine/importer/directoryimporter.cpp    |   13 +++
 src/engine/importer/directoryimporter.hpp    |    7 ++-
 src/engine/importer/iimporter.hpp            |   10 +++
 src/engine/library/thumbnailcache.cpp        |   83 ++++-----------------
 src/engine/library/thumbnailnotification.hpp |   21 +++---
 src/fwk/toolkit/Makefile.am                  |    3 +
 src/fwk/toolkit/thumbnail.cpp                |   93 +++++++++++++++++++++++
 src/fwk/toolkit/thumbnail.hpp                |   58 +++++++++++++++
 src/fwk/toolkit/uiresult.hpp                 |  102 ++++++++++++++++++++++++++
 src/niepce/ui/dialogs/importdialog.cpp       |   74 +++++++++++++++----
 src/niepce/ui/dialogs/importdialog.hpp       |    9 ++-
 src/niepce/ui/imageliststore.cpp             |    5 +-
 13 files changed, 378 insertions(+), 101 deletions(-)
---
diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am
index c980ffc..96e891f 100644
--- a/src/engine/Makefile.am
+++ b/src/engine/Makefile.am
@@ -1,7 +1,6 @@
 
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/  @FRAMEWORK_CFLAGS@ \
-       @OPENRAW_CFLAGS@ \
        $(NULL)
 
 TESTS = test_library test_filebundle test_opqueue
diff --git a/src/engine/importer/directoryimporter.cpp b/src/engine/importer/directoryimporter.cpp
index 6bb5aaa..2807786 100644
--- a/src/engine/importer/directoryimporter.cpp
+++ b/src/engine/importer/directoryimporter.cpp
@@ -18,6 +18,7 @@
  */
 
 #include <glibmm/i18n.h>
+#include <glibmm/miscutils.h>
 
 #include "fwk/base/debug.hpp"
 #include "fwk/utils/pathutils.hpp"
@@ -75,6 +76,18 @@ bool DirectoryImporter::listSourceContent(const std::string & source,
   return true;
 }
 
+bool DirectoryImporter::get_previews_for(const std::string& source,
+                                         const std::list<std::string>& paths,
+                                         const PreviewReady& callback)
+{
+  for (auto path : paths) {
+    auto full_path = Glib::build_filename(source, path);
+    auto thumbnail = fwk::Thumbnail::thumbnail_file(full_path, 160, 160, 0);
+    callback(path, thumbnail);
+  }
+  return true;
+}
+
 bool DirectoryImporter::doImport(const std::string& source,
                                  const FileImporter& callback)
 {
diff --git a/src/engine/importer/directoryimporter.hpp b/src/engine/importer/directoryimporter.hpp
index b778868..a20348c 100644
--- a/src/engine/importer/directoryimporter.hpp
+++ b/src/engine/importer/directoryimporter.hpp
@@ -20,7 +20,8 @@
 
 #pragma once
 
-#include <mutex>
+#include <string>
+#include <list>
 
 #include "fwk/utils/files.hpp"
 #include "engine/importer/iimporter.hpp"
@@ -38,9 +39,13 @@ public:
 
   bool listSourceContent(const std::string & source,
                          const SourceContentReady& callback) override;
+  bool get_previews_for(const std::string & source,
+                        const std::list<std::string>& paths,
+                        const PreviewReady& callback) override;
 
   bool doImport(const std::string & source,
                 const FileImporter & importer) override;
+
 };
 
 }
diff --git a/src/engine/importer/iimporter.hpp b/src/engine/importer/iimporter.hpp
index e5f16ff..03746a6 100644
--- a/src/engine/importer/iimporter.hpp
+++ b/src/engine/importer/iimporter.hpp
@@ -20,6 +20,11 @@
 
 #pragma once
 
+#include <string>
+#include <list>
+#include <functional>
+
+#include "fwk/toolkit/thumbnail.hpp"
 #include "engine/importer/importedfile.hpp"
 
 namespace eng {
@@ -41,6 +46,11 @@ public:
   virtual bool listSourceContent(const std::string & source,
                                  const SourceContentReady& callback) = 0;
 
+  typedef std::function<void (const std::string& path,
+                              const fwk::Thumbnail&)> PreviewReady;
+  virtual bool get_previews_for(const std::string& source,
+                                const std::list<std::string>& paths,
+                                const PreviewReady& callback) = 0;
 
   /** file importer callback */
   typedef std::function<void (const std::string&, bool)> FileImporter;
diff --git a/src/engine/library/thumbnailcache.cpp b/src/engine/library/thumbnailcache.cpp
index 2da56e9..ecff92a 100644
--- a/src/engine/library/thumbnailcache.cpp
+++ b/src/engine/library/thumbnailcache.cpp
@@ -22,16 +22,12 @@
 #include <boost/any.hpp>
 #include <boost/format.hpp>
 
-#include <gdkmm/pixbuf.h>
 #include <glibmm/miscutils.h>
-#include <libopenraw-gnome/gdkpixbuf.h>
 
 #include "niepce/notifications.hpp"
 #include "fwk/base/debug.hpp"
 #include "fwk/utils/pathutils.hpp"
-#include "fwk/toolkit/mimetype.hpp"
-#include "fwk/toolkit/gdkutils.hpp"
-#include "fwk/toolkit/movieutils.hpp"
+#include "fwk/toolkit/thumbnail.hpp"
 #include "thumbnailcache.hpp"
 #include "thumbnailnotification.hpp"
 
@@ -60,72 +56,28 @@ void ThumbnailCache::request(const LibFile::ListPtr & fl)
 
 namespace {
 
-// TODO see about 1. moving this out 2. abstracting the type away from Gdk::Pixbuf
-// Gdk does not belong to eng.
-Glib::RefPtr<Gdk::Pixbuf> getThumbnail(const LibFile::Ptr & f, int w, int h, const std::string & cached)
+fwk::Thumbnail getThumbnail(const LibFile::Ptr & f, int w, int h, const std::string & cached)
 {
+    const std::string & filename = f->path();
+
     if(ThumbnailCache::is_thumbnail_cached(f->path(), cached)) {
-        DBG_OUT("cached!");
+        DBG_OUT("thumbnail for %s is cached!", filename.c_str());
         return Gdk::Pixbuf::create_from_file(cached);
     }
-    const std::string & filename = f->path();
-    DBG_OUT("creating thumbnail for %s",filename.c_str());
 
-    fwk::MimeType mime_type(filename);
+    DBG_OUT("creating thumbnail for %s", filename.c_str());
+
     if(!fwk::ensure_path_for_file(cached)) {
         ERR_OUT("coudln't create directories for %s", cached.c_str());
     }
 
-    DBG_OUT("MIME type %s", mime_type.string().c_str());
-
-    Glib::RefPtr<Gdk::Pixbuf> pix;
-
-    if(mime_type.isUnknown()) {
-        DBG_OUT("unknown file type %s", filename.c_str());
-    }
-    else if(mime_type.isMovie()) {
-        try {
-            if(fwk::thumbnail_movie(filename, w, h, cached)) {
-                pix = Gdk::Pixbuf::create_from_file(cached, w, h, true);
-            }
-        }
-        catch(const Glib::Error & e) {
-            ERR_OUT("exception thumbnailing video %s", e.what().c_str());
-        }
-    }
-    else if(!mime_type.isImage()) {
-        DBG_OUT("not an image type");
-    }
-    else if(!mime_type.isDigicamRaw()) {
-        DBG_OUT("not a raw type, trying GdkPixbuf loaders");
-        try {
-            pix = Gdk::Pixbuf::create_from_file(filename, w, h, true);
-            if(pix) {
-                pix = fwk::gdkpixbuf_exif_rotate(pix, f->orientation());
-            }
-        }
-        catch(const Glib::Error & e) {
-            ERR_OUT("exception thumbnailing image %s", e.what().c_str());
-        }
-    }
-    else {
-        GdkPixbuf *pixbuf = or_gdkpixbuf_extract_rotated_thumbnail(filename.c_str(),
-                                                                   std::min(w, h));
-        if(pixbuf) {
-            pix = Glib::wrap(pixbuf, true); // take ownership
-            if((w < pix->get_width()) || (h < pix->get_height())) {
-                pix = fwk::gdkpixbuf_scale_to_fit(pix, std::min(w,h));
-            }
-        }
-    }
-    if(pix)
-    {
-        pix->save(cached, "png");
-    }
-    else {
+    auto thumbnail = fwk::Thumbnail::thumbnail_file(filename, w, h, f->orientation());
+    if (thumbnail.ok()) {
+        thumbnail.save(cached, "png");
+    } else {
         DBG_OUT("couldn't get the thumbnail for %s", filename.c_str());
     }
-    return pix;
+    return thumbnail;
 }
 
 }
@@ -136,22 +88,19 @@ void ThumbnailCache::execute(const ptr_t & task)
     w = task->width();
     h = task->height();
 
-    Glib::RefPtr<Gdk::Pixbuf> pix;
-
     std::string dest = path_for_thumbnail(task->file()->path(), task->file()->id(), std::max(w,h));
     DBG_OUT("cached thumbnail %s", dest.c_str());
 
-    pix = getThumbnail(task->file(), w, h, dest);
-
-    if(pix) {
+    fwk::Thumbnail pix = getThumbnail(task->file(), w, h, dest);
+    if(pix.ok()) {
         fwk::NotificationCenter::Ptr nc(m_notif_center);
         if(nc) {
             // pass the notification
             fwk::Notification::Ptr n(new fwk::Notification(niepce::NOTIFICATION_THUMBNAIL));
             ThumbnailNotification tn;
             tn.id = task->file()->id();
-            tn.width = pix->get_width();
-            tn.height = pix->get_height();
+            tn.width = pix.get_width();
+            tn.height = pix.get_height();
             tn.pixmap = pix;
             n->setData(boost::any(tn));
             DBG_OUT("notify thumbnail for id=%Ld", (long long)tn.id);
diff --git a/src/engine/library/thumbnailnotification.hpp b/src/engine/library/thumbnailnotification.hpp
index 7a4807e..8de0391 100644
--- a/src/engine/library/thumbnailnotification.hpp
+++ b/src/engine/library/thumbnailnotification.hpp
@@ -1,7 +1,7 @@
 /*
- * niepce - library/thumbnailnotification.h
+ * niepce - engine/library/thumbnailnotification.hpp
  *
- * Copyright (C) 2007 Hubert Figuiere
+ * Copyright (C) 2007-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
@@ -21,19 +21,18 @@
 #ifndef _LIBRARY_THUMBNAILNOTIFICATION_H__
 #define _LIBRARY_THUMBNAILNOTIFICATION_H__
 
-#include <gdkmm/pixbuf.h>
-
+#include "fwk/toolkit/thumbnail.hpp"
 #include "engine/db/librarytypes.hpp"
 
 namespace eng {
 
-       struct ThumbnailNotification
-       {
-               eng::library_id_t  id;
-               int  width;
-               int  height;
-               Glib::RefPtr<Gdk::Pixbuf> pixmap; 
-       };
+struct ThumbnailNotification
+{
+  eng::library_id_t  id;
+  int  width;
+  int  height;
+  fwk::Thumbnail pixmap;
+};
 
 }
 
diff --git a/src/fwk/toolkit/Makefile.am b/src/fwk/toolkit/Makefile.am
index fc3ac6e..f153d95 100644
--- a/src/fwk/toolkit/Makefile.am
+++ b/src/fwk/toolkit/Makefile.am
@@ -5,6 +5,7 @@
 AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/ext \
        -DDATADIR=\"$(datadir)\" \
        @FRAMEWORK_CFLAGS@ \
+       @OPENRAW_CFLAGS@ \
        $(NULL)
 
 noinst_LIBRARIES = libniepceframework.a
@@ -29,6 +30,8 @@ libniepceframework_a_SOURCES = configuration.hpp configuration.cpp \
        frame.hpp frame.cpp \
        controller.hpp controller.cpp \
        uicontroller.hpp uicontroller.cpp \
+       uiresult.hpp \
+       thumbnail.hpp thumbnail.cpp \
        mapcontroller.hpp mapcontroller.cpp \
        notification.hpp \
        mimetype.hpp mimetype.cpp \
diff --git a/src/fwk/toolkit/thumbnail.cpp b/src/fwk/toolkit/thumbnail.cpp
new file mode 100644
index 0000000..019e2f3
--- /dev/null
+++ b/src/fwk/toolkit/thumbnail.cpp
@@ -0,0 +1,93 @@
+/* -*- mode: C++; tab-width: 2; c-basic-offset: 2; indent-tabs-mode:nil; -*- */
+/*
+ * niepce - fwk/toolkit/thumbnail.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 "thumbnail.hpp"
+
+#include <glibmm/miscutils.h>
+#include <libopenraw-gnome/gdkpixbuf.h>
+
+#include "fwk/base/debug.hpp"
+#include "fwk/toolkit/mimetype.hpp"
+#include "fwk/toolkit/gdkutils.hpp"
+#include "fwk/toolkit/movieutils.hpp"
+
+namespace fwk {
+
+Thumbnail::Thumbnail(const Glib::RefPtr<Gdk::Pixbuf>& pixbuf)
+  : m_pixbuf(pixbuf)
+{
+}
+
+void Thumbnail::save(const std::string& path, const std::string& format)
+{
+  if (m_pixbuf) {
+    m_pixbuf->save(path, format);
+  }
+}
+
+Thumbnail Thumbnail::thumbnail_file(const std::string& filename,
+                                    int w, int h, int32_t orientation)
+{
+  fwk::MimeType mime_type(filename);
+  DBG_OUT("MIME type %s", mime_type.string().c_str());
+
+  Glib::RefPtr<Gdk::Pixbuf> pix;
+
+  if(mime_type.isUnknown()) {
+    DBG_OUT("unknown file type %s", filename.c_str());
+  } else if(mime_type.isMovie()) {
+    try {
+      // XXX FIXME
+      std::string cached = Glib::get_tmp_dir() + "/temp-1234";
+      if(fwk::thumbnail_movie(filename, w, h, cached)) {
+        pix = Gdk::Pixbuf::create_from_file(cached, w, h, true);
+      }
+    }
+    catch(const Glib::Error & e) {
+      ERR_OUT("exception thumbnailing video %s", e.what().c_str());
+    }
+  } else if(!mime_type.isImage()) {
+    DBG_OUT("not an image type");
+  } else if(!mime_type.isDigicamRaw()) {
+    DBG_OUT("not a raw type, trying GdkPixbuf loaders");
+    try {
+      pix = Gdk::Pixbuf::create_from_file(filename, w, h, true);
+      if(pix) {
+        pix = fwk::gdkpixbuf_exif_rotate(pix, orientation);
+      }
+    }
+    catch(const Glib::Error & e) {
+      ERR_OUT("exception thumbnailing image %s", e.what().c_str());
+    }
+  } else {
+    GdkPixbuf *pixbuf = or_gdkpixbuf_extract_rotated_thumbnail(filename.c_str(),
+                                                               std::min(w, h));
+    if(pixbuf) {
+      pix = Glib::wrap(pixbuf, true); // take ownership
+      if((w < pix->get_width()) || (h < pix->get_height())) {
+        pix = fwk::gdkpixbuf_scale_to_fit(pix, std::min(w,h));
+      }
+    }
+  }
+
+  return Thumbnail(pix);
+}
+
+}
diff --git a/src/fwk/toolkit/thumbnail.hpp b/src/fwk/toolkit/thumbnail.hpp
new file mode 100644
index 0000000..c039015
--- /dev/null
+++ b/src/fwk/toolkit/thumbnail.hpp
@@ -0,0 +1,58 @@
+/* -*- mode: C++; tab-width: 2; c-basic-offset: 2; indent-tabs-mode:nil; -*- */
+/*
+ * niepce - fwk/toolkit/thumbnail.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/>.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <string>
+
+#include <gdkmm/pixbuf.h>
+
+namespace fwk {
+
+class Thumbnail {
+public:
+  Thumbnail() = default;
+  Thumbnail(const Glib::RefPtr<Gdk::Pixbuf>& pixbuf);
+
+  bool ok() const {
+    return !!m_pixbuf;
+  }
+
+  int get_width() const {
+    return m_pixbuf->get_width();
+  }
+  int get_height() const {
+    return m_pixbuf->get_height();
+  }
+  const Glib::RefPtr<Gdk::Pixbuf>& pixbuf() const {
+    return m_pixbuf;
+  }
+
+  void save(const std::string& path, const std::string& format);
+
+  static Thumbnail thumbnail_file(const std::string& path, int w, int h, int32_t orientation);
+
+private:
+  Glib::RefPtr<Gdk::Pixbuf> m_pixbuf;
+};
+
+}
diff --git a/src/fwk/toolkit/uiresult.hpp b/src/fwk/toolkit/uiresult.hpp
new file mode 100644
index 0000000..e1cbdb3
--- /dev/null
+++ b/src/fwk/toolkit/uiresult.hpp
@@ -0,0 +1,102 @@
+/* -*- mode: C++; tab-width: 2; c-basic-offset: 2; indent-tabs-mode:nil; -*- */
+/*
+ * niepce - fwk/toolkit/uiresult.hpp
+ *
+ * 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/>.
+ */
+
+
+
+#pragma once
+
+#include <deque>
+#include <mutex>
+
+#include <glibmm/dispatcher.h>
+
+#include "fwk/base/option.hpp"
+
+namespace fwk {
+
+class UIResult
+{
+public:
+  virtual void clear() = 0;
+
+  sigc::connection connect(sigc::slot<void>&& slot) {
+    return m_notifier.connect(std::move(slot));
+  }
+protected:
+  Glib::Dispatcher m_notifier;
+  std::mutex m_data_mutex;
+};
+
+template<class T>
+class UIResultSingle
+  : public UIResult
+{
+public:
+  void clear() override {
+    m_data = T();
+  }
+
+  void send_data(T&& d) {
+    {
+      std::lock_guard<std::mutex> lock(m_data_mutex);
+      m_data = std::move(d);
+    }
+    m_notifier.emit();
+  };
+  T recv_data() {
+    {
+      std::lock_guard<std::mutex> lock(m_data_mutex);
+      return m_data;
+    }
+  };
+private:
+  T m_data;
+};
+
+template<class T>
+class UIResults
+  : public UIResult
+{
+public:
+  void clear() override {
+    m_data.clear();
+  }
+
+  void send_data(T&& d) {
+    {
+      std::lock_guard<std::mutex> lock(m_data_mutex);
+      m_data.push_back(std::move(d));
+    }
+    m_notifier.emit();
+  };
+  Option<T> recv_data() {
+    std::lock_guard<std::mutex> lock(m_data_mutex);
+    if (m_data.empty()) {
+      return Option<T>();
+    }
+    auto result = Option<T>(m_data.front());
+    m_data.pop_front();
+    return result;
+  };
+private:
+  std::deque<T> m_data;
+};
+
+}
diff --git a/src/niepce/ui/dialogs/importdialog.cpp b/src/niepce/ui/dialogs/importdialog.cpp
index ea4085b..3d2eb11 100644
--- a/src/niepce/ui/dialogs/importdialog.cpp
+++ b/src/niepce/ui/dialogs/importdialog.cpp
@@ -55,8 +55,6 @@ ImportDialog::ImportDialog()
     , m_attributesScrolled(nullptr)
     , m_images_list_scrolled(nullptr)
 {
-  m_received_files_to_import.connect(
-    sigc::mem_fun(this, &ImportDialog::append_files_to_import));
 }
 
 ImportDialog::~ImportDialog()
@@ -99,35 +97,48 @@ void ImportDialog::setup_widget()
     m_gridview->set_text_column(m_grid_columns.filename);
     m_gridview->show();
     m_images_list_scrolled->add(*m_gridview);
+    m_images_list_scrolled->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+
+    m_previews_to_import.connect(
+      sigc::mem_fun(this, &ImportDialog::preview_received));
+    m_files_to_import.connect(
+      sigc::mem_fun(this, &ImportDialog::append_files_to_import));
+
     m_is_setup = true;
 }
 
 // XXX doesn't belong here
 void ImportDialog::doSelectDirectories()
 {
-    Configuration & cfg = Application::app()->config();
+  Configuration & cfg = Application::app()->config();
 
+  Glib::ustring filename;
+  {
     Gtk::FileChooserDialog dialog(gtkWindow(), _("Import picture folder"),
                                   Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
 
     dialog.add_button(_("Cancel"), Gtk::RESPONSE_CANCEL);
-    dialog.add_button(_("Import"), Gtk::RESPONSE_OK);
+    dialog.add_button(_("Select"), Gtk::RESPONSE_OK);
     dialog.set_select_multiple(false);
 
     std::string last_import_location = cfg.getValue("last_import_location", "");
-    if(!last_import_location.empty()) {
-        dialog.set_filename(last_import_location);
+    if (!last_import_location.empty()) {
+      dialog.set_filename(last_import_location);
     }
 
     int result = dialog.run();
     switch(result)
     {
     case Gtk::RESPONSE_OK:
-        setToImport(dialog.get_filename());
-        break;
+      filename = dialog.get_filename();
+      break;
     default:
-        break;
+      break;
     }
+  }
+  if (!filename.empty()) {
+    setToImport(filename);
+  }
 }
 
 // XXX doesn't belong here. Or must be deeply modified to deal with the Importer
@@ -140,15 +151,12 @@ void ImportDialog::setToImport(const Glib::ustring & f)
 
     eng::IImporter::SourceContentReady source_content_ready =
       [this] (std::list<eng::ImportedFile::Ptr>&& list_to_import) {
-        {
-          std::lock_guard<std::mutex> lock(this->m_files_to_import_lock);
-          this->m_files_to_import = list_to_import;
-        }
-        this->m_received_files_to_import.emit();
+        this->m_files_to_import.send_data(std::move(list_to_import));
       };
 
 
     m_images_list_model->clear();
+    m_images_list_map.clear();
     m_files_to_import.clear();
 
     auto importer = m_importer;
@@ -165,15 +173,49 @@ void ImportDialog::setToImport(const Glib::ustring & f)
 
 void ImportDialog::append_files_to_import()
 {
-  std::lock_guard<std::mutex> lock(this->m_files_to_import_lock);
-  for(const auto & f : m_files_to_import) {
+  auto files_to_import = m_files_to_import.recv_data();
+
+  if (!m_images_list_model) {
+    ERR_OUT("No image list model");
+    return;
+  }
+  // request the previews to the importer.tn.pixmap.pixbuf()
+  std::list<std::string> paths;
+  for(const auto & f : files_to_import) {
     DBG_OUT("selected %s", f->name().c_str());
+    paths.push_back(f->name());
     Gtk::TreeIter iter = m_images_list_model->append();
+    m_images_list_map.insert(std::make_pair(f->name(), iter));
     iter->set_value(m_grid_columns.filename, Glib::ustring(f->name()));
     iter->set_value(m_grid_columns.file, std::move(f));
   }
+
+  eng::IImporter::PreviewReady preview_ready = [this] (const std::string& path,
+                                                       const fwk::Thumbnail& thumbnail) {
+    this->m_previews_to_import.send_data(std::make_pair(path, thumbnail));
+  };
+
+  auto importer = m_importer;
+  auto source = m_folder_path_source.raw();
+  std::async(std::launch::async,
+             [importer, source, paths, preview_ready] () {
+               return importer->get_previews_for(source, paths, preview_ready);
+             });
 }
 
+void ImportDialog::preview_received()
+{
+  auto result = m_previews_to_import.recv_data();
+  if (!result.empty()) {
+    auto preview = result.unwrap();
+    auto iter = m_images_list_map.find(preview.first);
+    if (iter != m_images_list_map.end()) {
+      iter->second->set_value(m_grid_columns.pixbuf, preview.second.pixbuf());
+    }
+  }
+}
+
+
 }
 
 /*
diff --git a/src/niepce/ui/dialogs/importdialog.hpp b/src/niepce/ui/dialogs/importdialog.hpp
index c02ef0c..2ae942d 100644
--- a/src/niepce/ui/dialogs/importdialog.hpp
+++ b/src/niepce/ui/dialogs/importdialog.hpp
@@ -31,6 +31,7 @@
 #include "engine/importer/importedfile.hpp"
 #include "fwk/toolkit/gtkutils.hpp"
 #include "fwk/toolkit/dialog.hpp"
+#include "fwk/toolkit/uiresult.hpp"
 #include "imageliststore.hpp"
 #include "metadatapanecontroller.hpp"
 
@@ -43,6 +44,7 @@ class TreeView;
 
 namespace fwk {
 class ImageGridView;
+class Thumbnail;
 }
 
 namespace eng {
@@ -85,6 +87,7 @@ private:
 
     void doSelectDirectories();
     void append_files_to_import();
+    void preview_received();
 
     std::shared_ptr<eng::IImporter> m_importer; // as shared_ptr<> for lambda capture
     Glib::ustring m_folder_path_source;
@@ -98,14 +101,14 @@ private:
     Gtk::ScrolledWindow *m_images_list_scrolled;
     PreviewGridModel m_grid_columns;
     Glib::RefPtr<Gtk::ListStore> m_images_list_model;
+    std::map<std::string, Gtk::TreeIter> m_images_list_map;
 
     Gtk::IconView *m_gridview;
 
     MetaDataPaneController::Ptr m_metadata_pane;
 
-    Glib::Dispatcher m_received_files_to_import;
-    std::mutex m_files_to_import_lock;
-    std::list<eng::ImportedFile::Ptr> m_files_to_import;
+    fwk::UIResultSingle<std::list<eng::ImportedFile::Ptr>> m_files_to_import;
+    fwk::UIResults<std::pair<std::string, fwk::Thumbnail>> m_previews_to_import;
 };
 
 }
diff --git a/src/niepce/ui/imageliststore.cpp b/src/niepce/ui/imageliststore.cpp
index 329bde3..4fb2b0b 100644
--- a/src/niepce/ui/imageliststore.cpp
+++ b/src/niepce/ui/imageliststore.cpp
@@ -160,9 +160,10 @@ void ImageListStore::on_tnail_notification(const eng::ThumbnailNotification &tn)
         = m_idmap.find( tn.id );
     if(iter != m_idmap.end()) {
         // found the icon view item
+        auto pixbuf = tn.pixmap.pixbuf();
         Gtk::TreeRow row = *(iter->second);
-        row[m_columns.m_pix] = tn.pixmap;
-        row[m_columns.m_strip_thumb] = fwk::gdkpixbuf_scale_to_fit(tn.pixmap, 100);
+        row[m_columns.m_pix] = pixbuf;
+        row[m_columns.m_strip_thumb] = fwk::gdkpixbuf_scale_to_fit(pixbuf, 100);
     }
     else {
         DBG_OUT("row %Ld not found", (long long)tn.id);


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