[glom] Image fields: Support PDF (and other types supported by evince)



commit f62ccd279011474a00c2ff52a438386d5f1d304a
Author: Murray Cumming <murrayc murrayc com>
Date:   Wed Jul 13 11:23:42 2011 +0200

    Image fields: Support PDF (and other types supported by evince)
    
    * configure.ac: Depend on evince-view-3.0, which is a library installed by
    evince. It is packaged separately from evince by distros.
    * glom/main.cc: Call ev_init().
    * glom/utility_widgets/dialog_image_load_progress.[h|cc]: Remove
    get_pixbuf() and do not use Gdk::PixbufLoader here.
    * glom/utility_widgets/imageglom.[h|cc]: Create the pixbuf here, from
    the data from the dialog.
    Add an EvView, and use that instead of the Gtk::Image when the mime type is
    supported by EvView. We use g_content_type_guess() to sniff the mime type
    from the actual data, but this will probably not always work. We should
    store the mime type (and the filename) too.
    
    The context menu doesn't work with the EvView yet.

 ChangeLog                                          |   18 ++
 configure.ac                                       |    2 +-
 glom/main.cc                                       |    4 +
 glom/utility_widgets/dialog_image_load_progress.cc |   23 --
 glom/utility_widgets/dialog_image_load_progress.h  |    3 -
 glom/utility_widgets/imageglom.cc                  |  321 ++++++++++++++++----
 glom/utility_widgets/imageglom.h                   |   21 ++-
 7 files changed, 301 insertions(+), 91 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 59e7b5e..d3fdb29 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2011-07-13  Murray Cumming  <murrayc murrayc com>
+
+	Image fields: Support PDF (and other types supported by evince)
+
+	* configure.ac: Depend on evince-view-3.0, which is a library installed by 
+	evince. It is packaged separately from evince by distros.
+	* glom/main.cc: Call ev_init().
+	* glom/utility_widgets/dialog_image_load_progress.[h|cc]: Remove 
+	get_pixbuf() and do not use Gdk::PixbufLoader here.
+	* glom/utility_widgets/imageglom.[h|cc]: Create the pixbuf here, from 
+	the data from the dialog.
+	Add an EvView, and use that instead of the Gtk::Image when the mime type is 
+	supported by EvView. We use g_content_type_guess() to sniff the mime type 
+	from the actual data, but this will probably not always work. We should 
+	store the mime type (and the filename) too.
+	
+	The context menu doesn't work with the EvView yet.
+
 1.19.7:
 
 2011-07-12  Murray Cumming  <murrayc murrayc com>
diff --git a/configure.ac b/configure.ac
index 3c6f813..e3d61c7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -160,7 +160,7 @@ AS_IF([test "x$glom_host_win32" != xyes],
       [REQUIRED_LIBGLOM_LIBS="$REQUIRED_LIBGLOM_LIBS libepc-1.0 >= 0.4.0"])
 
 # Libraries used by Glom:
-REQUIRED_GLOM_LIBS="$REQUIRED_LIBGLOM_LIBS gtkmm-3.0 >= 2.99.1 gthread-2.0 libxml++-2.6 libxslt >= 1.1.10 goocanvasmm-2.0 >= 1.90.3"
+REQUIRED_GLOM_LIBS="$REQUIRED_LIBGLOM_LIBS gtkmm-3.0 >= 2.99.1 gthread-2.0 libxml++-2.6 libxslt >= 1.1.10 goocanvasmm-2.0 >= 1.90.3 evince-view-3.0"
 
 # Do not require iso-codes in client-only mode, or on Windows:
 # TODO: Package iso-codes for Windows?
diff --git a/glom/main.cc b/glom/main.cc
index aba449c..51733fb 100644
--- a/glom/main.cc
+++ b/glom/main.cc
@@ -61,6 +61,8 @@
 #include <glom/glade_utils.h>
 #include <glom/utils_ui.h>
 
