Skip to content
Snippets Groups Projects
Commit 7cc2f832 authored by Jérôme Guelfucci's avatar Jérôme Guelfucci
Browse files

Depend on exo-1 for the ExoJob stuff.

This allows us to remove our local copy.
parent 1c6cf5f0
No related branches found
No related tags found
No related merge requests found
...@@ -20,8 +20,6 @@ noinst_LTLIBRARIES = lib/libscreenshooter.la ...@@ -20,8 +20,6 @@ noinst_LTLIBRARIES = lib/libscreenshooter.la
lib_libscreenshooter_la_SOURCES = \ lib_libscreenshooter_la_SOURCES = \
$(lib_libscreenshooter_built_sources) \ $(lib_libscreenshooter_built_sources) \
lib/exo-job.c lib/exo-job.h \
lib/exo-simple-job.c lib/exo-simple-job.h \
lib/katze-throbber.c lib/katze-throbber.h \ lib/katze-throbber.c lib/katze-throbber.h \
lib/libscreenshooter.h \ lib/libscreenshooter.h \
lib/screenshooter-actions.c lib/screenshooter-actions.h \ lib/screenshooter-actions.c lib/screenshooter-actions.h \
...@@ -35,6 +33,7 @@ lib_libscreenshooter_la_SOURCES = \ ...@@ -35,6 +33,7 @@ lib_libscreenshooter_la_SOURCES = \
lib_libscreenshooter_la_CFLAGS = \ lib_libscreenshooter_la_CFLAGS = \
-I$(top_srcdir) \ -I$(top_srcdir) \
@EXO_CFLAGS@ \
@GTK_CFLAGS@ \ @GTK_CFLAGS@ \
@GLIB_CFLAGS@ \ @GLIB_CFLAGS@ \
@LIBXFCE4UTIL_CFLAGS@ \ @LIBXFCE4UTIL_CFLAGS@ \
...@@ -43,6 +42,7 @@ lib_libscreenshooter_la_CFLAGS = \ ...@@ -43,6 +42,7 @@ lib_libscreenshooter_la_CFLAGS = \
-DPACKAGE_LOCALE_DIR=\"$(localedir)\" -DPACKAGE_LOCALE_DIR=\"$(localedir)\"
lib_libscreenshooter_la_LIBADD = \ lib_libscreenshooter_la_LIBADD = \
@EXO_LIBS@ \
@GTK_LIBS@ \ @GTK_LIBS@ \
@LIBXFCE4UTIL_LIBS@ \ @LIBXFCE4UTIL_LIBS@ \
@LIBXFCEGUI4_LIBS@ \ @LIBXFCEGUI4_LIBS@ \
...@@ -74,6 +74,7 @@ lib/screenshooter-marshal.c: lib/screenshooter-marshal.list Makefile ...@@ -74,6 +74,7 @@ lib/screenshooter-marshal.c: lib/screenshooter-marshal.list Makefile
# Main application # Main application
src_xfce4_screenshooter_CFLAGS = \ src_xfce4_screenshooter_CFLAGS = \
-I$(top_srcdir)/lib/ \ -I$(top_srcdir)/lib/ \
@EXO_CFLAGS@ \
@GTK_CFLAGS@ \ @GTK_CFLAGS@ \
@GLIB_CFLAGS@ \ @GLIB_CFLAGS@ \
@LIBXFCE4UTIL_CFLAGS@ \ @LIBXFCE4UTIL_CFLAGS@ \
...@@ -83,6 +84,7 @@ src_xfce4_screenshooter_CFLAGS = \ ...@@ -83,6 +84,7 @@ src_xfce4_screenshooter_CFLAGS = \
-DPACKAGE_LOCALE_DIR=\"$(localedir)\" -DPACKAGE_LOCALE_DIR=\"$(localedir)\"
src_xfce4_screenshooter_LDFLAGS = \ src_xfce4_screenshooter_LDFLAGS = \
@EXO_LIBS@ \
@GTK_LIBS@ \ @GTK_LIBS@ \
@GLIB_LIBS@ \ @GLIB_LIBS@ \
@GTHREAD_LIBS@ \ @GTHREAD_LIBS@ \
...@@ -115,12 +117,14 @@ panel_plugin_xfce4_screenshooter_plugin_CFLAGS = \ ...@@ -115,12 +117,14 @@ panel_plugin_xfce4_screenshooter_plugin_CFLAGS = \
-DPACKAGE_LOCALE_DIR=\"$(localedir)\" \ -DPACKAGE_LOCALE_DIR=\"$(localedir)\" \
-I$(top_srcdir) \ -I$(top_srcdir) \
-I$(top_srcdir)/lib/ \ -I$(top_srcdir)/lib/ \
@EXO_CFLAGS@ \
@LIBXFCE4PANEL_CFLAGS@ \ @LIBXFCE4PANEL_CFLAGS@ \
@LIBXFCEGUI4_CFLAGS@ \ @LIBXFCEGUI4_CFLAGS@ \
@GTHREAD_CFLAGS@ \ @GTHREAD_CFLAGS@ \
@SOUP_CFLAGS@ @SOUP_CFLAGS@
panel_plugin_xfce4_screenshooter_plugin_LDFLAGS = \ panel_plugin_xfce4_screenshooter_plugin_LDFLAGS = \
@EXO_LIBS@ \
@LIBXFCE4PANEL_LIBS@ \ @LIBXFCE4PANEL_LIBS@ \
@GTHREAD_LIBS@ \ @GTHREAD_LIBS@ \
@SOUP_LIBS@ \ @SOUP_LIBS@ \
......
...@@ -53,6 +53,7 @@ XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.16.0]) ...@@ -53,6 +53,7 @@ XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.16.0])
XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.16.0]) XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.16.0])
XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.16.0]) XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.16.0])
XDT_CHECK_PACKAGE([SOUP], [libsoup-2.4], [2.26.0]) XDT_CHECK_PACKAGE([SOUP], [libsoup-2.4], [2.26.0])
XDT_CHECK_PACKAGE([EXO], [exo-1], [0.5.0])
dnl ************************** dnl **************************
dnl *** Check for xsltproc *** dnl *** Check for xsltproc ***
......
/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
* Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib.h>
#include <glib-object.h>
#include <gio/gio.h>
#include <gtk/gtk.h>
#include <libxfce4util/libxfce4util.h>
#include "exo-job.h"
#define I_(string) (g_intern_static_string ((string)))
/**
* SECTION: exo-job
* @title: ExoJob
* @short_description: Base class for threaded/asynchronous jobs
* @include: exo/exo.h
* @see_also: <link linkend="ExoSimpleJob">ExoSimpleJob</link>
*
* <link linkend="ExoJob">ExoJob</link> is an abstract base class
* intended to wrap threaded/asynchronous operations (called jobs here).
* It was written because the ways of dealing with threads provided by
* GLib are not exactly object-oriented.
*
* It can be used to wrap any kind of long-running or possibly-blocking
* operation like file operations or communication with web services.
* The benefit of using <link linkend="ExoJob">ExoJob</link> is that one
* gets an object associated with each operation. After creating the job
* the caller can connect to signals like <link linkend="ExoJob::error">"error"
* </link> or <link linkend="ExoJob::percent">"percent"</link>. This
* design integrates very well with the usual object-oriented design of
* applications based on GObject.
**/
#define EXO_JOB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
EXO_TYPE_JOB, ExoJobPrivate))
/* Signal identifiers */
enum
{
ERROR,
FINISHED,
INFO_MESSAGE,
PERCENT,
LAST_SIGNAL,
};
typedef struct _ExoJobSignalData ExoJobSignalData;
static void exo_job_finalize (GObject *object);
static void exo_job_error (ExoJob *job,
GError *error);
static void exo_job_finished (ExoJob *job);
struct _ExoJobPrivate
{
GIOSchedulerJob *scheduler_job;
GCancellable *cancellable;
guint running : 1;
};
struct _ExoJobSignalData
{
gpointer instance;
GQuark signal_detail;
guint signal_id;
va_list var_args;
};
static guint job_signals[LAST_SIGNAL];
G_DEFINE_ABSTRACT_TYPE (ExoJob, exo_job, G_TYPE_OBJECT)
static void
exo_job_class_init (ExoJobClass *klass)
{
GObjectClass *gobject_class;
g_type_class_add_private (klass, sizeof (ExoJobPrivate));
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = exo_job_finalize;
klass->execute = NULL;
klass->error = NULL;
klass->finished = NULL;
klass->info_message = NULL;
klass->percent = NULL;
/**
* ExoJob::error:
* @job : an #ExoJob.
* @error : a #GError describing the cause.
*
* Emitted whenever an error occurs while executing the @job. This signal
* may not be emitted from within #ExoJob subclasses. If a subclass wants
* to emit an "error" signal (and thereby terminate the operation), it has
* to fill the #GError structure and abort from its execute() method.
* #ExoJob will automatically emit the "error" signal when the #GError is
* filled after the execute() method has finished.
*
* Callers interested in whether the @job was cancelled can connect to
* the "cancelled" signal of the #GCancellable returned from
* exo_job_get_cancellable().
**/
job_signals[ERROR] =
g_signal_new (I_("error"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_NO_HOOKS,
G_STRUCT_OFFSET (ExoJobClass, error),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1, G_TYPE_POINTER);
/**
* ExoJob::finished:
* @job : an #ExoJob.
*
* This signal will be automatically emitted once the @job finishes
* its execution, no matter whether @job completed successfully or
* was cancelled by the user. It may not be emitted by subclasses of
* #ExoJob as it is automatically emitted by #ExoJob after the execute()
* method has finished.
**/
job_signals[FINISHED] =
g_signal_new (I_("finished"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_NO_HOOKS,
G_STRUCT_OFFSET (ExoJobClass, finished),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* ExoJob::info-message:
* @job : an #ExoJob.
* @message : information to be displayed about @job.
*
* This signal is emitted to display information about the status of
* the @job. Examples of messages are "Preparing..." or "Cleaning up...".
*
* The @message is garanteed to contain valid UTF-8, so it can be
* displayed by #GtkWidget<!---->s out of the box.
**/
job_signals[INFO_MESSAGE] =
g_signal_new (I_("info-message"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_NO_HOOKS,
G_STRUCT_OFFSET (ExoJobClass, info_message),
NULL, NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1, G_TYPE_STRING);
/**
* ExoJob::percent:
* @job : an #ExoJob.
* @percent : the percentage of completeness.
*
* This signal is emitted to present the overall progress of the
* operation. The @percent value is garantied to be a value between
* 0.0 and 100.0.
**/
job_signals[PERCENT] =
g_signal_new (I_("percent"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_NO_HOOKS,
G_STRUCT_OFFSET (ExoJobClass, percent),
NULL, NULL,
g_cclosure_marshal_VOID__DOUBLE,
G_TYPE_NONE, 1, G_TYPE_DOUBLE);
}
static void
exo_job_init (ExoJob *job)
{
job->priv = EXO_JOB_GET_PRIVATE (job);
job->priv->cancellable = g_cancellable_new ();
job->priv->running = FALSE;
job->priv->scheduler_job = NULL;
}
static void
exo_job_finalize (GObject *object)
{
ExoJob *job = EXO_JOB (object);
if (job->priv->running)
exo_job_cancel (job);
g_object_unref (job->priv->cancellable);
(*G_OBJECT_CLASS (exo_job_parent_class)->finalize) (object);
}
/**
* exo_job_finish:
* @job : an #ExoJob.
* @result : the #GSimpleAsyncResult of the job.
* @error : return location for errors.
*
* Finishes the execution of an operation by propagating errors
* from the @result into @error.
*
* Returns: %TRUE if there was no error during the operation,
* %FALSE otherwise.
**/
static gboolean
exo_job_finish (ExoJob *job,
GSimpleAsyncResult *result,
GError **error)
{
g_return_val_if_fail (EXO_IS_JOB (job), FALSE);
g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
return !g_simple_async_result_propagate_error (result, error);
}
/**
* exo_job_async_ready:
* @object : an #ExoJob.
* @result : the #GAsyncResult of the job.
*
* This function is called by the #GIOScheduler at the end of the
* operation. It checks if there were errors during the operation
* and emits "error" and "finished" signals.
**/
static void
exo_job_async_ready (GObject *object,
GAsyncResult *result)
{
ExoJob *job = EXO_JOB (object);
GError *error = NULL;
g_return_if_fail (EXO_IS_JOB (job));
g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result));
if (!exo_job_finish (job, G_SIMPLE_ASYNC_RESULT (result), &error))
{
g_assert (error != NULL);
/* don't treat cancellation as an error */
if (error->code != G_IO_ERROR_CANCELLED)
exo_job_error (job, error);
g_error_free (error);
}
exo_job_finished (job);
job->priv->running = FALSE;
}
/**
* exo_job_scheduler_job_func:
* @scheduler_job : the #GIOSchedulerJob running the operation.
* @cancellable : the #GCancellable associated with the job.
* @user_data : a #GSimpleAsyncResult.
*
* This function is called by the #GIOScheduler to execute the
* operation associated with the job. It basically calls the
* execute() function of #ExoJobClass.
*
* Returns: %FALSE, to stop the thread at the end of the operation.
**/
static gboolean
exo_job_scheduler_job_func (GIOSchedulerJob *scheduler_job,
GCancellable *cancellable,
gpointer user_data)
{
GSimpleAsyncResult *result = user_data;
ExoJob *job;
GError *error = NULL;
gboolean success;
job = g_simple_async_result_get_op_res_gpointer (result);
job->priv->scheduler_job = scheduler_job;
success = (*EXO_JOB_GET_CLASS (job)->execute) (job, &error);
/* TODO why was this necessary again? GIO uses this too, for some reason. */
g_io_scheduler_job_send_to_mainloop (scheduler_job, (GSourceFunc) gtk_false,
NULL, NULL);
if (!success)
{
g_simple_async_result_set_from_error (result, error);
g_error_free (error);
}
g_simple_async_result_complete_in_idle (result);
return FALSE;
}
/**
* exo_job_emit_valist_in_mainloop:
* @user_data : an #ExoJobSignalData.
*
* Called from the main loop of the application to emit the signal
* specified by the @user_data.
*
* Returns: %FALSE, to keep the function from being called
* multiple times in a row.
**/
static gboolean
exo_job_emit_valist_in_mainloop (gpointer user_data)
{
ExoJobSignalData *data = user_data;
g_signal_emit_valist (data->instance, data->signal_id, data->signal_detail,
data->var_args);
return FALSE;
}
/**
* exo_job_emit_valist:
* @job : an #ExoJob.
* @signal_id : the signal id.
* @signal_detail : the signal detail.
* @var_args : a list of parameters to be passed to the signal,
* followed by a location for the return value. If the
* return type of the signal is G_TYPE_NONE, the return
* value location can be omitted.
*
* Sends a the signal with the given @signal_id and @signal_detail to the
* main loop of the application and waits for listeners to handle it.
**/
static void
exo_job_emit_valist (ExoJob *job,
guint signal_id,
GQuark signal_detail,
va_list var_args)
{
ExoJobSignalData data;
g_return_if_fail (EXO_IS_JOB (job));
g_return_if_fail (job->priv->scheduler_job != NULL);
data.instance = job;
data.signal_id = signal_id;
data.signal_detail = signal_detail;
/* copy the variable argument list */
G_VA_COPY (data.var_args, var_args);
/* emit the signal in the main loop */
g_io_scheduler_job_send_to_mainloop (job->priv->scheduler_job,
exo_job_emit_valist_in_mainloop,
&data, NULL);
}
/**
* exo_job_error:
* @job : an #ExoJob.
* @error : a #GError.
*
* Emits the "error" signal and passes the @error to it so that the
* application can handle it (e.g. by displaying an error dialog).
*
* This function should never be called from outside the application's
* main loop.
**/
static void
exo_job_error (ExoJob *job,
GError *error)
{
g_return_if_fail (EXO_IS_JOB (job));
g_return_if_fail (error != NULL);
g_signal_emit (job, job_signals[ERROR], 0, error);
}
/**
* exo_job_finished:
* @job : an #ExoJob.
*
* Emits the "finished" signal to notify listeners of the end of the
* operation.
*
* This function should never be called from outside the application's
* main loop.
**/
static void
exo_job_finished (ExoJob *job)
{
g_return_if_fail (EXO_IS_JOB (job));
g_signal_emit (job, job_signals[FINISHED], 0);
}
/**
* exo_job_launch:
* @job : an #ExoJob.
*
* This functions schedules the @job to be run as soon as possible, in
* a separate thread. The caller can connect to signals of the @job prior
* or after this call in order to be notified on errors, progress updates
* and the end of the operation.
*
* Returns: the @job itself.
**/
ExoJob *
exo_job_launch (ExoJob *job)
{
GSimpleAsyncResult *result;
g_return_val_if_fail (EXO_IS_JOB (job), NULL);
g_return_val_if_fail (!job->priv->running, NULL);
g_return_val_if_fail (EXO_JOB_GET_CLASS (job)->execute != NULL, NULL);
/* mark the job as running */
job->priv->running = TRUE;
result = g_simple_async_result_new (G_OBJECT (job),
(GAsyncReadyCallback) exo_job_async_ready,
NULL, exo_job_launch);
g_simple_async_result_set_op_res_gpointer (result, g_object_ref (job),
(GDestroyNotify) g_object_unref);
g_io_scheduler_push_job (exo_job_scheduler_job_func, result,
(GDestroyNotify) g_object_unref,
G_PRIORITY_HIGH, job->priv->cancellable);
return job;
}
/**
* exo_job_cancel:
* @job : a #ExoJob.
*
* Attempts to cancel the operation currently performed by @job. Even
* after the cancellation of @job, it may still emit signals, so you
* must take care of disconnecting all handlers appropriately if you
* cannot handle signals after cancellation.
*
* Calling this function when the @job has not been launched yet or
* when it has already finished will have no effect.
**/
void
exo_job_cancel (ExoJob *job)
{
g_return_if_fail (EXO_IS_JOB (job));
if (job->priv->running)
g_cancellable_cancel (job->priv->cancellable);
}
/**
* exo_job_is_cancelled:
* @job : a #ExoJob.
*
* Checks whether @job was previously cancelled
* by a call to exo_job_cancel().
*
* Returns: %TRUE if @job is cancelled.
**/
gboolean
exo_job_is_cancelled (const ExoJob *job)
{
g_return_val_if_fail (EXO_IS_JOB (job), FALSE);
return g_cancellable_is_cancelled (job->priv->cancellable);
}
/**
* exo_job_get_cancellable:
* @job : an #ExoJob.
*
* Returns the #GCancellable that can be used to cancel the @job.
*
* Returns: the #GCancellable associated with the @job. It
* is owned by the @job and must not be released.
**/
GCancellable *
exo_job_get_cancellable (const ExoJob *job)
{
g_return_val_if_fail (EXO_IS_JOB (job), NULL);
return job->priv->cancellable;
}
/**
* exo_job_set_error_if_cancelled:
* @job : an #ExoJob.
* @error : error to be set if the @job was cancelled.
*
* Sets the @error if the @job was cancelled. This is a convenience
* function that is equivalent to
* <informalexample><programlisting>
* GCancellable *cancellable;
* cancellable = exo_job_get_cancllable (job);
* g_cancellable_set_error_if_cancelled (cancellable, error);
* </programlisting></informalexample>
*
* Returns: %TRUE if the job was cancelled and @error is now set,
* %FALSE otherwise.
**/
gboolean
exo_job_set_error_if_cancelled (ExoJob *job,
GError **error)
{
g_return_val_if_fail (EXO_IS_JOB (job), FALSE);
return g_cancellable_set_error_if_cancelled (job->priv->cancellable, error);
}
/**
* exo_job_emit:
* @job : an #ExoJob.
* @signal_id : the signal id.
* @signal_detail : the signal detail.
* @Varargs : a list of parameters to be passed to the signal,
* followed by a location for the return value. If the
* return type of the signal is G_TYPE_NONE, the return
* value location can be omitted.
*
* Sends the signal with @signal_id and @signal_detail to the application's
* main loop and waits for listeners to handle it.
**/
void
exo_job_emit (ExoJob *job,
guint signal_id,
GQuark signal_detail,
...)
{
va_list var_args;
g_return_if_fail (EXO_IS_JOB (job));
va_start (var_args, signal_detail);
exo_job_emit_valist (job, signal_id, signal_detail, var_args);
va_end (var_args);
}
/**
* exo_job_info_message:
* @job : an #ExoJob.
* @format : a format string.
* @Varargs : parameters for the format string.
*
* Generates and emits an "info-message" signal and sends it to the
* application's main loop.
**/
void
exo_job_info_message (ExoJob *job,
const gchar *format,
...)
{
va_list var_args;
gchar *message;
g_return_if_fail (EXO_IS_JOB (job));
g_return_if_fail (format != NULL);
va_start (var_args, format);
message = g_strdup_vprintf (format, var_args);
exo_job_emit (job, job_signals[INFO_MESSAGE], 0, message);
g_free (message);
va_end (var_args);
}
/**
* exo_job_percent:
* @job : an #ExoJob.
* @percent : percentage of completeness of the operation.
*
* Emits a "percent" signal and sends it to the application's main
* loop. Also makes sure that @percent is between 0.0 and 100.0.
**/
void
exo_job_percent (ExoJob *job,
gdouble percent)
{
g_return_if_fail (EXO_IS_JOB (job));
percent = CLAMP (percent, 0.0, 100.0);
exo_job_emit (job, job_signals[PERCENT], 0, percent);
}
/**
* exo_job_send_to_mainloop:
* @job : an #ExoJob.
* @func : a #GSourceFunc callback that will be called in the main thread.
* @user_data : data to pass to @func.
* @destroy_notify : a #GDestroyNotify for @user_data, or %NULL.
*
* This functions schedules @func to be run in the main loop (main thread),
* waiting for the result (and blocking the job in the meantime).
*
* Returns: The return value of @func.
**/
gboolean
exo_job_send_to_mainloop (ExoJob *job,
GSourceFunc func,
gpointer user_data,
GDestroyNotify destroy_notify)
{
g_return_val_if_fail (EXO_IS_JOB (job), FALSE);
return g_io_scheduler_job_send_to_mainloop (job->priv->scheduler_job, func, user_data,
destroy_notify);
}
/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
* Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __EXO_JOB_H__
#define __EXO_JOB_H__
#include <gio/gio.h>
G_BEGIN_DECLS
#define EXO_TYPE_JOB (exo_job_get_type ())
#define EXO_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXO_TYPE_JOB, ExoJob))
#define EXO_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXO_TYPE_JOB, ExoJobClass))
#define EXO_IS_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXO_TYPE_JOB))
#define EXO_IS_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EXO_TYPE_JOB)
#define EXO_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EXO_TYPE_JOB, ExoJobClass))
typedef struct _ExoJobPrivate ExoJobPrivate;
typedef struct _ExoJobClass ExoJobClass;
typedef struct _ExoJob ExoJob;
struct _ExoJobClass
{
GObjectClass __parent__;
/* virtual methods */
gboolean (*execute) (ExoJob *job,
GError **error);
/* signals */
void (*error) (ExoJob *job,
GError *error);
void (*finished) (ExoJob *job);
void (*info_message) (ExoJob *job,
const gchar *message);
void (*percent) (ExoJob *job,
gdouble percent);
};
/**
* ExoJob:
*
* The #ExoJob struct contains only private fields and should not be
* directly accessed.
**/
struct _ExoJob
{
GObject __parent__;
/*< private >*/
ExoJobPrivate *priv;
};
GType exo_job_get_type (void) G_GNUC_CONST;
ExoJob *exo_job_launch (ExoJob *job);
void exo_job_cancel (ExoJob *job);
gboolean exo_job_is_cancelled (const ExoJob *job);
GCancellable *exo_job_get_cancellable (const ExoJob *job);
gboolean exo_job_set_error_if_cancelled (ExoJob *job,
GError **error);
void exo_job_emit (ExoJob *job,
guint signal_id,
GQuark signal_detail,
...);
void exo_job_info_message (ExoJob *job,
const gchar *format,
...);
void exo_job_percent (ExoJob *job,
gdouble percent);
gboolean exo_job_send_to_mainloop (ExoJob *job,
GSourceFunc func,
gpointer user_data,
GDestroyNotify destroy_notify);
G_END_DECLS
#endif /* !__EXO_JOB_H__ */
/* $Id$ */
/*-
* Copyright (c) 2006 Benedikt Meurer <benny@xfce.org>
* Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <gobject/gvaluecollector.h>
#include "exo-job.h"
#include "exo-simple-job.h"
/**
* SECTION: exo-simple-job
* @title: ExoSimpleJob
* @short_description: Simple interface to execute functions asynchronously
* @include: exo/exo.h
* @see_also: <link linkend="ExoJob">ExoJob</link>
*
* <link linkend="ExoSimpleJob">ExoSimpleJob</link> can be used to execute
* functions asynchronously in an #ExoJob wrapper object. It is easier to
* use than the #GThread system and provides basic signals to follow the
* progress of an operation.
**/
static void exo_simple_job_finalize (GObject *object);
static gboolean exo_simple_job_execute (ExoJob *job,
GError **error);
struct _ExoSimpleJobClass
{
ExoJobClass __parent__;
};
/**
* ExoSimpleJob:
*
* The #ExoSimpleJob struct contains only private fields and should not be
* directly accessed.
**/
struct _ExoSimpleJob
{
ExoSimpleJobFunc func;
GValueArray *param_values;
ExoJob __parent__;
};
G_DEFINE_TYPE (ExoSimpleJob, exo_simple_job, EXO_TYPE_JOB)
static void
exo_simple_job_class_init (ExoSimpleJobClass *klass)
{
ExoJobClass *exojob_class;
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = exo_simple_job_finalize;
exojob_class = EXO_JOB_CLASS (klass);
exojob_class->execute = exo_simple_job_execute;
}
static void
exo_simple_job_init (ExoSimpleJob *simple_job)
{
}
static void
exo_simple_job_finalize (GObject *object)
{
ExoSimpleJob *simple_job = EXO_SIMPLE_JOB (object);
/* release the param values */
g_value_array_free (simple_job->param_values);
(*G_OBJECT_CLASS (exo_simple_job_parent_class)->finalize) (object);
}
static gboolean
exo_simple_job_execute (ExoJob *job,
GError **error)
{
ExoSimpleJob *simple_job = EXO_SIMPLE_JOB (job);
gboolean success = TRUE;
GError *err = NULL;
g_return_val_if_fail (EXO_IS_SIMPLE_JOB (job), FALSE);
g_return_val_if_fail (simple_job->func != NULL, FALSE);
/* try to execute the job using the supplied function */
success = (*simple_job->func) (job, simple_job->param_values, &err);
if (!success)
{
g_assert (err != NULL || exo_job_is_cancelled (job));
/* set error if the job was cancelled. otherwise just propagate
* the results of the processing function */
if (exo_job_set_error_if_cancelled (job, error))
{
g_clear_error (&err);
}
else
{
if (err != NULL)
g_propagate_error (error, err);
}
return FALSE;
}
else
return TRUE;
}
/**
* exo_simple_job_launch:
* @func : the #ExoSimpleJobFunc to execute the job.
* @n_param_values : the number of parameters to pass to the @func.
* @... : a list of #GType and parameter pairs (exactly
* @n_param_values pairs) that are passed to @func.
*
* Allocates a new #ExoJob which executes the specified @func with
* the specified parameters.
*
* An example could be:
*
* <informalexample><programlisting>
* static gboolean
* list_directory (ExoJob *job,
* GValueArray *param_values,
* GError **error)
* {
* GFileEnumerator *enumerator;
* GFileInfo *info;
* GError *err = NULL;
* GFile *directory;
*
* if (exo_job_set_error_if_cancelled (EXO_JOB (job), error))
* return FALSE;
*
* directory = g_value_get_object (g_value_array_get_nth (param_values, 0));
*
* enumerator = g_file_enumerate_children (directory,
* "standard::display-name",
* G_FILE_QUERY_INFO_NONE,
* exo_job_get_cancellable (job),
* &err);
*
* if (err != NULL)
* {
* g_propagate_error (error, err);
* return FALSE;
* }
*
* while (TRUE)
* {
* info = g_file_enumerator_next_file (enumerator,
* exo_job_get_cancellable (job),
* &err);
*
* if (info == NULL)
* break;
*
* exo_job_info_message (job, _("Child: %s"),
* g_file_info_get_display_name (info));
*
* g_object_unref (info);
* }
*
* g_object_unref (enumerator);
*
* if (err != NULL)
* {
* g_propagate_error (error, err);
* return FALSE;
* }
* else
* {
* return TRUE;
* }
* }
*
* ...
*
* GFile *file = g_file_new_for_path ("/home/user");
* ExoJob *job = exo_simple_job_launch (list_directory, 1, G_TYPE_FILE, file);
* g_signal_connect (job, "info-message", G_CALLBACK (update_some_widget), widget);
* g_signal_connect (job, "finished", G_CALLBACK (unref_the_job_object), NULL);
* </programlisting></informalexample>
*
* The caller is responsible to release the returned #ExoJob object
* using g_object_unref() when no longer needed.
*
* Returns: the launched #ExoJob.
**/
ExoJob*
exo_simple_job_launch (ExoSimpleJobFunc func,
guint n_param_values,
...)
{
ExoSimpleJob *simple_job;
va_list var_args;
GValue value = { 0, };
gchar *error_message;
guint n;
/* allocate and initialize the simple job */
simple_job = g_object_new (EXO_TYPE_SIMPLE_JOB, NULL);
simple_job->func = func;
simple_job->param_values = g_value_array_new (n_param_values);
/* collect the parameters */
va_start (var_args, n_param_values);
for (n = 0; n < n_param_values; ++n)
{
/* initialize the value to hold the next parameter */
g_value_init (&value, va_arg (var_args, GType));
/* collect the value from the stack */
G_VALUE_COLLECT (&value, var_args, 0, &error_message);
/* check if an error occurred */
if (G_UNLIKELY (error_message != NULL))
{
g_error ("%s: %s", G_STRLOC, error_message);
g_free (error_message);
}
g_value_array_insert (simple_job->param_values, n, &value);
g_value_unset (&value);
}
va_end (var_args);
/* launch the job */
return exo_job_launch (EXO_JOB (simple_job));
}
/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
* Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __EXO_SIMPLE_JOB_H__
#define __EXO_SIMPLE_JOB_H__
#include "exo-job.h"
G_BEGIN_DECLS
/**
* ExoSimpleJobFunc:
* @job : an #ExoJob.
* @param_values : a #GValueArray of the #GValue<!---->s passed to
* exo_simple_job_launch().
* @error : return location for errors.
*
* Used by the #ExoSimpleJob to process the @job. See exo_simple_job_launch()
* for further details.
*
* Returns: %TRUE on success, %FALSE in case of an error.
**/
typedef gboolean (*ExoSimpleJobFunc) (ExoJob *job,
GValueArray *param_values,
GError **error);
#define EXO_TYPE_SIMPLE_JOB (exo_simple_job_get_type ())
#define EXO_SIMPLE_JOB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXO_TYPE_SIMPLE_JOB, ExoSimpleJob))
#define EXO_SIMPLE_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EXO_TYPE_SIMPLE_JOB, ExoSimpleJobClass))
#define EXO_IS_SIMPLE_JOB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EXO_TYPE_SIMPLE_JOB))
#define EXO_IS_SIMPLE_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EXO_TYPE_SIMPLE_JOB))
#define EXO_SIMPLE_JOB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EXO_TYPE_SIMPLE_JOB, ExoSimpleJobClass))
typedef struct _ExoSimpleJobClass ExoSimpleJobClass;
typedef struct _ExoSimpleJob ExoSimpleJob;
GType exo_simple_job_get_type (void) G_GNUC_CONST;
ExoJob *exo_simple_job_launch (ExoSimpleJobFunc func,
guint n_param_values,
...) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
G_END_DECLS
#endif /* !__EXO_SIMPLE_JOB_H__ */
...@@ -27,8 +27,8 @@ ...@@ -27,8 +27,8 @@
#include <gio/gio.h> #include <gio/gio.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <libxfce4util/libxfce4util.h> #include <libxfce4util/libxfce4util.h>
#include <exo/exo.h>
#include "exo-simple-job.h"
#include "screenshooter-marshal.h" #include "screenshooter-marshal.h"
G_BEGIN_DECLS G_BEGIN_DECLS
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment