[glom] ImageGlom: Saving is now mostly async.



commit dd8e028758d1fa01599c64f353b965090e421388
Author: Murray Cumming <murrayc murrayc com>
Date:   Tue Jul 12 15:05:42 2011 +0200

    ImageGlom: Saving is now mostly async.
    
    * glom/utility_widgets/dialog_image_save_progress.[h|cc]: Doing the actual
    writing in callbacks, like in the loader.
    * glom/utility_widgets/imageglom.cc: Show the dialog, so we can use the
    idle callbacks, and give user feedback.

 ChangeLog                                          |    9 ++++
 glom/utility_widgets/dialog_image_load_progress.cc |    5 ++
 glom/utility_widgets/dialog_image_save_progress.cc |   48 +++++++++++++++++---
 glom/utility_widgets/dialog_image_save_progress.h  |    2 +
 glom/utility_widgets/imageglom.cc                  |    3 +-
 5 files changed, 58 insertions(+), 9 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 6f2939f..f7bf002 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2011-07-12  Murray Cumming  <murrayc murrayc com>
 
+	ImageGlom: Saving is now mostly async.
+
+	* glom/utility_widgets/dialog_image_save_progress.[h|cc]: Doing the actual 
+	writing in callbacks, like in the loader.
+	* glom/utility_widgets/imageglom.cc: Show the dialog, so we can use the 
+	idle callbacks, and give user feedback.
+
+2011-07-12  Murray Cumming  <murrayc murrayc com>
+
 	ImageGlom: Allow the user to choose any file.
 
 	* glom/utility_widgets/imageglom.cc: However, we are still restricted to 
diff --git a/glom/utility_widgets/dialog_image_load_progress.cc b/glom/utility_widgets/dialog_image_load_progress.cc
index 71148a9..83558b2 100644
--- a/glom/utility_widgets/dialog_image_load_progress.cc
+++ b/glom/utility_widgets/dialog_image_load_progress.cc
@@ -132,12 +132,16 @@ void DialogImageLoadProgress::on_stream_read(const Glib::RefPtr<Gio::AsyncResult
   {
     gssize size = m_stream->read_finish(result);
     g_assert(size >= 0); // Would have thrown an exception otherwise
+    
     // 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);
+    
     // Read next chunk, if any
     if(  static_cast<gssize>(offset + size) < static_cast<gssize>(m_data->binary_length))
       // Even if choose a priority lower than GDK_PRIORITY_REDRAW + 10 for the
@@ -151,6 +155,7 @@ void DialogImageLoadProgress::on_stream_read(const Glib::RefPtr<Gio::AsyncResult
   catch(const Glib::Error& ex)
   {
     error(ex.what());
+    response(Gtk::RESPONSE_REJECT);
   }
 }
 
diff --git a/glom/utility_widgets/dialog_image_save_progress.cc b/glom/utility_widgets/dialog_image_save_progress.cc
index 4e7753b..245f0d7 100644
--- a/glom/utility_widgets/dialog_image_save_progress.cc
+++ b/glom/utility_widgets/dialog_image_save_progress.cc
@@ -24,6 +24,14 @@
 #include <iostream>
 #include <glibmm/i18n.h>
 
+namespace
+{
+
+// Write the file in chunks of this size:
+const unsigned int CHUNK_SIZE = 2048;
+
+} // anonymous namespace
+
 namespace Glom
 {
 
@@ -80,10 +88,11 @@ void DialogImageSaveProgress::save(const Glib::ustring& uri)
   }
   
   //Write the data to the output uri
-  gssize bytes_written = 0;
   try
   {
-    bytes_written = m_stream->write(m_data->data, m_data->binary_length);
+    m_stream->write_async(m_data->data,
+      std::min<gsize>(CHUNK_SIZE, m_data->binary_length),
+      sigc::bind(sigc::mem_fun(*this, &DialogImageSaveProgress::on_stream_write), 0));
   }
   catch(const Gio::Error& ex)
   {
@@ -91,14 +100,33 @@ void DialogImageSaveProgress::save(const Glib::ustring& uri)
     response(Gtk::RESPONSE_REJECT);
     return;
   }
+}
 
-  if(bytes_written != m_data->binary_length)
+void DialogImageSaveProgress::on_stream_write(const Glib::RefPtr<Gio::AsyncResult>& result, unsigned int offset)
+{
+  try
   {
-    std::cerr << G_STRFUNC << ": unexpected number of bytes written: bytes_written=" << bytes_written <<
-       ", binary_length=" << m_data->binary_length << std::endl;
+    const gssize size = m_stream->write_finish(result);
+    g_assert(size >= 0); // Would have thrown an exception otherwise
+    
+    // Set progress
+    m_progress_bar->set_fraction(static_cast<double>(offset + size) / m_data->binary_length);
+    
+    // Write next chunk, if any
+    if(  static_cast<gssize>(offset + size) < static_cast<gssize>(m_data->binary_length))
+      // Even if choose a priority lower than GDK_PRIORITY_REDRAW + 10 for the
+      // write_async we don't see the progressbar progressing while the image
+      // is loading. Therefore we put an idle inbetween.
+      Glib::signal_idle().connect(sigc::bind_return(sigc::bind(sigc::mem_fun(*this, &DialogImageSaveProgress::on_write_next), offset + size), false));
+    else
+      // We are done saving the image, close the progress dialog
+      response(Gtk::RESPONSE_ACCEPT);
+  }
+  catch(const Glib::Error& ex)
+  {
+    error(ex.what());
+    response(Gtk::RESPONSE_REJECT);
   }
-  
-  response(Gtk::RESPONSE_ACCEPT);
 }
 
 void DialogImageSaveProgress::error(const Glib::ustring& error_message)
@@ -111,6 +139,12 @@ void DialogImageSaveProgress::error(const Glib::ustring& error_message)
   response(Gtk::RESPONSE_REJECT);
 }
 
+void DialogImageSaveProgress::on_write_next(unsigned int at)
+{
+  g_assert(at < static_cast<gsize>(m_data->binary_length));
+
+  m_stream->write_async(m_data->data + at, std::min<gsize>(CHUNK_SIZE, m_data->binary_length - at), sigc::bind(sigc::mem_fun(*this, &DialogImageSaveProgress::on_stream_write), at));
+}
 
 void DialogImageSaveProgress::set_image_data(const GdaBinary& data)
 {
diff --git a/glom/utility_widgets/dialog_image_save_progress.h b/glom/utility_widgets/dialog_image_save_progress.h
index 7506606..42acee7 100644
--- a/glom/utility_widgets/dialog_image_save_progress.h
+++ b/glom/utility_widgets/dialog_image_save_progress.h
@@ -45,7 +45,9 @@ public:
   void set_image_data(const GdaBinary& data);
 
 private:
+  void on_stream_write(const Glib::RefPtr<Gio::AsyncResult>& result, unsigned int offset);
   void error(const Glib::ustring& error_message);
+  void on_write_next(unsigned int at);
 
   Gtk::ProgressBar* m_progress_bar;
   const GdaBinary* m_data;
diff --git a/glom/utility_widgets/imageglom.cc b/glom/utility_widgets/imageglom.cc
index ecada37..fc9743b 100644
--- a/glom/utility_widgets/imageglom.cc
+++ b/glom/utility_widgets/imageglom.cc
@@ -453,8 +453,7 @@ bool ImageGlom::save_file(const Glib::ustring& uri)
   dialog_save->set_image_data(*gda_binary);
   dialog_save->save(uri);
 
-  //TODO: Use this when we do async saving:
-  //dialog_save->run();
+  dialog_save->run();
   return true;
 }
 



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