[solang] Overhauled the ProgressObserver and its friends
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [solang] Overhauled the ProgressObserver and its friends
- Date: Fri, 5 Mar 2010 14:09:46 +0000 (UTC)
commit f4257a077c2fd0ad2d790e443e252c1cd2df7f99
Author: Debarshi Ray <rishi gnu org>
Date: Thu Mar 4 13:39:58 2010 +0200
Overhauled the ProgressObserver and its friends
The previous ProgressObserver infrastructure was unable to deal with
two or more simultaneous operations. Moreoever it solely relied on
Glib::Dispatcher which required the observed operation to be done in a
separate thread.
A ProgressDialog has been to the Application, and whenever a
ProgressObserver is created it is associated with this dialog. The
observer is a Gio::Cancellable, and a template that expects either a
Glib::Dispatcher or a sigc::slot as the parameter. When the operation
begins, the observer attaches a ProgressWidget to the ProgressDialog
and detaches it when cancelled or destructed. The ProgressDialog and
ProgressWidget were translated to C++ from C code written for
Nautilus.
A IProgressObserver was added as an interface to the actual templates
for use by user code:
+ IProgressObsever::is_finished
+ IProgressObsever::progress
+ IProgressObsever::set_description
+ IProgressObsever::set_fraction
+ IProgressObsever::set_total
Construction and destruction of a IProgressObserver, and
IProgressObserver::set_description are only meant to work from the
main thread they involve interactions with the GUI.
IPhotoDestination::export_photos has been renamed to
IPhotoDestination::export_photos_async and it is run in the main
thread. It is unknown whether the Brasero libraries are thread-safe or
not, and there was really no pressing need for using a separate
thread.
The IPhotoDestination::export_photo has been removed as there was no
real need for it and it was becoming too different for the Brasero and
directory destinations.
EditablePhoto::pending_ now contains triplets instead of pairs -- a
ProgressObserverPtr being the new addition. If an ongoing operation is
cancelled (or the initial Gegl::Buffer could not be created) the
entire queue is cleared and a new GdkPixbuf is not created.
A Finally was added to mimic Java's finally clause. This is useful for
invoking of g_object_unref when moving out of the local scope, or
emitting Glib::Dispatchers to indicate the end of a thread worker.
Regressions:
Removal of the temporary directory used for creating an archive when
exporting to a directory is now done synchronously in the main thread.
po/POTFILES.in | 1 +
po/POTFILES.skip | 1 +
src/application/application.cpp | 37 +----
src/application/application.h | 11 +-
src/application/deletion-queue.cpp | 8 +-
src/application/engine.cpp | 265 ++++++++++++++------------------
src/application/engine.h | 99 +++++--------
src/application/main-window.cpp | 43 -----
src/application/main-window.h | 15 --
src/common/Makefile.am | 7 +-
src/common/database.cpp | 44 +-----
src/common/database.h | 13 +-
src/common/finally.cpp | 42 +++++
src/common/finally.h | 44 ++++++
src/common/i-operation.h | 3 +-
src/common/i-photo-destination.h | 8 +-
src/common/i-progress-observer.cpp | 37 +++++
src/common/i-progress-observer.h | 59 +++++++
src/common/non-copyable.cpp | 2 +-
src/common/non-copyable.h | 2 +-
src/common/operation.cpp | 32 ++--
src/common/operation.h | 3 +-
src/common/progress-dialog.cpp | 122 ++++-----------
src/common/progress-dialog.h | 43 ++----
src/common/progress-observer.cpp | 126 ---------------
src/common/progress-observer.h | 229 +++++++++++++++++++--------
src/common/progress-widget.cpp | 99 ++++++++++++
src/common/progress-widget.h | 74 +++++++++
src/common/types.h | 15 ++-
src/editor/editable-photo.cpp | 60 ++++++--
src/editor/editable-photo.h | 24 ++--
src/editor/editor.cpp | 14 +-
src/exporter/brasero-destination.cpp | 61 ++------
src/exporter/brasero-destination.h | 19 +--
src/exporter/directory-destination.cpp | 145 +++++++++++++-----
src/exporter/directory-destination.h | 26 +++-
src/exporter/exporter.cpp | 14 +-
37 files changed, 1015 insertions(+), 832 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index a859c3b..0711334 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -12,6 +12,7 @@ src/attribute/tag-new-dialog.cpp
src/common/exif-data.cpp
src/common/histogram-viewer.cpp
src/common/progress-dialog.cpp
+src/common/progress-observer.h
src/editor/editor.cpp
src/editor/flip-horiz-operation.cpp
src/editor/flip-operation.cpp
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index f57a79c..b868a38 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -1,6 +1,7 @@
data/edit-toolbar.ui
data/save-modified-photos.ui
data/solang.desktop.in
+src/common/progress-widget.cpp
src/common/spinner-dialog.cpp
src/importer/camera-import-widget.cpp
src/importer/camera-source.cpp
diff --git a/src/application/application.cpp b/src/application/application.cpp
index 734cb5f..f2ee23b 100644
--- a/src/application/application.cpp
+++ b/src/application/application.cpp
@@ -44,7 +44,6 @@
#include "i-plugin.h"
//#include "importer.h"
#include "photo.h"
-#include "progress-observer.h"
#include "property-manager.h"
#include "search-manager.h"
#include "slideshow-renderer.h"
@@ -178,10 +177,9 @@ Application::Application(int & argc, char ** & argv) throw() :
sigc::trackable(),
threadPool_(4, false),
iconFactory_(Gtk::IconFactory::create()),
- observer_( new ProgressObserver() ),
- engine_(argc, argv, observer_),
+ engine_(argc, argv),
mainWindow_(),
- progressDialog_(engine_.get_default_observer()),
+ progressDialog_(mainWindow_),
listStore_(Gtk::ListStore::create(BrowserModelColumnRecord())),
listStoreIter_(),
plugins_(),
@@ -246,14 +244,6 @@ Application::Application(int & argc, char ** & argv) throw() :
engine_.signal_criteria_changed().connect(
sigc::mem_fun(*this,
&Application::on_criteria_changed));
- engine_.photo_export_begin().connect(sigc::mem_fun(*this,
- &Application::show_progress_dialog));
- engine_.photo_export_end().connect(sigc::mem_fun(*this,
- &Application::hide_progress_dialog));
- engine_.photo_import_begin().connect(sigc::mem_fun(*this,
- &Application::show_progress_dialog));
- engine_.photo_import_end().connect(sigc::mem_fun(*this,
- &Application::hide_progress_dialog));
Thumbnailer & thumbnailer = Thumbnailer::instance();
thumbnailer.signal_ready().connect(
@@ -343,8 +333,6 @@ Application::init() throw()
mainWindow_.init(*this);
- mainWindow_.connect_progress( engine_.get_default_observer() );
-
initEnd_.emit(*this);
}
@@ -462,13 +450,6 @@ Application::init_end() throw()
return initEnd_;
}
-void
-Application::hide_progress_dialog() throw()
-{
- progressDialog_.hide();
- engine_.get_default_observer()->reset();
-}
-
sigc::signal<void, Application &> &
Application::list_store_change_begin() throw()
{
@@ -539,14 +520,6 @@ Application::on_thumbnailer_ready(PhotoList & photos) const throw()
}
}
-void
-Application::show_progress_dialog() throw()
-{
- progressDialog_.set_transient_for(mainWindow_);
- progressDialog_.show_all();
-}
-
-
Glib::ThreadPool &
Application::get_thread_pool() throw()
{
@@ -565,6 +538,12 @@ Application::get_main_window() throw()
return mainWindow_;
}
+ProgressDialog &
+Application::get_progress_dialog() throw()
+{
+ return progressDialog_;
+}
+
const ListStorePtr &
Application::get_list_store() throw()
{
diff --git a/src/application/application.h b/src/application/application.h
index 38d1a06..dcd60be 100644
--- a/src/application/application.h
+++ b/src/application/application.h
@@ -71,6 +71,9 @@ class Application :
MainWindow &
get_main_window() throw();
+ ProgressDialog &
+ get_progress_dialog() throw();
+
const ListStorePtr &
get_list_store() throw();
@@ -107,9 +110,6 @@ class Application :
add_photos_to_model(const PhotoList & photos) throw();
void
- hide_progress_dialog() throw();
-
- void
on_async_search(PhotoList & photos) throw();
void
@@ -119,15 +119,10 @@ class Application :
void
on_thumbnailer_ready(PhotoList & photos) const throw();
- void
- show_progress_dialog() throw();
-
Glib::ThreadPool threadPool_;
IconFactoryPtr iconFactory_;
- ProgressObserverPtr observer_;
-
Engine engine_;
MainWindow mainWindow_;
diff --git a/src/application/deletion-queue.cpp b/src/application/deletion-queue.cpp
index 7257bb5..48bea84 100644
--- a/src/application/deletion-queue.cpp
+++ b/src/application/deletion-queue.cpp
@@ -21,7 +21,7 @@
#endif
#include "deletion-queue.h"
-#include "progress-observer.h"
+#include "i-progress-observer.h"
namespace Solang
{
@@ -91,8 +91,8 @@ DeletionQueue::execute_actions(
throw;
}
}
- observer->set_event_description( "Executing delete actions" );
- observer->set_num_events( actions_.size() );
+ observer->set_description( "Executing delete actions" );
+ observer->set_total( actions_.size() );
for( DeleteActionList::iterator action = actions_.begin();
action != actions_.end(); action++ )
{
@@ -106,7 +106,7 @@ DeletionQueue::execute_actions(
observer->reset();
throw;
}
- observer->receive_event_notifiation();
+ observer->progress();
}
}
diff --git a/src/application/engine.cpp b/src/application/engine.cpp
index b68e7b7..441b8de 100644
--- a/src/application/engine.cpp
+++ b/src/application/engine.cpp
@@ -28,15 +28,12 @@
#include "i-photo-destination.h"
#include "i-photo-source.h"
#include "photo-tag.h"
-#include "progress-observer.h"
#include "tag.h"
namespace Solang
{
-Engine::Engine(int & argc, char ** & argv,
- const ProgressObserverPtr & observer) throw() :
- observer_(observer),
+Engine::Engine(int & argc, char ** & argv) throw() :
photoExportBegin_(),
photoExportEnd_(),
photoImportBegin_(),
@@ -67,7 +64,7 @@ Engine::init(Glib::ustring str)
void
Engine::final()
{
- deleteActions_.execute_actions( observer_ );
+ deleteActions_.execute_actions();
}
void
@@ -79,116 +76,116 @@ Engine::criteria_changed() throw()
criteriaChanged_.emit(criteria);
}
-void
-Engine::import(const PhotoPtr & photo,
- const IPhotoSourcePtr & source,
- const IStoragePtr & selected_storage,
- const TagList & tags) throw()
-{
- import(photo, source, selected_storage, tags, observer_);
- return;
-}
-
-void
-Engine::import(const PhotoPtr & photo,
- const IPhotoSourcePtr & source,
- const IStoragePtr & selected_storage,
- const TagList & tags,
- const ProgressObserverPtr & observer) throw()
-{
- photoImportBegin_.emit();
-#if 0
- for (TagList::const_iterator it = tags.begin();
- it != tags.end(); it++)
- {
- (*it)->save(database_);
- }
-#endif
- PhotoPtr imp_photo = source->import(photo, selected_storage,
- tags, database_, observer);
- photoImportEnd_.emit();
-
- PhotoList imp_photos;
- imp_photos.push_back(imp_photo);
- {
- Glib::Mutex::Lock lock(mutex_);
- photos_ = imp_photos;
- }
-
- return;
-}
-
-void
-Engine::import(const PhotoList & photos,
- const IPhotoSourcePtr & source,
- const IStoragePtr & selected_storage,
- const TagList & tags) throw()
-{
- import(photos, source, selected_storage, tags, observer_);
- return;
-}
-
-void
-Engine::import(const PhotoList & photos,
- const IPhotoSourcePtr & source,
- const IStoragePtr & selected_storage,
- const TagList & tags,
- const ProgressObserverPtr & observer) throw()
-{
- photoImportBegin_.emit();
-#if 0
- for (TagList::const_iterator it = tags.begin();
- it != tags.end(); it++)
- {
- (*it)->save(database_);
- }
-#endif
- PhotoList imp_photos = source->import(photos, selected_storage,
- tags, database_, observer);
- photoImportEnd_.emit();
-
- {
- Glib::Mutex::Lock lock(mutex_);
- photos_ = imp_photos;
- }
-
- return;
-}
-
-void
-Engine::import(const IPhotoSourcePtr & source,
- const IStoragePtr & selected_storage,
- const TagList & tags) throw()
-{
- import(source, selected_storage, tags, observer_);
- return;
-}
-
-void
-Engine::import(const IPhotoSourcePtr & source,
- const IStoragePtr & selected_storage,
- const TagList & tags,
- const ProgressObserverPtr & observer) throw()
-{
- photoImportBegin_.emit();
-#if 0
- for (TagList::const_iterator it = tags.begin();
- it != tags.end(); it++)
- {
- (*it)->save(database_);
- }
-#endif
- PhotoList imp_photos = source->import(selected_storage, tags,
- database_, observer);
- photoImportEnd_.emit();
-
- {
- Glib::Mutex::Lock lock(mutex_);
- photos_ = imp_photos;
- }
-
- return;
-}
+/* void */
+/* Engine::import(const PhotoPtr & photo, */
+/* const IPhotoSourcePtr & source, */
+/* const IStoragePtr & selected_storage, */
+/* const TagList & tags) throw() */
+/* { */
+/* import(photo, source, selected_storage, tags, observer_); */
+/* return; */
+/* } */
+
+/* void */
+/* Engine::import(const PhotoPtr & photo, */
+/* const IPhotoSourcePtr & source, */
+/* const IStoragePtr & selected_storage, */
+/* const TagList & tags, */
+/* const ProgressObserverPtr & observer) throw() */
+/* { */
+/* photoImportBegin_.emit(); */
+/* #if 0 */
+/* for (TagList::const_iterator it = tags.begin(); */
+/* it != tags.end(); it++) */
+/* { */
+/* (*it)->save(database_); */
+/* } */
+/* #endif */
+/* PhotoPtr imp_photo = source->import(photo, selected_storage, */
+/* tags, database_, observer); */
+/* photoImportEnd_.emit(); */
+
+/* PhotoList imp_photos; */
+/* imp_photos.push_back(imp_photo); */
+/* { */
+/* Glib::Mutex::Lock lock(mutex_); */
+/* photos_ = imp_photos; */
+/* } */
+
+/* return; */
+/* } */
+
+/* void */
+/* Engine::import(const PhotoList & photos, */
+/* const IPhotoSourcePtr & source, */
+/* const IStoragePtr & selected_storage, */
+/* const TagList & tags) throw() */
+/* { */
+/* import(photos, source, selected_storage, tags, observer_); */
+/* return; */
+/* } */
+
+/* void */
+/* Engine::import(const PhotoList & photos, */
+/* const IPhotoSourcePtr & source, */
+/* const IStoragePtr & selected_storage, */
+/* const TagList & tags, */
+/* const ProgressObserverPtr & observer) throw() */
+/* { */
+/* photoImportBegin_.emit(); */
+/* #if 0 */
+/* for (TagList::const_iterator it = tags.begin(); */
+/* it != tags.end(); it++) */
+/* { */
+/* (*it)->save(database_); */
+/* } */
+/* #endif */
+/* PhotoList imp_photos = source->import(photos, selected_storage, */
+/* tags, database_, observer); */
+/* photoImportEnd_.emit(); */
+
+/* { */
+/* Glib::Mutex::Lock lock(mutex_); */
+/* photos_ = imp_photos; */
+/* } */
+
+/* return; */
+/* } */
+
+/* void */
+/* Engine::import(const IPhotoSourcePtr & source, */
+/* const IStoragePtr & selected_storage, */
+/* const TagList & tags) throw() */
+/* { */
+/* import(source, selected_storage, tags, observer_); */
+/* return; */
+/* } */
+
+/* void */
+/* Engine::import(const IPhotoSourcePtr & source, */
+/* const IStoragePtr & selected_storage, */
+/* const TagList & tags, */
+/* const ProgressObserverPtr & observer) throw() */
+/* { */
+/* photoImportBegin_.emit(); */
+/* #if 0 */
+/* for (TagList::const_iterator it = tags.begin(); */
+/* it != tags.end(); it++) */
+/* { */
+/* (*it)->save(database_); */
+/* } */
+/* #endif */
+/* PhotoList imp_photos = source->import(selected_storage, tags, */
+/* database_, observer); */
+/* photoImportEnd_.emit(); */
+
+/* { */
+/* Glib::Mutex::Lock lock(mutex_); */
+/* photos_ = imp_photos; */
+/* } */
+
+/* return; */
+/* } */
void
Engine::search_async(const IPhotoSearchCriteriaList & criteria,
@@ -199,37 +196,8 @@ Engine::search_async(const IPhotoSearchCriteriaList & criteria,
}
void
-Engine::export_photos(const IPhotoDestinationPtr & destination)
- throw()
+Engine::erase(const PhotoList & photos)
{
- export_photos(destination, observer_);
- return;
-}
-
-void
-Engine::export_photos(const IPhotoDestinationPtr & destination,
- const ProgressObserverPtr & observer) throw()
-{
- photoExportBegin_.emit();
- destination->export_photos(exportQueue_, observer);
- photoExportEnd_.emit();
-
- return;
-}
-
-
-void
-Engine::erase(const PhotoList & photos,
- const ProgressObserverPtr & observer)
-{
- ProgressObserverPtr obs = (observer) ? observer : observer_;
-
- if (obs)
- {
- obs->set_num_events(photos.size());
- obs->set_event_description("Removing Selected Photos");
- }
-
return;
}
@@ -243,20 +211,19 @@ Engine::get_tags_async(const Database::SlotAsyncTags & slot) const
DatePhotoInfoList
Engine::get_dates_with_picture_count()
{
- return database_.get_dates_with_picture_count( observer_ );
+ return database_.get_dates_with_picture_count( );
}
DatePhotoInfoList
Engine::get_dates_with_picture_count( gint year )
{
- return database_.get_dates_with_picture_count(year, observer_ );
+ return database_.get_dates_with_picture_count(year);
}
DatePhotoInfoList
Engine::get_dates_with_picture_count( gint year, gint month )
{
- return database_.get_dates_with_picture_count(year, month,
- observer_ );
+ return database_.get_dates_with_picture_count(year, month);
}
Glib::Dispatcher &
diff --git a/src/application/engine.h b/src/application/engine.h
index de35778..69b4f15 100644
--- a/src/application/engine.h
+++ b/src/application/engine.h
@@ -43,9 +43,7 @@ class Engine :
typedef std::map<Glib::ustring, IStoragePtr> StorageMap;
public:
- Engine(int & argc, char ** & argv,
- const ProgressObserverPtr & observer
- = ProgressObserverPtr()) throw();
+ Engine(int & argc, char ** & argv) throw();
~Engine() throw();
@@ -58,42 +56,42 @@ class Engine :
void
criteria_changed() throw();
- void
- import(const PhotoPtr & photo,
- const IPhotoSourcePtr & source,
- const IStoragePtr & selected_storage,
- const TagList & tags) throw();
-
- void
- import(const PhotoPtr & photo,
- const IPhotoSourcePtr & source,
- const IStoragePtr & selected_storage,
- const TagList & tags,
- const ProgressObserverPtr & observer) throw();
-
- void
- import(const PhotoList & photos,
- const IPhotoSourcePtr & source,
- const IStoragePtr & selected_storage,
- const TagList & tags) throw();
-
- void
- import(const PhotoList & photos,
- const IPhotoSourcePtr & source,
- const IStoragePtr & selected_storage,
- const TagList & tags,
- const ProgressObserverPtr & observer) throw();
-
- void
- import(const IPhotoSourcePtr & source,
- const IStoragePtr & selected_storage,
- const TagList & tags) throw();
-
- void
- import(const IPhotoSourcePtr & source,
- const IStoragePtr & selected_storage,
- const TagList & tags,
- const ProgressObserverPtr & observer) throw();
+ /* void */
+ /* import(const PhotoPtr & photo, */
+ /* const IPhotoSourcePtr & source, */
+ /* const IStoragePtr & selected_storage, */
+ /* const TagList & tags) throw(); */
+
+ /* void */
+ /* import(const PhotoPtr & photo, */
+ /* const IPhotoSourcePtr & source, */
+ /* const IStoragePtr & selected_storage, */
+ /* const TagList & tags, */
+ /* const ProgressObserverPtr & observer) throw(); */
+
+ /* void */
+ /* import(const PhotoList & photos, */
+ /* const IPhotoSourcePtr & source, */
+ /* const IStoragePtr & selected_storage, */
+ /* const TagList & tags) throw(); */
+
+ /* void */
+ /* import(const PhotoList & photos, */
+ /* const IPhotoSourcePtr & source, */
+ /* const IStoragePtr & selected_storage, */
+ /* const TagList & tags, */
+ /* const ProgressObserverPtr & observer) throw(); */
+
+ /* void */
+ /* import(const IPhotoSourcePtr & source, */
+ /* const IStoragePtr & selected_storage, */
+ /* const TagList & tags) throw(); */
+
+ /* void */
+ /* import(const IPhotoSourcePtr & source, */
+ /* const IStoragePtr & selected_storage, */
+ /* const TagList & tags, */
+ /* const ProgressObserverPtr & observer) throw(); */
void
search_async(const IPhotoSearchCriteriaList & criteria,
@@ -101,17 +99,7 @@ class Engine :
throw();
void
- export_photos(const IPhotoDestinationPtr & destination)
- throw();
-
- void
- export_photos(const IPhotoDestinationPtr & destination,
- const ProgressObserverPtr & observer) throw();
-
- void
- erase(const PhotoList & photos,
- const ProgressObserverPtr & observer
- = ProgressObserverPtr());
+ erase(const PhotoList & photos);
void
get_tags_async(const Database::SlotAsyncTags & slot) const
@@ -165,9 +153,6 @@ class Engine :
PhotoList
get_photos() throw();
- inline const ProgressObserverPtr &
- get_default_observer();
-
inline SearchCriterionRepo &
get_criterion_repo();
@@ -175,8 +160,6 @@ class Engine :
get_delete_actions();
private:
- ProgressObserverPtr observer_;
-
Glib::Dispatcher photoExportBegin_;
Glib::Dispatcher photoExportEnd_;
@@ -212,12 +195,6 @@ class Engine :
DeletionQueue deleteActions_;
};
-inline const ProgressObserverPtr &
-Engine::get_default_observer()
-{
- return observer_;
-}
-
inline SearchCriterionRepo &
Engine::get_criterion_repo()
{
diff --git a/src/application/main-window.cpp b/src/application/main-window.cpp
index b177b96..9402270 100644
--- a/src/application/main-window.cpp
+++ b/src/application/main-window.cpp
@@ -29,7 +29,6 @@
#include "export-queue-operations.h"
#include "main-window.h"
-#include "progress-observer.h"
namespace Solang
{
@@ -208,8 +207,6 @@ MainWindow::MainWindow() throw() :
spinnerToolItem_(),
hBox_(false, 6),
statusBar_(),
- progress_(),
- observer_(),
dock_(gdl_dock_new()),
dockBar_(gdl_dock_bar_new(GDL_DOCK(dock_))),
layout_(gdl_dock_layout_new(GDL_DOCK(dock_))),
@@ -325,7 +322,6 @@ MainWindow::MainWindow() throw() :
statusBar_.set_has_resize_grip(true);
vBox_.pack_start(statusBar_, Gtk::PACK_SHRINK, 0);
- statusBar_.pack_start(progress_, Gtk::PACK_SHRINK, 0);
show_all_children();
}
@@ -836,43 +832,4 @@ MainWindow::set_busy(bool busy) throw()
spinnerToolItem_.set_spinning(busy);
}
-void
-MainWindow::connect_progress( const ProgressObserverPtr &observer ) throw()
-{
- observer_ = observer;
- progress_.set_fraction( 0.0L );
-
- observer_->progress().connect(
- sigc::mem_fun(*this,
- &MainWindow::on_progress));
-
- observer_->dispatcher_reset().connect(
- sigc::mem_fun(*this,
- &MainWindow::on_reset));
-}
-
-void
-MainWindow::on_progress() throw()
-{
- const guint64 num_events = observer_->get_num_events();
- if (0 == num_events)
- {
- return;
- }
-
- const double percentage =
- static_cast<double>(observer_->get_current_events())
- / static_cast<double>(num_events);
-
- progress_.set_fraction( percentage );
- progress_.show();
-}
-
-void
-MainWindow::on_reset() throw()
-{
- progress_.hide();
- progress_.set_fraction(0.0);
-}
-
} // namespace Solang
diff --git a/src/application/main-window.h b/src/application/main-window.h
index 7275c65..5574010 100644
--- a/src/application/main-window.h
+++ b/src/application/main-window.h
@@ -81,11 +81,6 @@ class MainWindow :
void
set_busy(bool busy) throw();
- void
- connect_progress(
- const ProgressObserverPtr &observer ) throw();
-
-
protected:
std::string
get_user_layout_file() throw();
@@ -120,12 +115,6 @@ class MainWindow :
virtual bool
on_delete_event(GdkEventAny * event);
- void
- on_progress() throw();
-
- void
- on_reset() throw();
-
ApplicationPtr application_;
ActionGroupPtr actionGroup_;
@@ -142,10 +131,6 @@ class MainWindow :
Gtk::Statusbar statusBar_;
- Gtk::ProgressBar progress_;
-
- ProgressObserverPtr observer_;
-
GtkWidget * const dock_;
GtkWidget * const dockBar_;
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 64763be..69dc300 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -16,6 +16,8 @@ libcommon_la_SOURCES = \
delete-action.h \
db-object.cpp \
db-object.h \
+ finally.cpp \
+ finally.h \
tracker-client.cpp \
tracker-client.h \
content-type-repo.cpp \
@@ -47,6 +49,8 @@ libcommon_la_SOURCES = \
i-photo-source.h \
i-plugin.cpp \
i-plugin.h \
+ i-progress-observer.cpp \
+ i-progress-observer.h \
i-renderer.cpp \
i-renderer.h \
i-renderer-selector.cpp \
@@ -65,8 +69,9 @@ libcommon_la_SOURCES = \
pixbuf-maker.h \
progress-dialog.cpp \
progress-dialog.h \
- progress-observer.cpp \
progress-observer.h \
+ progress-widget.cpp \
+ progress-widget.h \
renderer-selector.h \
scale-action.cpp \
scale-action.h \
diff --git a/src/common/database.cpp b/src/common/database.cpp
index a9d5363..d306dd6 100644
--- a/src/common/database.cpp
+++ b/src/common/database.cpp
@@ -31,7 +31,6 @@
#include "exif-data.h"
#include "photo.h"
#include "photo-tag.h"
-#include "progress-observer.h"
#include "tag.h"
#include "date-photo-info.h"
@@ -179,34 +178,29 @@ Database::search_async(const IPhotoSearchCriteriaList & criteria,
//Group by year
DatePhotoInfoList
-Database::get_dates_with_picture_count(
- const ProgressObserverPtr & observer)
+Database::get_dates_with_picture_count()
{
Glib::ustring sql
= "select 0, 0, mod_year, count(*) from photos ";
sql += "group by mod_year";
- return get_dates_with_picture_count( sql, observer );
+ return get_dates_with_picture_count( sql );
}
//Group by year, month
DatePhotoInfoList
-Database::get_dates_with_picture_count(
- gint year,
- const ProgressObserverPtr & observer)
+Database::get_dates_with_picture_count(gint year)
{
std::ostringstream sout;
sout<<"select 0, mod_month, mod_year, count(*) from photos ";
sout<<"where mod_year="<<year<<" ";
sout<<"group by mod_year,mod_month ";
// sout<<"order by mod_year desc, mod_month desc";
- return get_dates_with_picture_count( sout.str(), observer );
+ return get_dates_with_picture_count( sout.str() );
}
//Group by year, month, day
DatePhotoInfoList
-Database::get_dates_with_picture_count(
- gint year, gint month,
- const ProgressObserverPtr & observer)
+Database::get_dates_with_picture_count(gint year, gint month)
{
std::ostringstream sout;
sout<<"select mod_day, mod_month, mod_year, count(*) from photos ";
@@ -214,13 +208,11 @@ Database::get_dates_with_picture_count(
sout<<"and mod_month="<<month<<" ";
sout<<"group by mod_year,mod_month,mod_day ";
// sout<<"order by mod_year desc, mod_month desc, mod_day desc";
- return get_dates_with_picture_count( sout.str(), observer );
+ return get_dates_with_picture_count( sout.str() );
}
DatePhotoInfoList
-Database::get_dates_with_picture_count(
- const Glib::ustring & sql,
- const ProgressObserverPtr & observer)
+Database::get_dates_with_picture_count(const Glib::ustring & sql)
{
DatePhotoInfoList infos;
@@ -233,20 +225,8 @@ Database::get_dates_with_picture_count(
const gint32 numRows
= static_cast<gint32>(model->get_n_rows());
- if (0 != observer)
- {
- observer->set_event_description(_("Summarizing photos"));
- observer->set_num_events(numRows);
- observer->set_current_events(0);
- }
-
for( gint32 row = 0; row < numRows; row++ )
{
- if (0 != observer && true == observer->get_stop())
- {
- break;
- }
-
infos.push_back(
DatePhotoInfo(
ModificationDate(
@@ -254,16 +234,6 @@ Database::get_dates_with_picture_count(
model->get_value_at( 1, row ).get_int(),
model->get_value_at( 2, row ).get_int()),
model->get_value_at( 3, row ).get_int()));
-
- if (0 != observer)
- {
- observer->receive_event_notifiation();
- }
- }
-
- if (0 != observer)
- {
- observer->reset();
}
}
catch (Glib::Error &e)
diff --git a/src/common/database.h b/src/common/database.h
index e10a226..498bf4c 100644
--- a/src/common/database.h
+++ b/src/common/database.h
@@ -91,27 +91,22 @@ class Database
//Group by year
DatePhotoInfoList
- get_dates_with_picture_count( const ProgressObserverPtr &);
+ get_dates_with_picture_count( );
//Group by year, month
DatePhotoInfoList
- get_dates_with_picture_count( gint year,
- const ProgressObserverPtr &);
+ get_dates_with_picture_count( gint year );
//Group by year, month, day
DatePhotoInfoList
- get_dates_with_picture_count(
- gint year, gint month,
- const ProgressObserverPtr &);
+ get_dates_with_picture_count(gint year, gint month);
void
get_tags_async(const SlotAsyncTags & slot) const throw();
private:
DatePhotoInfoList
- get_dates_with_picture_count(
- const Glib::ustring & sql,
- const ProgressObserverPtr &);
+ get_dates_with_picture_count(const Glib::ustring & sql);
void
on_async_exif_data(std::vector<UStringList> & result,
diff --git a/src/common/finally.cpp b/src/common/finally.cpp
new file mode 100644
index 0000000..7df166f
--- /dev/null
+++ b/src/common/finally.cpp
@@ -0,0 +1,42 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * Copyright (C) 2010 Debarshi Ray <rishi gnu org>
+ *
+ * Solang 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.
+ *
+ * Solang 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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "finally.h"
+
+namespace Solang
+{
+
+Finally::Finally(const sigc::slot<void> & s) throw() :
+ NonCopyable(),
+ s_(s)
+{
+}
+
+Finally::~Finally()
+{
+ if (true == s_)
+ {
+ s_();
+ }
+}
+
+} // namespace Solang
diff --git a/src/common/finally.h b/src/common/finally.h
new file mode 100644
index 0000000..100be6b
--- /dev/null
+++ b/src/common/finally.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * Copyright (C) 2010 Debarshi Ray <rishi gnu org>
+ *
+ * Solang 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.
+ *
+ * Solang 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 SOLANG_FINALLY_H
+#define SOLANG_FINALLY_H
+
+#include <sigc++/sigc++.h>
+
+#include "non-copyable.h"
+
+namespace Solang
+{
+
+class Finally :
+ public NonCopyable
+{
+ public:
+ Finally(const sigc::slot<void> & s) throw();
+
+ // Calling the slot might lead to an exception.
+ ~Finally();
+
+ private:
+ sigc::slot<void> s_;
+};
+
+} // namespace Solang
+
+#endif // SOLANG_FINALLY_H
diff --git a/src/common/i-operation.h b/src/common/i-operation.h
index b2f9605..672e543 100644
--- a/src/common/i-operation.h
+++ b/src/common/i-operation.h
@@ -47,7 +47,8 @@ class IOperation :
virtual BufferPtr
apply(const BufferPtr & buffer,
- const ProgressObserverPtr & observer) throw() = 0;
+ const ProgressObserverPtr & observer)
+ throw(Glib::Thread::Exit) = 0;
virtual Glib::ustring
get_description() const throw() = 0;
diff --git a/src/common/i-photo-destination.h b/src/common/i-photo-destination.h
index 409aadf..895a92c 100644
--- a/src/common/i-photo-destination.h
+++ b/src/common/i-photo-destination.h
@@ -46,11 +46,9 @@ class IPhotoDestination :
final(Application & application) throw() = 0;
virtual void
- export_photo(const PhotoPtr & photo,
- const ProgressObserverPtr & observer) throw() = 0;
- virtual void
- export_photos(const PhotoList & photos,
- const ProgressObserverPtr & observer) throw() = 0;
+ export_photos_async(const PhotoList & photos,
+ const ProgressObserverPtr & observer)
+ throw() = 0;
virtual void
final() throw() = 0;
diff --git a/src/common/i-progress-observer.cpp b/src/common/i-progress-observer.cpp
new file mode 100644
index 0000000..eab350c
--- /dev/null
+++ b/src/common/i-progress-observer.cpp
@@ -0,0 +1,37 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * Copyright (C) 2010 Debarshi Ray <rishi gnu org>
+ *
+ * Solang 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.
+ *
+ * Solang 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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "i-progress-observer.h"
+
+namespace Solang
+{
+
+IProgressObserver::IProgressObserver() throw() :
+ Gio::Cancellable()
+{
+}
+
+IProgressObserver::~IProgressObserver() throw()
+{
+}
+
+} // namespace Solang
diff --git a/src/common/i-progress-observer.h b/src/common/i-progress-observer.h
new file mode 100644
index 0000000..946abf3
--- /dev/null
+++ b/src/common/i-progress-observer.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * Copyright (C) 2010 Debarshi Ray <rishi gnu org>
+ *
+ * Solang 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.
+ *
+ * Solang 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 SOLANG_I_PROGRESS_OBSERVER_H
+#define SOLANG_I_PROGRESS_OBSERVER_H
+
+#include <giomm.h>
+#include <glibmm.h>
+
+namespace Solang
+{
+
+class IProgressObserver :
+ public Gio::Cancellable
+{
+ public:
+ virtual
+ ~IProgressObserver() throw() = 0;
+
+ virtual bool
+ is_finished() const throw() = 0;
+
+ virtual void
+ progress() throw() = 0;
+
+ virtual void
+ set_description(const Glib::ustring & description)
+ throw() = 0;
+
+ virtual void
+ set_fraction(gdouble fraction) throw() = 0;
+
+ virtual void
+ set_total(guint64 total) throw() = 0;
+
+ protected:
+ IProgressObserver() throw();
+
+ private:
+};
+
+} // namespace Solang
+
+#endif // SOLANG_I_PROGRESS_OBSERVER_H
diff --git a/src/common/non-copyable.cpp b/src/common/non-copyable.cpp
index a1e8335..0206d71 100644
--- a/src/common/non-copyable.cpp
+++ b/src/common/non-copyable.cpp
@@ -27,7 +27,7 @@ NonCopyable::NonCopyable()
{
}
-NonCopyable::~NonCopyable() throw()
+NonCopyable::~NonCopyable()
{
}
diff --git a/src/common/non-copyable.h b/src/common/non-copyable.h
index d9b47cf..f742ddd 100644
--- a/src/common/non-copyable.h
+++ b/src/common/non-copyable.h
@@ -26,7 +26,7 @@ class NonCopyable
{
public:
virtual
- ~NonCopyable() throw();
+ ~NonCopyable();
protected:
NonCopyable();
diff --git a/src/common/operation.cpp b/src/common/operation.cpp
index d8915b2..54a28cb 100644
--- a/src/common/operation.cpp
+++ b/src/common/operation.cpp
@@ -29,8 +29,9 @@ extern "C"
#include <geglmm/buffer.h>
#include <geglmm/processor.h>
+#include "finally.h"
+#include "i-progress-observer.h"
#include "operation.h"
-#include "progress-observer.h"
namespace Solang
{
@@ -46,13 +47,12 @@ Operation::~Operation() throw()
BufferPtr
Operation::apply(const BufferPtr & buffer,
- const ProgressObserverPtr & observer) throw()
+ const ProgressObserverPtr & observer)
+ throw(Glib::Thread::Exit)
{
if (0 != observer)
{
- observer->set_event_description(get_description());
- observer->set_num_events(100);
- observer->set_current_events(0);
+ observer->set_description(get_description());
}
const NodePtr root = Gegl::Node::create();
@@ -69,7 +69,7 @@ Operation::apply(const BufferPtr & buffer,
const NodePtr buffer_sink = root->new_child("operation",
"gegl:buffer-sink");
- GeglBuffer * output_buffer;
+ GeglBuffer * output_buffer = 0;
gegl_node_set(buffer_sink->gobj(),
"buffer", &output_buffer,
NULL);
@@ -79,25 +79,25 @@ Operation::apply(const BufferPtr & buffer,
gdouble progress;
GeglProcessor * const processor = gegl_node_new_processor(
buffer_sink->gobj(), 0);
+ const Finally finally(sigc::bind(sigc::ptr_fun(&g_object_unref),
+ processor));
while (true == gegl_processor_work(processor, &progress))
{
if (0 != observer)
{
- observer->set_current_events(static_cast<guint64>(
- progress * 100.0));
- if (true == observer->get_stop())
+ observer->set_fraction(progress);
+ if (true == observer->is_cancelled())
{
- break;
+ // FIXME: Find a better way to do this.
+ if (0 != output_buffer)
+ {
+ g_object_unref(output_buffer);
+ }
+ throw Glib::Thread::Exit();
}
}
}
- g_object_unref(processor);
-
- if (0 != observer)
- {
- observer->reset();
- }
return Glib::wrap(output_buffer, false);
}
diff --git a/src/common/operation.h b/src/common/operation.h
index 6af154e..0785ccc 100644
--- a/src/common/operation.h
+++ b/src/common/operation.h
@@ -30,7 +30,8 @@ class Operation :
public:
virtual BufferPtr
apply(const BufferPtr & buffer,
- const ProgressObserverPtr & observer) throw();
+ const ProgressObserverPtr & observer)
+ throw(Glib::Thread::Exit);
protected:
virtual
diff --git a/src/common/progress-dialog.cpp b/src/common/progress-dialog.cpp
index 8b45773..e199399 100644
--- a/src/common/progress-dialog.cpp
+++ b/src/common/progress-dialog.cpp
@@ -1,6 +1,6 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
- * Copyright (C) 2009 Debarshi Ray <rishi gnu org>
+ * Copyright (C) 2010, 2009 Debarshi Ray <rishi gnu org>
*
* Solang is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -16,52 +16,35 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/*
+ * Based on code by: Alexander Larsson
+ *
+ * This widget was originally written in C as a part of Nautilus:
+ * libnautilus-private/nautilus-progress-info.c
+ */
+
#include "config.h"
-#include <sstream>
+#include <glibmm/i18n.h>
#include "progress-dialog.h"
-#include "progress-observer.h"
namespace Solang
{
-ProgressDialog::ProgressDialog(const ProgressObserverPtr & observer)
- throw() :
- Gtk::Dialog(),
- observer_(observer),
- primaryLabel_("", Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false),
- mainVBox_(false, 3),
- progressBar_()
+ProgressDialog::ProgressDialog(Gtk::Window & parent) throw() :
+ Gtk::Dialog(_("Pending Operations"), parent, false, false),
+ num_(0)
{
- set_border_width(12);
- set_default_size(408, 108);
- set_has_separator(false);
-
- Gtk::VBox * const dialog_vbox = get_vbox();
- dialog_vbox->set_spacing(12);
-
- primaryLabel_.set_use_markup(true);
- dialog_vbox->pack_start(primaryLabel_, Gtk::PACK_SHRINK, 0);
+ Gtk::VBox * const vbox = get_vbox();
+ vbox->set_homogeneous(false);
+ vbox->set_spacing(5);
- dialog_vbox->pack_start(mainVBox_, Gtk::PACK_EXPAND_WIDGET, 0);
-
- progressBar_.set_orientation(Gtk::PROGRESS_LEFT_TO_RIGHT);
- mainVBox_.pack_start(progressBar_, Gtk::PACK_SHRINK, 0);
-
- add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ set_border_width(10);
+ set_position(Gtk::WIN_POS_CENTER);
+ set_resizable(false);
show_all_children();
-
- observer_->description_changed().connect(sigc::mem_fun(*this,
- &ProgressDialog::on_observer_description_changed));
-
- observer_->progress().connect(sigc::mem_fun(*this,
- &ProgressDialog::on_progress));
-
- observer_->dispatcher_reset().connect(
- sigc::mem_fun(*this,
- &ProgressDialog::on_reset));
}
ProgressDialog::~ProgressDialog() throw()
@@ -69,73 +52,36 @@ ProgressDialog::~ProgressDialog() throw()
}
void
-ProgressDialog::set_progress_title()
+ProgressDialog::attach(Gtk::Widget & child) throw()
{
- const Glib::ustring & description
- = observer_->get_event_description();
+ Gtk::VBox * const vbox = get_vbox();
+ vbox->pack_start(child, false, false, 6);
- set_title(description);
- primaryLabel_.set_markup("<b><big>" + description + "</big></b>");
+ num_++;
+ child.show_all();
+ present();
}
void
-ProgressDialog::pulse() throw()
+ProgressDialog::detach(Gtk::Widget & child) throw()
{
- progressBar_.pulse();
-}
+ Gtk::VBox * const vbox = get_vbox();
+ vbox->remove(child);
-void
-ProgressDialog::set_pulse_step(double fraction) throw()
-{
- progressBar_.set_pulse_step(fraction);
+ num_--;
+ if (0 == num_)
+ {
+ hide();
+ }
}
bool
ProgressDialog::on_delete_event(GdkEventAny * event)
{
- hide();
- return false;
-}
+ const bool return_value = Gtk::Dialog::on_delete_event(event);
-void
-ProgressDialog::on_observer_description_changed() throw()
-{
- set_progress_title();
-}
-
-void
-ProgressDialog::on_progress() throw()
-{
- const guint64 num_events = observer_->get_num_events();
- if (0 == num_events)
- {
- return;
- }
-
- std::ostringstream sout;
- sout << observer_->get_current_events() << " of "
- << num_events << " completed";
-
- progressBar_.set_text(sout.str());
- progressBar_.set_fraction(
- static_cast<double>(observer_->get_current_events())
- / static_cast<double>(num_events));
-}
-
-void
-ProgressDialog::on_response(int response_id)
-{
- observer_->set_stop(true);
hide();
-}
-
-void
-ProgressDialog::on_reset() throw()
-{
- primaryLabel_.set_markup("");
- progressBar_.set_fraction(0.0);
- progressBar_.set_text("");
- set_title("");
+ return return_value;
}
} // namespace Solang
diff --git a/src/common/progress-dialog.h b/src/common/progress-dialog.h
index edd5d8f..87fe613 100644
--- a/src/common/progress-dialog.h
+++ b/src/common/progress-dialog.h
@@ -1,6 +1,6 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
- * Copyright (C) 2009 Debarshi Ray <rishi gnu org>
+ * Copyright (C) 2010, 2009 Debarshi Ray <rishi gnu org>
*
* Solang is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -16,14 +16,18 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/*
+ * Based on code by: Alexander Larsson
+ *
+ * This widget was originally written in C as a part of Nautilus:
+ * libnautilus-private/nautilus-progress-info.h
+ */
+
#ifndef SOLANG_PROGRESS_DIALOG_H
#define SOLANG_PROGRESS_DIALOG_H
-#include <glibmm.h>
#include <gtkmm.h>
-#include "types.h"
-
namespace Solang
{
@@ -31,46 +35,23 @@ class ProgressDialog :
public Gtk::Dialog
{
public:
- ProgressDialog(const ProgressObserverPtr & observer) throw();
+ ProgressDialog(Gtk::Window & parent) throw();
virtual
~ProgressDialog() throw();
void
- pulse() throw();
+ attach(Gtk::Widget & child) throw();
void
- set_pulse_step(double fraction) throw();
-
- void
- set_progress_title();
+ detach(Gtk::Widget & child) throw();
protected:
virtual bool
on_delete_event(GdkEventAny * event);
- virtual void
- on_response(int response_id);
-
- void
- on_observer_description_changed() throw();
-
- void
- on_progress() throw();
-
- void
- on_reset() throw();
-
- ProgressObserverPtr observer_;
-
- Gtk::Label primaryLabel_;
-
- Gtk::VBox mainVBox_;
-
- Gtk::ProgressBar progressBar_;
-
-
private:
+ guint num_;
};
} // namespace Solang
diff --git a/src/common/progress-observer.h b/src/common/progress-observer.h
index 2808548..1d0652f 100644
--- a/src/common/progress-observer.h
+++ b/src/common/progress-observer.h
@@ -1,5 +1,6 @@
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
+ * Copyright (C) 2010 Debarshi Ray <rishi gnu org>
* Copyright (C) 2009 Santanu Sinha <santanu sinha gmail com>
*
* Solang is free software: you can redistribute it and/or modify it
@@ -19,124 +20,218 @@
#ifndef SOLANG_PROGRESS_OBSERVER_H
#define SOLANG_PROGRESS_OBSERVER_H
-#include <tr1/memory>
+#include <glibmm/i18n.h>
+#include <sigc++/sigc++.h>
-#include <glibmm.h>
+#include "i-progress-observer.h"
+#include "progress-dialog.h"
+#include "progress-widget.h"
+#include "types.h"
+#include "utils.h"
namespace Solang
{
-class ProgressObserver
+template <typename T>
+class ProgressObserver :
+ public IProgressObserver
{
public:
- ProgressObserver() throw();
-
- ProgressObserver(const ProgressObserver & source) throw();
-
- ProgressObserver &
- operator=(const ProgressObserver & source) throw();
+ static ProgressObserverPtr
+ create(ProgressDialog & progress_dialog);
+ virtual
~ProgressObserver() throw();
- inline guint64
- get_num_events() const throw();
+ virtual bool
+ is_finished() const throw();
- void
- set_num_events(guint64 numEvents) throw();
+ virtual void
+ progress() throw();
- inline guint64
- get_current_events() const throw();
+ virtual void
+ set_description(const Glib::ustring & description) throw();
- void
- set_current_events(guint64 current_events) throw();
+ virtual void
+ set_fraction(gdouble fraction) throw();
- inline const Glib::ustring &
- get_event_description() const throw();
+ virtual void
+ set_total(guint64 total) throw();
- void
- set_event_description(const Glib::ustring & event_description)
- throw();
+ protected:
+ ProgressObserver(ProgressDialog & progress_dialog) throw();
- inline bool
- get_stop() const throw();
+ virtual void
+ on_cancelled();
+ private:
void
- set_stop(bool value) throw();
+ clean_up() throw();
void
- receive_event_notifiation() throw();
+ on_fraction_changed() throw();
- inline Glib::Dispatcher &
- description_changed() throw();
+ T fractionChanged_;
- inline Glib::Dispatcher &
- progress() throw();
-
- Glib::Dispatcher &
- dispatcher_reset() throw();
+ mutable Glib::Mutex mutex_;
- void
- reset() throw();
+ gdouble fraction_;
- private:
- guint64 numEvents_;
+ guint64 current_;
- guint64 currentEvents_;
+ guint64 total_;
- Glib::Dispatcher descriptionChanged_;
+ ProgressDialog & progressDialog_;
- Glib::Dispatcher progress_;
+ ProgressWidget progressWidget_;
- Glib::Dispatcher reset_;
+ sigc::connection connectionFractionChanged_;
+};
- mutable Glib::Mutex mutex_;
+template <typename T>
+ProgressObserver<T>::ProgressObserver(ProgressDialog & progress_dialog)
+ throw() :
+ IProgressObserver(),
+ fractionChanged_(),
+ mutex_(),
+ fraction_(0.0),
+ current_(0),
+ total_(0),
+ progressDialog_(progress_dialog),
+ progressWidget_(),
+ connectionFractionChanged_()
+{
+ fractionChanged_.connect(
+ sigc::mem_fun(*this,
+ &ProgressObserver::on_fraction_changed));
+ progressWidget_.signal_cancelled().connect(
+ sigc::mem_fun(*this,
+ &ProgressObserver::cancel));
+}
- Glib::ustring eventDescription_;
+template <typename T>
+ProgressObserver<T>::~ProgressObserver() throw()
+{
+ clean_up();
+}
- bool stop_;
-};
+template <typename T>
+void
+ProgressObserver<T>::clean_up() throw()
+{
+ if (0 != progressWidget_.get_parent())
+ {
+ progressDialog_.detach(progressWidget_);
+ }
+}
+template <typename T>
+ProgressObserverPtr
+ProgressObserver<T>::create(ProgressDialog & progress_dialog)
+{
+ return ProgressObserverPtr(new ProgressObserver<T>(
+ progress_dialog));
+}
-inline guint64
-ProgressObserver::get_num_events() const throw()
+template <typename T>
+bool
+ProgressObserver<T>::is_finished() const throw()
{
Glib::Mutex::Lock lock(mutex_);
- return numEvents_;
+ return (0 < total_) ? (current_ == total_)
+ : is_equal(1.0, fraction_);
}
-inline guint64
-ProgressObserver::get_current_events() const throw()
+template <typename T>
+void
+ProgressObserver<T>::on_cancelled()
{
- Glib::Mutex::Lock lock(mutex_);
- return currentEvents_;
+ clean_up();
+ connectionFractionChanged_.block();
}
-inline const Glib::ustring &
-ProgressObserver::get_event_description() const throw()
+template <typename T>
+void
+ProgressObserver<T>::on_fraction_changed() throw()
{
- Glib::Mutex::Lock lock(mutex_);
- return eventDescription_;
+ {
+ Glib::Mutex::Lock lock(mutex_);
+
+ progressWidget_.set_fraction(fraction_);
+
+ if (0 < total_)
+ {
+ // Translators: Progress bar text. eg., 13 of 42 completed.
+ const Glib::ustring details = Glib::ustring::compose(
+ _("%1 of %2 completed"),
+ current_,
+ total_);
+ progressWidget_.set_details(details);
+ }
+ else
+ {
+ // Translators: Progress bar text. eg., 13% completed.
+ const Glib::ustring details = Glib::ustring::compose(
+ _("%1%% complete"),
+ fraction_ * 100.0);
+ progressWidget_.set_details(details);
+ }
+ }
+
+ if (0 == progressWidget_.get_parent())
+ {
+ progressDialog_.attach(progressWidget_);
+ }
}
-inline bool
-ProgressObserver::get_stop() const throw()
+template <typename T>
+void
+ProgressObserver<T>::progress() throw()
{
- Glib::Mutex::Lock lock(mutex_);
- return stop_;
+ if (true == is_cancelled())
+ {
+ return;
+ }
+
+ {
+ Glib::Mutex::Lock lock(mutex_);
+ current_++;
+ fraction_ = static_cast<gdouble>(current_)
+ / static_cast<gdouble>(total_);
+ }
+ fractionChanged_.emit();
}
-inline Glib::Dispatcher &
-ProgressObserver::description_changed() throw()
+template <typename T>
+void
+ProgressObserver<T>::set_description(const Glib::ustring & description)
+ throw()
{
- Glib::Mutex::Lock lock(mutex_);
- return descriptionChanged_;
+ progressWidget_.set_status(description);
+}
+
+template <typename T>
+void
+ProgressObserver<T>::set_fraction(gdouble fraction) throw()
+{
+ if (true == is_cancelled())
+ {
+ return;
+ }
+
+ {
+ Glib::Mutex::Lock lock(mutex_);
+ fraction_ = fraction;
+ }
+ fractionChanged_.emit();
}
-inline Glib::Dispatcher &
-ProgressObserver::progress() throw()
+template <typename T>
+void
+ProgressObserver<T>::set_total(guint64 total) throw()
{
Glib::Mutex::Lock lock(mutex_);
- return progress_;
+ total_ = total;
}
} // namespace Solang
diff --git a/src/common/progress-widget.cpp b/src/common/progress-widget.cpp
new file mode 100644
index 0000000..1a37459
--- /dev/null
+++ b/src/common/progress-widget.cpp
@@ -0,0 +1,99 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * Copyright (C) 2010 Debarshi Ray <rishi gnu org>
+ *
+ * Solang 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.
+ *
+ * Solang 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/>.
+ */
+
+/*
+ * Based on code by: Alexander Larsson
+ *
+ * This widget was originally written in C as a part of Nautilus:
+ * libnautilus-private/nautilus-progress-info.c
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#include "progress-widget.h"
+
+namespace Solang
+{
+
+ProgressWidget::ProgressWidget() throw() :
+ Gtk::VBox(false, 5),
+ button_(),
+ hBox_(false, 10),
+ image_(Gtk::Stock::CANCEL, Gtk::ICON_SIZE_BUTTON),
+ detailsLabel_("details", false),
+ statusLabel_("status", false),
+ progressBar_(),
+ vBox_(false, 0)
+{
+ statusLabel_.set_alignment(0.0, 0.5);
+ statusLabel_.set_line_wrap(true);
+ statusLabel_.set_line_wrap_mode(Pango::WRAP_WORD_CHAR);
+ statusLabel_.set_size_request(500, -1);
+ pack_start(statusLabel_, true, false, 0);
+
+ progressBar_.set_pulse_step(0.05);
+ vBox_.pack_start(progressBar_, true, false, 0);
+ hBox_.pack_start(vBox_, true, true, 0);
+
+ button_.add(image_);
+ hBox_.pack_start(button_, false, false, 0);
+
+ pack_start(hBox_, false, false, 0);
+
+ detailsLabel_.set_alignment(0.0, 0.5);
+ detailsLabel_.set_line_wrap(true);
+ detailsLabel_.set_use_markup(true);
+ pack_start(detailsLabel_, true, false, 0);
+
+ show_all_children();
+}
+
+ProgressWidget::~ProgressWidget() throw()
+{
+}
+
+void
+ProgressWidget::set_details(const Glib::ustring & details) throw()
+{
+ const Glib::ustring markup
+ = Glib::ustring::compose("<span size='small'>%1</span>",
+ Glib::Markup::escape_text(details));
+ detailsLabel_.set_markup(markup);
+}
+
+void
+ProgressWidget::set_fraction(gdouble fraction) throw()
+{
+ progressBar_.set_fraction(fraction);
+}
+
+void
+ProgressWidget::set_status(const Glib::ustring & status) throw()
+{
+ statusLabel_.set_text(status);
+}
+
+Glib::SignalProxy0<void>
+ProgressWidget::signal_cancelled() throw()
+{
+ return button_.signal_clicked();
+}
+
+} // namespace Solang
diff --git a/src/common/progress-widget.h b/src/common/progress-widget.h
new file mode 100644
index 0000000..5dabe10
--- /dev/null
+++ b/src/common/progress-widget.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * Copyright (C) 2010 Debarshi Ray <rishi gnu org>
+ *
+ * Solang 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.
+ *
+ * Solang 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/>.
+ */
+
+/*
+ * Based on code by: Alexander Larsson
+ *
+ * This widget was originally written in C as a part of Nautilus:
+ * libnautilus-private/nautilus-progress-info.h
+ */
+
+#ifndef SOLANG_WIDGET_H
+#define SOLANG_WIDGET_H
+
+#include <glibmm.h>
+#include <gtkmm.h>
+
+namespace Solang
+{
+
+class ProgressWidget :
+ public Gtk::VBox
+{
+ public:
+ ProgressWidget() throw();
+
+ virtual
+ ~ProgressWidget() throw();
+
+ void
+ set_details(const Glib::ustring & details) throw();
+
+ void
+ set_fraction(gdouble fraction) throw();
+
+ void
+ set_status(const Glib::ustring & status) throw();
+
+ Glib::SignalProxy0<void>
+ signal_cancelled() throw();
+
+ private:
+ Gtk::Button button_;
+
+ Gtk::HBox hBox_;
+
+ Gtk::Image image_;
+
+ Gtk::Label detailsLabel_;
+
+ Gtk::Label statusLabel_;
+
+ Gtk::ProgressBar progressBar_;
+
+ Gtk::VBox vBox_;
+};
+
+} // namespace Solang
+
+#endif // SOLANG_WIDGET_H
diff --git a/src/common/types.h b/src/common/types.h
index 837be80..cc05758 100644
--- a/src/common/types.h
+++ b/src/common/types.h
@@ -51,6 +51,7 @@ class Processor;
namespace Gio
{
+class AsyncResult;
class DataInputStream;
class File;
@@ -185,6 +186,11 @@ typedef std::tr1::shared_ptr<const IPlugin> ConstIPluginPtr;
typedef std::tr1::shared_ptr<IPlugin> IPluginPtr;
typedef std::vector<IPluginPtr> IPluginList;
+class IProgressObserver;
+typedef Glib::RefPtr<const IProgressObserver>
+ ConstProgressObserverPtr;
+typedef Glib::RefPtr<IProgressObserver> ProgressObserverPtr;
+
class IRenderer;
typedef const IRenderer * ConstIRendererPtr;
typedef IRenderer * IRendererPtr;
@@ -202,6 +208,7 @@ typedef std::tr1::shared_ptr<const Photo> ConstPhotoPtr;
typedef std::tr1::shared_ptr<Photo> PhotoPtr;
typedef Photo * UnrefPhotoPtr;
typedef std::vector<PhotoPtr> PhotoList;
+typedef std::tr1::shared_ptr<PhotoList> PhotoListPtr;
class IPhotoSearchCriteria;
typedef std::tr1::shared_ptr<const IPhotoSearchCriteria>
@@ -222,11 +229,6 @@ typedef Glib::RefPtr<ProgressDialog> ProgressDialogPtr;
typedef Glib::RefPtr<Glib::Dispatcher> DispatcherPtr;
-class ProgressObserver;
-typedef std::tr1::shared_ptr<const ProgressObserver>
- ConstProgressObserverPtr;
-typedef std::tr1::shared_ptr<ProgressObserver> ProgressObserverPtr;
-
class IStorage;
typedef std::tr1::shared_ptr<const IStorage> ConstIStoragePtr;
typedef std::tr1::shared_ptr<IStorage> IStoragePtr;
@@ -281,6 +283,9 @@ typedef Glib::RefPtr<Gegl::Node> NodePtr;
typedef Glib::RefPtr<const Gegl::Processor> ConstProcessorPtr;
typedef Glib::RefPtr<Gegl::Processor> ProcessorPtr;
+typedef Glib::RefPtr<const Gio::AsyncResult> ConstAsyncResultPtr;
+typedef Glib::RefPtr<Gio::AsyncResult> AsyncResultPtr;
+
typedef Glib::RefPtr<const Gio::DataInputStream>
ConstDataInputStreamPtr;
typedef Glib::RefPtr<Gio::DataInputStream> DataInputStreamPtr;
diff --git a/src/editor/editable-photo.cpp b/src/editor/editable-photo.cpp
index 5108586..078293f 100644
--- a/src/editor/editable-photo.cpp
+++ b/src/editor/editable-photo.cpp
@@ -21,25 +21,27 @@
#include "config.h"
#endif // HAVE_CONFIG_H
+#include <algorithm>
+
#include <geglmm.h>
#include <geglmm/buffer.h>
#include "buffer-maker.h"
#include "buffer-pixbuf-converter.h"
#include "editable-photo.h"
+#include "finally.h"
#include "i-operation.h"
+#include "i-progress-observer.h"
#include "photo.h"
namespace Solang
{
-EditablePhoto::EditablePhoto(const PhotoPtr & photo,
- const ProgressObserverPtr & observer) throw() :
+EditablePhoto::EditablePhoto(const PhotoPtr & photo) throw() :
buffer_(0),
photo_(photo),
pixbuf_(0),
pending_(),
- observer_(observer),
applyEnd_(),
threadPool_(1, false)
{
@@ -49,15 +51,34 @@ EditablePhoto::EditablePhoto(const PhotoPtr & photo,
EditablePhoto::~EditablePhoto() throw()
{
+ if (true == pending_.empty())
+ {
+ return;
+ }
+
+ const Triplet & current = pending_.front();
+ const ProgressObserverPtr & observer = current.third;
+
+ if (0 != observer)
+ {
+ observer->cancel();
+ }
}
void
EditablePhoto::apply_async(const IOperationPtr & operation,
- const SlotAsyncReady & slot) throw()
+ const SlotAsyncReady & slot,
+ const ProgressObserverPtr & observer)
+ throw()
{
const SlotAsyncReadyPtr slot_copy(new SlotAsyncReady(slot));
- pending_.push(std::make_pair(operation, slot_copy));
+ Triplet triplet;
+ triplet.first = operation;
+ triplet.second = slot_copy;
+ triplet.third = observer;
+
+ pending_.push(triplet);
if (1 < pending_.size())
{
return;
@@ -70,19 +91,23 @@ EditablePhoto::apply_async(const IOperationPtr & operation,
void
EditablePhoto::apply_begin() throw()
{
- const std::pair<IOperationPtr, SlotAsyncReadyPtr> & current
- = pending_.front();
+ const Triplet & current = pending_.front();
threadPool_.push(sigc::bind(
sigc::mem_fun(*this,
&EditablePhoto::apply_worker),
- current.first));
+ current.first,
+ current.third));
}
void
-EditablePhoto::apply_worker(const IOperationPtr & operation)
+EditablePhoto::apply_worker(const IOperationPtr & operation,
+ const ProgressObserverPtr & observer)
throw(Glib::Thread::Exit)
{
+ const Finally finally(sigc::mem_fun(applyEnd_,
+ &Glib::Dispatcher::emit));
+
if (0 == buffer_)
{
std::string path;
@@ -100,19 +125,17 @@ EditablePhoto::apply_worker(const IOperationPtr & operation)
buffer_ = buffer_maker(path);
}
- buffer_ = operation->apply(buffer_, observer_);
+ buffer_ = operation->apply(buffer_, observer);
g_warning("done op");
BufferPixbufConverter buffer_pixbuf_converter;
pixbuf_ = buffer_pixbuf_converter(buffer_);
g_warning("done pixbuf");
- applyEnd_.emit();
}
void
EditablePhoto::on_apply_end() throw()
{
- const std::pair<IOperationPtr, SlotAsyncReadyPtr> current
- = pending_.front();
+ const Triplet current = pending_.front();
pending_.pop();
photo_->set_buffer(pixbuf_);
@@ -122,6 +145,17 @@ EditablePhoto::on_apply_end() throw()
(*current.second)();
}
+ const ProgressObserverPtr & observer = current.third;
+
+ // Clear the pending queue if:
+ // + an operation was cancelled
+ // + the buffer could not be created
+ if (true == observer->is_cancelled() || 0 == buffer_)
+ {
+ PendingOperationQueue tmp;
+ std::swap(pending_, tmp);
+ }
+
if (true == pending_.empty())
{
return;
diff --git a/src/editor/editable-photo.h b/src/editor/editable-photo.h
index 43c45e8..63698e2 100644
--- a/src/editor/editable-photo.h
+++ b/src/editor/editable-photo.h
@@ -40,28 +40,34 @@ class EditablePhoto
typedef std::tr1::shared_ptr<SlotAsyncReady>
SlotAsyncReadyPtr;
- typedef std::queue<std::pair<IOperationPtr,
- SlotAsyncReadyPtr> >
- PendingOperationQueue;
-
- EditablePhoto(const PhotoPtr & photo,
- const ProgressObserverPtr & observer) throw();
+ EditablePhoto(const PhotoPtr & photo) throw();
~EditablePhoto() throw();
void
apply_async(const IOperationPtr & operation,
- const SlotAsyncReady & slot) throw();
+ const SlotAsyncReady & slot,
+ const ProgressObserverPtr & observer) throw();
PhotoPtr &
get_photo() throw();
private:
+ struct Triplet
+ {
+ IOperationPtr first;
+ SlotAsyncReadyPtr second;
+ ProgressObserverPtr third;
+ };
+
+ typedef std::queue<Triplet> PendingOperationQueue;
+
void
apply_begin() throw();
void
- apply_worker(const IOperationPtr & operation)
+ apply_worker(const IOperationPtr & operation,
+ const ProgressObserverPtr & observer)
throw(Glib::Thread::Exit);
void
@@ -75,8 +81,6 @@ class EditablePhoto
PendingOperationQueue pending_;
- ProgressObserverPtr observer_;
-
Glib::Dispatcher applyEnd_;
Glib::ThreadPool threadPool_;
diff --git a/src/editor/editor.cpp b/src/editor/editor.cpp
index 15a50fb..610d0de 100644
--- a/src/editor/editor.cpp
+++ b/src/editor/editor.cpp
@@ -31,6 +31,7 @@
#include "flip-vert-operation.h"
#include "i-renderer.h"
#include "non-copyable.h"
+#include "progress-observer.h"
#include "rotate-clock-operation.h"
#include "rotate-counter-operation.h"
@@ -248,12 +249,8 @@ Editor::apply_async(const IOperationPtr & operation) throw()
if (editablePhotos_.end() == iter)
{
- Engine & engine = application_->get_engine();
- const ProgressObserverPtr & observer = engine.get_default_observer();
-
editable_photo = EditablePhotoPtr(new EditablePhoto(
- currentPhoto_,
- observer));
+ currentPhoto_));
editablePhotos_.insert(std::make_pair(current_uri,
editable_photo));
}
@@ -262,11 +259,16 @@ Editor::apply_async(const IOperationPtr & operation) throw()
editable_photo = iter->second;
}
+ const ProgressObserverPtr observer
+ = ProgressObserver<Glib::Dispatcher>::create(
+ application_->get_progress_dialog());
+
editable_photo->apply_async(
operation,
sigc::bind(sigc::mem_fun(*this,
&Editor::on_action_edit_photo_end),
- editable_photo));
+ editable_photo),
+ observer);
}
void
diff --git a/src/exporter/brasero-destination.cpp b/src/exporter/brasero-destination.cpp
index 841d5ac..ddcd9a9 100644
--- a/src/exporter/brasero-destination.cpp
+++ b/src/exporter/brasero-destination.cpp
@@ -25,9 +25,9 @@
#include <glibmm/i18n.h>
#include "brasero-destination.h"
+#include "i-progress-observer.h"
#include "photo.h"
#include "photo-destination-enums.h"
-#include "progress-observer.h"
namespace Solang
{
@@ -38,14 +38,9 @@ BraseroDestination::BraseroDestination() throw() :
braseroSessionCfg_(0),
braseroTrackDataCfg_(0),
braseroDriveSelection_(0),
- braseroBurnBegin_(),
initEnd_()
{
brasero_burn_library_start(0, 0);
-
- braseroBurnBegin_.connect(
- sigc::mem_fun(*this,
- &BraseroDestination::on_brasero_burn_begin));
}
BraseroDestination::~BraseroDestination() throw()
@@ -65,10 +60,9 @@ BraseroDestination::final(Application & application) throw()
}
void
-BraseroDestination::export_photo(
+BraseroDestination::export_photo_async(
const PhotoPtr & photo,
- const ProgressObserverPtr & observer)
- throw()
+ const ProgressObserverPtr &) throw()
{
brasero_track_data_cfg_add(braseroTrackDataCfg_,
photo->get_uri().c_str(),
@@ -76,7 +70,7 @@ BraseroDestination::export_photo(
}
void
-BraseroDestination::export_photos(
+BraseroDestination::export_photos_async(
const PhotoList & photos,
const ProgressObserverPtr & observer)
throw()
@@ -86,13 +80,6 @@ BraseroDestination::export_photos(
return;
}
- if (0 != observer)
- {
- observer->set_event_description(_("Exporting photos"));
- observer->set_num_events(photos.size());
- observer->set_current_events(0);
- }
-
braseroSessionCfg_ = brasero_session_cfg_new();
brasero_burn_session_set_burner(
BRASERO_BURN_SESSION(braseroSessionCfg_), braseroDrive_);
@@ -109,23 +96,13 @@ BraseroDestination::export_photos(
for (it = photos.begin(); photos.end() != it; it++)
{
- export_photo(*it, observer);
-
- if (0 != observer)
- {
- observer->receive_event_notifiation();
- }
+ export_photo_async(*it, observer);
}
g_object_unref(braseroTrackDataCfg_);
braseroTrackDataCfg_ = 0;
- if (0 != observer)
- {
- observer->reset();
- }
-
- braseroBurnBegin_.emit();
+ brasero_burn_begin();
}
void BraseroDestination::final() throw()
@@ -191,6 +168,15 @@ BraseroDestination::set_create_archive(bool value) throw()
}
void
+BraseroDestination::brasero_burn_begin() throw()
+{
+ Glib::signal_idle().connect_once(
+ sigc::mem_fun(*this,
+ &BraseroDestination::brasero_burn_begin_idle),
+ Glib::PRIORITY_LOW);
+}
+
+void
BraseroDestination::brasero_burn_begin_idle() throw()
{
GtkWidget * const burn_dialog = brasero_burn_dialog_new();
@@ -205,21 +191,4 @@ BraseroDestination::brasero_burn_begin_idle() throw()
braseroSessionCfg_ = 0;
}
-void
-BraseroDestination::on_brasero_burn_begin() throw()
-{
- // FIXME: Sometimes the brasero_burn_dialog_run gets stuck and
- // freezes the application. This is a workaround.
-
- while (true == Gtk::Main::events_pending())
- {
- Gtk::Main::iteration();
- }
-
- Glib::signal_idle().connect_once(
- sigc::mem_fun(*this,
- &BraseroDestination::brasero_burn_begin_idle),
- Glib::PRIORITY_LOW);
-}
-
} // namespace Solang
diff --git a/src/exporter/brasero-destination.h b/src/exporter/brasero-destination.h
index 4d4f53d..5eff35c 100644
--- a/src/exporter/brasero-destination.h
+++ b/src/exporter/brasero-destination.h
@@ -46,12 +46,9 @@ class BraseroDestination :
final(Application & application) throw();
virtual void
- export_photo(const PhotoPtr & photo,
- const ProgressObserverPtr & observer) throw();
-
- virtual void
- export_photos(const PhotoList & photos,
- const ProgressObserverPtr & observer) throw();
+ export_photos_async(const PhotoList & photos,
+ const ProgressObserverPtr & observer)
+ throw();
virtual void
final() throw();
@@ -82,10 +79,14 @@ class BraseroDestination :
protected:
void
- brasero_burn_begin_idle() throw();
+ export_photo_async(const PhotoPtr & photo,
+ const ProgressObserverPtr &) throw();
void
- on_brasero_burn_begin() throw();
+ brasero_burn_begin() throw();
+
+ void
+ brasero_burn_begin_idle() throw();
BraseroDrive * braseroDrive_;
@@ -95,8 +96,6 @@ class BraseroDestination :
GtkWidget * braseroDriveSelection_;
- Glib::Dispatcher braseroBurnBegin_;
-
sigc::signal<void, bool> initEnd_;
private:
diff --git a/src/exporter/directory-destination.cpp b/src/exporter/directory-destination.cpp
index 77eb885..919cd64 100644
--- a/src/exporter/directory-destination.cpp
+++ b/src/exporter/directory-destination.cpp
@@ -28,9 +28,9 @@
#include <glibmm/i18n.h>
#include "directory-destination.h"
+#include "i-progress-observer.h"
#include "photo.h"
#include "photo-destination-enums.h"
-#include "progress-observer.h"
namespace Solang
{
@@ -60,8 +60,9 @@ DirectoryDestination::final(Application & application) throw()
}
void
-DirectoryDestination::export_photo(
+DirectoryDestination::export_photo_async(
const PhotoPtr & photo,
+ const PhotoListPtr & pending,
const ProgressObserverPtr & observer)
throw()
{
@@ -69,27 +70,30 @@ DirectoryDestination::export_photo(
const FilePtr dest = Gio::File::create_for_path(
filename_ + "/" + file->get_basename());
- try
- {
- file->copy(dest, Gio::FILE_COPY_NONE);
- }
- catch (const Gio::Error & e)
- {
- g_warning("%s", e.what().c_str());
- }
+ file->copy_async(
+ dest,
+ sigc::slot<void, goffset, goffset>(),
+ sigc::bind(
+ sigc::mem_fun(*this,
+ &DirectoryDestination::on_async_copy_ready),
+ file,
+ pending,
+ observer),
+ observer,
+ Gio::FILE_COPY_NONE,
+ Glib::PRIORITY_DEFAULT);
}
void
-DirectoryDestination::export_photos(
+DirectoryDestination::export_photos_async(
const PhotoList & photos,
const ProgressObserverPtr & observer)
throw()
{
if (0 != observer)
{
- observer->set_event_description(_("Exporting photos"));
- observer->set_num_events(photos.size());
- observer->set_current_events(0);
+ observer->set_description(_("Exporting photos"));
+ observer->set_total(photos.size());
}
if (true == createArchive_)
@@ -116,44 +120,111 @@ DirectoryDestination::export_photos(
}
}
- PhotoList::const_iterator it;
+ const PhotoListPtr pending(new PhotoList(photos.begin(),
+ photos.end()));
- for (it = photos.begin(); photos.end() != it; it++)
- {
- export_photo(*it, observer);
+ export_photo_async(pending->back(), pending, observer);
- if (0 != observer)
- {
- observer->receive_event_notifiation();
- }
- }
+ return;
+}
- if (true == createArchive_)
+void DirectoryDestination::final() throw()
+{
+}
+
+sigc::signal<void, bool> &
+DirectoryDestination::init_end() throw()
+{
+ return initEnd_;
+}
+
+void
+DirectoryDestination::on_async_copy_ready(
+ const AsyncResultPtr & async_result,
+ const FilePtr & file,
+ const PhotoListPtr & pending,
+ const ProgressObserverPtr & observer)
+ throw()
+{
+ try
+ {
+ file->copy_finish(async_result);
+ }
+ catch (const Gio::Error & e)
{
- const std::string command_line
- = "file-roller --add-to=" + filename_ + ".zip"
- + " --add " + filename_;
+ switch (e.code())
+ {
+ case Gio::Error::CANCELLED:
+ return;
+ break;
- Glib::spawn_command_line_sync(command_line);
- g_remove(filename_.c_str());
+ default:
+ g_warning("%s", e.what().c_str());
+ break;
+ }
}
if (0 != observer)
{
- observer->reset();
+ observer->progress();
}
- return;
-}
+ pending->pop_back();
-void DirectoryDestination::final() throw()
-{
+ if (true == pending->empty())
+ {
+ if (true == createArchive_)
+ {
+ const std::string command_line
+ = Glib::find_program_in_path("file-roller")
+ + " --add-to=" + filename_ + ".zip"
+ + " --add " + filename_;
+
+ GPid pid;
+
+ try
+ {
+ Glib::spawn_async(
+ "",
+ Glib::shell_parse_argv(command_line),
+ static_cast<Glib::SpawnFlags>(0),
+ sigc::slot<void>(),
+ &pid);
+ }
+ catch (const Glib::ShellError & e)
+ {
+ g_warning("%s", e.what().c_str());
+ return;
+ }
+ catch (const Glib::SpawnError & e)
+ {
+ g_warning("%s", e.what().c_str());
+ return;
+ }
+
+ Glib::signal_child_watch().connect(
+ sigc::bind(
+ sigc::mem_fun(
+ *this,
+ &DirectoryDestination::on_child_watch),
+ filename_),
+ pid,
+ Glib::PRIORITY_DEFAULT);
+ }
+ }
+ else
+ {
+ export_photo_async(pending->back(), pending, observer);
+ }
}
-sigc::signal<void, bool> &
-DirectoryDestination::init_end() throw()
+void
+DirectoryDestination::on_child_watch(GPid,
+ int,
+ const std::string & filename)
+ throw()
{
- return initEnd_;
+ g_remove(filename.c_str());
}
void
diff --git a/src/exporter/directory-destination.h b/src/exporter/directory-destination.h
index ca2c332..15d1ea6 100644
--- a/src/exporter/directory-destination.h
+++ b/src/exporter/directory-destination.h
@@ -43,12 +43,9 @@ class DirectoryDestination :
final(Application & application) throw();
virtual void
- export_photo(const PhotoPtr & photo,
- const ProgressObserverPtr & observer) throw();
-
- virtual void
- export_photos(const PhotoList & photos,
- const ProgressObserverPtr & observer) throw();
+ export_photos_async(const PhotoList & photos,
+ const ProgressObserverPtr & observer)
+ throw();
virtual void
final() throw();
@@ -78,6 +75,23 @@ class DirectoryDestination :
set_create_archive(bool value) throw();
protected:
+ void
+ export_photo_async(const PhotoPtr & photo,
+ const PhotoListPtr & pending,
+ const ProgressObserverPtr & observer)
+ throw();
+
+ void
+ on_async_copy_ready(const AsyncResultPtr & async_result,
+ const FilePtr & file,
+ const PhotoListPtr & pending,
+ const ProgressObserverPtr & observer)
+ throw();
+
+ void
+ on_child_watch(GPid, int, const std::string & filename)
+ throw();
+
bool createArchive_;
std::string filename_;
diff --git a/src/exporter/exporter.cpp b/src/exporter/exporter.cpp
index 6cdd967..b1470aa 100644
--- a/src/exporter/exporter.cpp
+++ b/src/exporter/exporter.cpp
@@ -211,14 +211,16 @@ Exporter::on_exporter_dialog_response(
= exporter_dialog->get_create_archive();
photoDestination_->set_create_archive(create_archive);
- Glib::ThreadPool & thread_pool
- = application_->get_thread_pool();
Engine & engine = application_->get_engine();
+ const PhotoList & export_queue
+ = engine.get_export_queue();
- thread_pool.push(
- sigc::bind(sigc::mem_fun1(engine,
- &Engine::export_photos),
- photoDestination_));
+ const ProgressObserverPtr observer
+ = ProgressObserver<sigc::signal<void> >::create(
+ application_->get_progress_dialog());
+
+ photoDestination_->export_photos_async(export_queue,
+ observer);
break;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]