+#include <evince-view.h>
+
 #ifdef G_OS_WIN32
 #include <winsock2.h>
 #else
@@ -535,6 +537,8 @@ main(int argc, char* argv[])
     Goocanvas::init(PACKAGE_NAME, PACKAGE_VERSION, argc, argv);
 #endif //!GLOM_ENABLE_CLIENT_ONLY
 
+    ev_init();
+
     //Get command-line parameters, if any:
     Glib::ustring input_uri = group.m_arg_filename;
 
diff --git a/glom/utility_widgets/dialog_image_load_progress.cc b/glom/utility_widgets/dialog_image_load_progress.cc
index 83558b2..892196e 100644
--- a/glom/utility_widgets/dialog_image_load_progress.cc
+++ b/glom/utility_widgets/dialog_image_load_progress.cc
@@ -51,20 +51,6 @@ DialogImageLoadProgress::~DialogImageLoadProgress()
   if(m_data.get())
     g_free(m_data->data);
 
-  if(m_loader)
-  {
-    try
-    {
-      m_loader->close();
-    }
-    catch(const Glib::Error& ex)
-    {
-      // Ignore error, it's normal for close() to throw when the image has
-      // not yet been loaded completely, for example when cancelling the
-      // dialog.
-    }
-  }
-
   // TODO: Cancel outstanding async operations in destructor?
 }
 
@@ -73,7 +59,6 @@ void DialogImageLoadProgress::load(const Glib::ustring& uri)
   // Can only load one file with data 
   g_assert(!m_data.get());
 
-  m_loader = Gdk::PixbufLoader::create();
   m_data.reset(new GdaBinary);
   m_data->data = 0;
   m_data->binary_length = 0;
@@ -136,9 +121,6 @@ void DialogImageLoadProgress::on_stream_read(const Glib::RefPtr<Gio::AsyncResult
     // Cannot read more data than there is available in the file:
     g_assert( static_cast<gssize>(offset + size) <= static_cast<gssize>(m_data->binary_length));
     
-    // Load image
-    m_loader->write(m_data->data + offset, size);
-    
     // Set progress
     m_progress_bar->set_fraction(static_cast<double>(offset + size) / m_data->binary_length);
     
@@ -181,9 +163,4 @@ std::auto_ptr<GdaBinary> DialogImageLoadProgress::get_image_data()
   return m_data;
 }
 
-Glib::RefPtr<Gdk::Pixbuf> DialogImageLoadProgress::get_pixbuf() 
-{
-  return m_loader->get_pixbuf();
-}
-
 } // namespace Glom
diff --git a/glom/utility_widgets/dialog_image_load_progress.h b/glom/utility_widgets/dialog_image_load_progress.h
index 3275e6b..6057f83 100644
--- a/glom/utility_widgets/dialog_image_load_progress.h
+++ b/glom/utility_widgets/dialog_image_load_progress.h
@@ -24,7 +24,6 @@
 #include <gtkmm/dialog.h>
 #include <gtkmm/builder.h>
 #include <gtkmm/progressbar.h>
-#include <gdkmm/pixbufloader.h>
 #include <giomm/file.h>
 #include <giomm/fileinputstream.h>
 #include <libgda/libgda.h>
@@ -45,7 +44,6 @@ public:
   void load(const Glib::ustring& uri);
 
   std::auto_ptr<GdaBinary> get_image_data();
-  Glib::RefPtr<Gdk::Pixbuf> get_pixbuf();
 
 private:
   void error(const Glib::ustring& error_message);
@@ -55,7 +53,6 @@ private:
   void on_stream_read(const Glib::RefPtr<Gio::AsyncResult>& result, unsigned int offset);
   void on_read_next(unsigned int at);
 
-  Glib::RefPtr<Gdk::PixbufLoader> m_loader;
   std::auto_ptr<GdaBinary> m_data;
   Gtk::ProgressBar* m_progress_bar;
 
diff --git a/glom/utility_widgets/imageglom.cc b/glom/utility_widgets/imageglom.cc
index fc9743b..2e1bf9a 100644
--- a/glom/utility_widgets/imageglom.cc
+++ b/glom/utility_widgets/imageglom.cc
@@ -32,8 +32,11 @@
 namespace Glom
 {
 
+ImageGlom::type_vec_ustrings ImageGlom::m_evince_supported_mime_types;
+
 ImageGlom::ImageGlom()
-: m_image(Gtk::Stock::MISSING_IMAGE, Gtk::ICON_SIZE_DIALOG), //The widget is invisible if we don't specify an image.
+: m_ev_view(0),
+  m_ev_document_model(0),
   m_pMenuPopup_UserMode(0)
 {
   init();
@@ -41,7 +44,8 @@ ImageGlom::ImageGlom()
 
 ImageGlom::ImageGlom(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& /* builder */)
 : Gtk::EventBox(cobject),
-  m_image(Gtk::Stock::MISSING_IMAGE, Gtk::ICON_SIZE_DIALOG), //The widget is invisible if we don't specify an image.
+  m_ev_view(0),
+  m_ev_document_model(0),
   m_pMenuPopup_UserMode(0)
 {
   init();
@@ -49,6 +53,8 @@ ImageGlom::ImageGlom(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>&
 
 void ImageGlom::init()
 {
+  m_ev_view = EV_VIEW(ev_view_new());
+
   m_read_only = false;
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
@@ -58,10 +64,9 @@ void ImageGlom::init()
   setup_menu_usermode();
 
   //m_image.set_size_request(150, 150);
-  m_image.show();
+
 
   m_frame.set_shadow_type(Gtk::SHADOW_ETCHED_IN); //Without this, the image widget has no borders and is completely invisible when empty.
-  m_frame.add(m_image);
   m_frame.show();
 
   add(m_frame);
@@ -149,26 +154,21 @@ bool ImageGlom::get_has_original_data() const
   return true; //TODO.
 }
 
+/*
 void ImageGlom::set_pixbuf(const Glib::RefPtr<Gdk::Pixbuf>& pixbuf)
 {
   m_pixbuf_original = pixbuf;
-  scale();
+  show_image_data();
 }
+*/
 
 void ImageGlom::set_value(const Gnome::Gda::Value& value)
 {
   // Remember original data 
   m_original_data = Gnome::Gda::Value();
   m_original_data = value;
-  Glib::RefPtr<Gdk::Pixbuf> pixbuf = Utils::get_pixbuf_for_gda_value(value);
+  show_image_data();
 
-  if(pixbuf)
-  {
-    scale();
-    set_pixbuf(pixbuf);
-  }
-  else
-  {
     /*
     std::cout << "Debug: Setting MISSING_IMAGE" << std::endl;
     
@@ -189,7 +189,7 @@ void ImageGlom::set_value(const Gnome::Gda::Value& value)
       if(iterFind != sizes.end())
       {
      */
-        m_image.set(Gtk::Stock::MISSING_IMAGE, Gtk::ICON_SIZE_DIALOG);
+        //m_image.set(Gtk::Stock::MISSING_IMAGE, Gtk::ICON_SIZE_DIALOG);
      /*
       }
       else
@@ -213,10 +213,8 @@ void ImageGlom::set_value(const Gnome::Gda::Value& value)
       std::cerr << "Glom: No Gtk::Style available for this widget (yet), so not setting MISSING_IMAGE icon." << std::endl;
       m_image.set("");
     }
-    */
-
-    m_pixbuf_original = Glib::RefPtr<Gdk::Pixbuf>();
   }
+  */
 }
 
 Gnome::Gda::Value ImageGlom::get_value() const
@@ -267,61 +265,206 @@ bool ImageGlom::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
 {
   const bool result = Gtk::EventBox::on_draw(cr);
 
-  scale();
+  if(m_pixbuf_original);
+    scale_image();
+
   return result;
 }
 
-void ImageGlom::scale()
+static void image_glom_ev_job_finished(EvJob* job, void* user_data)
 {
-  Glib::RefPtr<Gdk::Pixbuf> pixbuf = m_pixbuf_original;
+  g_assert(job);
+  
+  ImageGlom* self = (ImageGlom*)user_data;
+  g_assert(self);
+  
+  self->on_ev_job_finished(job);
+}
+  
+void ImageGlom::on_ev_job_finished(EvJob* job)
+{
+	if (ev_job_is_failed (job)) {
+		g_warning ("%s", job->error->message);
+		g_object_unref (job);
+
+		return;
+	}
+
+	ev_document_model_set_document(m_ev_document_model, job->document);
+	ev_document_model_set_page(m_ev_document_model, 1);
+	g_object_unref (job);
+	
+	ev_view_set_loading(m_ev_view, FALSE);
+}
 
-  if(pixbuf)
+Glib::ustring ImageGlom::get_mime_type() const
+{
+  const GdaBinary* gda_binary = gda_value_get_binary(m_original_data.gobj());
+  if(!gda_binary)
+    return Glib::ustring();
+    
+  if(!gda_binary->data)
+    return Glib::ustring();
+
+  bool uncertain = false;
+  const Glib::ustring result = Gio::content_type_guess(std::string(),
+    gda_binary->data, gda_binary->binary_length,
+    uncertain);
+
+  //std::cout << G_STRFUNC << ": mime_type=" << result << ", uncertain=" << uncertain << std::endl;
+  return result;  
+}
+
+void ImageGlom::fill_evince_supported_mime_types()
+{
+  //Fill the static list if it has not already been filled:
+  if(!m_evince_supported_mime_types.empty())
+    return;
+
+  //Discover what mime types libevview can support.
+  //Older versions supported image types too, via GdkPixbuf,
+  //but that support was then removed.  
+  GList* types_list = ev_backends_manager_get_all_types_info();
+  if(!types_list)
+  {
+    return;
+  }
+  
+  for(GList* l = types_list; l; l = g_list_next(l))
+  {
+	  EvTypeInfo *info = (EvTypeInfo *)l->data;
+	  if(!info)
+	    continue;
+
+	  const char* mime_type = 0;
+	  int i = 0;
+	  while((mime_type = info->mime_types[i++]))
+	  {
+	    if(mime_type)
+	      m_evince_supported_mime_types.push_back(mime_type);
+	    //std::cout << "evince supported mime_type=" << mime_type << std::endl; 
+	  }
+	}  
+}
+
+void ImageGlom::show_image_data()
+{
+  bool use_evince = false;
+  
+  const Glib::ustring mime_type = get_mime_type();
+  //std::cout << "mime_type=" << mime_type << std::endl; 
+  
+  fill_evince_supported_mime_types();
+  const type_vec_ustrings::iterator iterFind = 
+    std::find(m_evince_supported_mime_types.begin(),
+      m_evince_supported_mime_types.end(),
+      mime_type);
+  if(iterFind != m_evince_supported_mime_types.end())
+  {
+    use_evince = true;
+  }
+  
+  m_frame.remove();
+  
+
+  //Clear all possible display widgets:
+  m_pixbuf_original.reset();
+  m_image.set(m_pixbuf_original);
+  
+  if(m_ev_document_model)
+  {
+    g_object_unref(m_ev_document_model);
+    m_ev_document_model = 0;
+  }
+
+  if(use_evince)
   {
-    const Gtk::Allocation allocation = m_image.get_allocation();
-    const int pixbuf_height = pixbuf->get_height();
-    const int pixbuf_width = pixbuf->get_width();
+    //Use EvView:
+    m_image.hide();
     
-    int allocation_height = allocation.get_height();
-    int allocation_width = allocation.get_width();
+    gtk_widget_show(GTK_WIDGET(m_ev_view));
+    gtk_container_add(GTK_CONTAINER(m_frame.gobj()), GTK_WIDGET(m_ev_view));
+
+    const Glib::ustring uri = save_to_temp_file(false /* don't show progress */);
+    if(uri.empty())
+    {
+      std::cerr << G_STRFUNC << "Could not save temp file to show in the EvView." << std::endl;
+    }
+  
+    EvJob *job = ev_job_load_new(uri.c_str());
+  
+    m_ev_document_model = ev_document_model_new();
+    ev_view_set_model(m_ev_view, m_ev_document_model);
+	  ev_document_model_set_continuous(m_ev_document_model, FALSE); //Show only one page.
+	  ev_view_set_loading(m_ev_view, TRUE);
+	
+    g_signal_connect (job, "finished",
+		  G_CALLBACK (image_glom_ev_job_finished), this);
+	  ev_job_scheduler_push_job (job, EV_JOB_PRIORITY_NONE);
+  }
+  else
+  {
+    //Use GtkImage instead:
+
+    gtk_widget_hide(GTK_WIDGET(m_ev_view));
+      
+    m_image.show();
+    m_frame.add(m_image);
+    
+    m_pixbuf_original = Utils::get_pixbuf_for_gda_value(m_original_data);
+    m_image.set(m_pixbuf_original);
+  }
+}
+
+void ImageGlom::scale_image()
+{
+  Glib::RefPtr<Gdk::Pixbuf> pixbuf = m_pixbuf_original;
+
+  if(!pixbuf)
+    return;
+ 
+  const Gtk::Allocation allocation = m_image.get_allocation();
+  const int pixbuf_height = pixbuf->get_height();
+  const int pixbuf_width = pixbuf->get_width();
     
-    //If the Image widget has expanded to be big enough for the original image,
-    //it might be huge. We don't want that.
-    //Scaling it down will reduce how much it requests.
-    if(allocation_width >= 400)
-      allocation_width = 400;
+  int allocation_height = allocation.get_height();
+  int allocation_width = allocation.get_width();
+    
+  //If the Image widget has expanded to be big enough for the original image,
+  //it might be huge. We don't want that.
+  //Scaling it down will reduce how much it requests.
+  if(allocation_width >= 400)
+    allocation_width = 400;
       
-    if(allocation_height >= 400)
-      allocation_height = 400;
+  if(allocation_height >= 400)
+    allocation_height = 400;
       
-    //std::cout << "pixbuf_height=" << pixbuf_height << ", pixbuf_width=" << pixbuf_width << std::endl;
-    //std::cout << "allocation_height=" << allocation.get_height() << ", allocation_width=" << allocation.get_width() << std::endl;
+  //std::cout << "pixbuf_height=" << pixbuf_height << ", pixbuf_width=" << pixbuf_width << std::endl;
+  //std::cout << "allocation_height=" << allocation.get_height() << ", allocation_width=" << allocation.get_width() << std::endl;
 
-    if( (pixbuf_height >allocation_height ) ||
-        (pixbuf_width > allocation_width) )
+  if( (pixbuf_height >allocation_height ) ||
+      (pixbuf_width > allocation_width) )
+  {
+    if(allocation_height > 10 || allocation_width > 10)
     {
-      if(allocation_height > 10 || allocation_width > 10)
+      Glib::RefPtr<Gdk::Pixbuf> pixbuf_scaled = Utils::image_scale_keeping_ratio(pixbuf, allocation.get_height(), allocation.get_width());
+      if(!pixbuf_scaled)
       {
-        Glib::RefPtr<Gdk::Pixbuf> pixbuf_scaled = Utils::image_scale_keeping_ratio(pixbuf, allocation.get_height(), allocation.get_width());
-        if(!pixbuf_scaled)
-        {
-          std::cerr << "Utils::image_scale_keeping_ratio() returned NULL pixbuf." << std::endl;
-        }
-        else 
-        {
-          //Don't set a new pixbuf if the dimensions have not changed:
-          Glib::RefPtr<const Gdk::Pixbuf> pixbuf_in_image;
+        std::cerr << "Utils::image_scale_keeping_ratio() returned NULL pixbuf." << std::endl;
+      }
+      else 
+      {
+        //Don't set a new pixbuf if the dimensions have not changed:
+        Glib::RefPtr<const Gdk::Pixbuf> pixbuf_in_image;
 
-          if(m_image.get_storage_type() == Gtk::IMAGE_PIXBUF) //Prevent warning.
-            pixbuf_in_image = m_image.get_pixbuf();
+        if(m_image.get_storage_type() == Gtk::IMAGE_PIXBUF) //Prevent warning.
+          pixbuf_in_image = m_image.get_pixbuf();
 
-          if( !pixbuf_in_image || (pixbuf_in_image->get_height() != pixbuf_scaled->get_height()) || (pixbuf_in_image->get_width() != pixbuf_scaled->get_width()) )
-            m_image.set(pixbuf_scaled);
-        }
+        if( !pixbuf_in_image || (pixbuf_in_image->get_height() != pixbuf_scaled->get_height()) || (pixbuf_in_image->get_width() != pixbuf_scaled->get_width()) )
+          m_image.set(pixbuf_scaled);
       }
     }
   }
-  //else
-  //  g_warning("ImageGlom::scale(): attempt to scale a null pixbuf.");
 }
 
 void ImageGlom::on_menupopup_activate_open_file()
@@ -350,8 +493,10 @@ void ImageGlom::on_menupopup_activate_open_file_with()
   open_with(app_info);
 }
 
-void ImageGlom::open_with(const Glib::RefPtr<Gio::AppInfo>& app_info)
+Glib::ustring ImageGlom::save_to_temp_file(bool show_progress)
 {
+  Glib::ustring uri;
+  
   //Get a temporary file path:
   std::string filepath;
   const int filehandle = Glib::file_open_tmp(filepath);
@@ -360,12 +505,30 @@ void ImageGlom::open_with(const Glib::RefPtr<Gio::AppInfo>& app_info)
   if(filepath.empty())
   {
     std::cerr << G_STRFUNC << ": Glib::file_open_tmp() returned an empty filepath" << std::endl;
-    return;
+    return uri;
   }
   
-  const Glib::ustring uri = Glib::filename_to_uri(filepath);
+  uri = Glib::filename_to_uri(filepath);
+  
+  bool saved = false;
+  if(show_progress)
+    saved = save_file(uri);
+  else
+    saved = save_file_sync(uri);
   
-  if(!save_file(uri))
+  if(!saved)
+  {
+    uri = Glib::ustring();
+    std::cerr << G_STRFUNC << ": save_file() failed." << std::endl;
+  }
+
+  return uri;
+}
+
+void ImageGlom::open_with(const Glib::RefPtr<Gio::AppInfo>& app_info)
+{
+  const Glib::ustring uri = save_to_temp_file();
+  if(uri.empty())
     return;
 
   if(app_info)
@@ -432,6 +595,40 @@ void ImageGlom::on_menupopup_activate_save_file()
   save_file(uri);
 }
 
+bool ImageGlom::save_file_sync(const Glib::ustring& uri)
+{
+  //TODO: We should still do this asynchronously, 
+  //even when we don't use the dialog's run() to do that
+  //because we don't want to offer feedback.
+  //Ideally, EvView would just load from data anyway.
+  
+  const GdaBinary* gda_binary = gda_value_get_binary(m_original_data.gobj());
+  if(!gda_binary)
+  {
+    std::cerr << G_STRFUNC << ": GdaBinary is null" << std::endl;
+    return false;
+  }
+    
+  if(!gda_binary->data)
+  {
+    std::cerr << G_STRFUNC << ": GdaBinary::data is null" << std::endl;
+    return false;
+  }
+
+  try
+  {
+    const std::string filepath = Glib::filename_from_uri(uri);
+    Glib::file_set_contents(filepath, (const char*)gda_binary->data, gda_binary->binary_length);
+  }
+  catch(const Glib::Error& ex)
+  {
+    std::cerr << G_STRFUNC << "Exception: " << ex.what() << std::endl;
+    return false;
+  }
+  
+  return true;
+}
+
 bool ImageGlom::save_file(const Glib::ustring& uri)
 {
   DialogImageSaveProgress* dialog_save = 0;
@@ -504,8 +701,7 @@ void ImageGlom::on_menupopup_activate_select_file()
           m_original_data.Glib::ValueBase::init(GDA_TYPE_BINARY);
           gda_value_take_binary(m_original_data.gobj(), bin);
 
-          m_pixbuf_original = dialog->get_pixbuf();
-          scale();
+          show_image_data();
           signal_edited().emit();
         }
       }
@@ -569,7 +765,7 @@ void ImageGlom::on_clipboard_received_image(const Glib::RefPtr<Gdk::Pixbuf>& pix
     m_original_data = Gnome::Gda::Value();
 
     m_pixbuf_original = pixbuf;
-    scale();
+    show_image_data();
 
     signal_edited().emit();
   }
@@ -594,7 +790,8 @@ void ImageGlom::on_menupopup_activate_clear()
     return;
 
   m_pixbuf_original.reset();
-  m_image.set(Gtk::Stock::MISSING_IMAGE, Gtk::ICON_SIZE_DIALOG);
+  show_image_data();
+  //TODO: m_image.set(Gtk::Stock::MISSING_IMAGE, Gtk::ICON_SIZE_DIALOG);
   signal_edited().emit();
 }
 
diff --git a/glom/utility_widgets/imageglom.h b/glom/utility_widgets/imageglom.h
index 188044a..5e2bf7e 100644
--- a/glom/utility_widgets/imageglom.h
+++ b/glom/utility_widgets/imageglom.h
@@ -25,6 +25,7 @@
 #include <libglom/data_structure/field.h>
 #include "layoutwidgetfield.h"
 #include <gtkmm/builder.h>
+#include <evince-view.h>
 
 namespace Glom
 {
@@ -49,12 +50,14 @@ public:
   virtual bool get_has_original_data() const;
 
   //Optionally use this instead of set_value(), to avoid creating an unnecessary Value.
-  void set_pixbuf(const Glib::RefPtr<Gdk::Pixbuf>& pixbuf);
+  //void set_pixbuf(const Glib::RefPtr<Gdk::Pixbuf>& pixbuf);
 
   void do_choose_image();
 
   void set_read_only(bool read_only = true);
 
+  void on_ev_job_finished(EvJob* job);
+  
 private:
   void init();
 
@@ -77,11 +80,22 @@ private:
   virtual Application* get_application();
 
   void setup_menu_usermode();
-  void scale();
+  void show_image_data();
+  void scale_image();
+  
+  Glib::ustring save_to_temp_file(bool show_progress = true);
   bool save_file(const Glib::ustring& uri);
+  bool save_file_sync(const Glib::ustring& uri);
   void open_with(const Glib::RefPtr<Gio::AppInfo>& app_info =  Glib::RefPtr<Gio::AppInfo>());
+
+  Glib::ustring get_mime_type() const;
+  static void fill_evince_supported_mime_types();
  
   Gtk::Image m_image;
+
+  EvView* m_ev_view;
+  EvDocumentModel* m_ev_document_model;
+  
   Gtk::Frame m_frame;
   mutable Gnome::Gda::Value m_original_data; // Original file data (mutable so that we can create it in get_value() if it does not exist yet)
   Glib::RefPtr<Gdk::Pixbuf> m_pixbuf_original; //Only stored temporarily, because it could be big.
@@ -94,6 +108,9 @@ private:
     m_refActionSaveFile, m_refActionSelectFile, m_refActionCopy, m_refActionPaste, m_refActionClear;
 
   bool m_read_only;
+  
+  typedef std::vector<Glib::ustring> type_vec_ustrings;
+  static type_vec_ustrings m_evince_supported_mime_types;
 };
 
 } //namespace Glom



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