[gnome-builder] pausable: add object helper for pausable operations
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] pausable: add object helper for pausable operations
- Date: Tue, 5 Sep 2017 08:36:39 +0000 (UTC)
commit 5bbe3df23537bf84c2acbad7f1cc5ec70b512405
Author: Christian Hergert <chergert redhat com>
Date: Tue Sep 5 01:15:07 2017 -0700
pausable: add object helper for pausable operations
This gives us something we can let the context own to describe pausable
operations. We can then integrate it into the popover so that the user
has an escape hatch on expensive background operations.
libide/ide-context.c | 74 ++++++++++++++-
libide/ide-context.h | 4 +
libide/ide-internal.h | 1 +
libide/ide-pausable.c | 251 +++++++++++++++++++++++++++++++++++++++++++++++++
libide/ide-pausable.h | 42 ++++++++
libide/ide-types.h | 2 +
libide/ide.h | 1 +
libide/meson.build | 12 ++-
8 files changed, 379 insertions(+), 8 deletions(-)
---
diff --git a/libide/ide-context.c b/libide/ide-context.c
index 72e0a78..66d877e 100644
--- a/libide/ide-context.c
+++ b/libide/ide-context.c
@@ -25,6 +25,7 @@
#include "ide-debug.h"
#include "ide-global.h"
#include "ide-internal.h"
+#include "ide-pausable.h"
#include "ide-service.h"
#include "buffers/ide-buffer-manager.h"
@@ -72,6 +73,7 @@ struct _IdeContext
IdeDeviceManager *device_manager;
IdeDoap *doap;
IdeDocumentation *documentation;
+ GListStore *pausables;
GtkRecentManager *recent_manager;
IdeRunManager *run_manager;
IdeRuntimeManager *runtime_manager;
@@ -499,11 +501,11 @@ ide_context_loaded (IdeContext *self)
static void
ide_context_dispose (GObject *object)
{
+ IdeContext *self = (IdeContext *)object;
+
IDE_ENTRY;
- /*
- * TODO: Shutdown services.
- */
+ g_list_store_remove_all (self->pausables);
G_OBJECT_CLASS (ide_context_parent_class)->dispose (object);
@@ -518,6 +520,7 @@ ide_context_finalize (GObject *object)
IDE_ENTRY;
g_clear_object (&self->services);
+ g_clear_object (&self->pausables);
g_clear_pointer (&self->build_system_hint, g_free);
g_clear_pointer (&self->services_by_gtype, g_hash_table_unref);
@@ -769,6 +772,8 @@ ide_context_init (IdeContext *self)
g_mutex_init (&self->unload_mutex);
+ self->pausables = g_list_store_new (IDE_TYPE_PAUSABLE);
+
self->recent_manager = g_object_ref (gtk_recent_manager_get_default ());
self->root_build_dir = g_build_filename (g_get_user_cache_dir (),
@@ -2337,3 +2342,66 @@ ide_context_get_debug_manager (IdeContext *self)
return self->debug_manager;
}
+
+/**
+ * ide_context_add_pausable:
+ * @self: an #IdeContext
+ * @pausable: an #IdePausable
+ *
+ * Adds a pausable which can be used to associate pausable actions with the
+ * context. Various UI in Builder may use this to present pausable actions to
+ * the user.
+ *
+ * Since: 3.26
+ */
+void
+ide_context_add_pausable (IdeContext *self,
+ IdePausable *pausable)
+{
+ g_return_if_fail (IDE_IS_CONTEXT (self));
+ g_return_if_fail (IDE_IS_PAUSABLE (pausable));
+
+ g_list_store_append (self->pausables, pausable);
+}
+
+/**
+ * ide_context_remove_pausable:
+ * @self: an #IdeContext
+ * @pausable: an #IdePausable
+ *
+ * Remove a previously registered #IdePausable.
+ *
+ * Since: 3.26
+ */
+void
+ide_context_remove_pausable (IdeContext *self,
+ IdePausable *pausable)
+{
+ guint n_items;
+
+ g_return_if_fail (IDE_IS_CONTEXT (self));
+ g_return_if_fail (IDE_IS_PAUSABLE (pausable));
+
+ n_items = g_list_model_get_n_items (G_LIST_MODEL (self->pausables));
+
+ for (guint i = 0; i < n_items; i++)
+ {
+ g_autoptr(IdePausable) item = NULL;
+
+ item = g_list_model_get_item (G_LIST_MODEL (self->pausables), i);
+
+ if (item == pausable)
+ {
+ g_list_store_remove (self->pausables, i);
+ break;
+ }
+ }
+}
+
+GListModel *
+_ide_context_get_pausables (IdeContext *self)
+{
+ g_return_val_if_fail (IDE_IS_CONTEXT (self), NULL);
+
+ return G_LIST_MODEL (self->pausables);
+}
diff --git a/libide/ide-context.h b/libide/ide-context.h
index 474bb0f..3231640 100644
--- a/libide/ide-context.h
+++ b/libide/ide-context.h
@@ -76,6 +76,10 @@ void ide_context_restore_async (IdeContext
gboolean ide_context_restore_finish (IdeContext *self,
GAsyncResult *result,
GError **error);
+void ide_context_add_pausable (IdeContext *self,
+ IdePausable *pausable);
+void ide_context_remove_pausable (IdeContext *self,
+ IdePausable *pausable);
void ide_context_hold (IdeContext *self);
void ide_context_hold_for_object (IdeContext *self,
gpointer instance);
diff --git a/libide/ide-internal.h b/libide/ide-internal.h
index a3d9a7d..5654735 100644
--- a/libide/ide-internal.h
+++ b/libide/ide-internal.h
@@ -41,6 +41,7 @@ void _ide_configuration_set_prebuild (IdeConfiguration
void _ide_configuration_set_postbuild (IdeConfiguration *self,
IdeBuildCommandQueue *postbuild);
gboolean _ide_context_is_restoring (IdeContext *self);
+GListModel *_ide_context_get_pausables (IdeContext *self);
const gchar *_ide_file_get_content_type (IdeFile *self);
GtkSourceFile *_ide_file_set_content_type (IdeFile *self,
const gchar *content_type);
diff --git a/libide/ide-pausable.c b/libide/ide-pausable.c
new file mode 100644
index 0000000..fc5d882
--- /dev/null
+++ b/libide/ide-pausable.c
@@ -0,0 +1,251 @@
+/* ide-pausable.c
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "ide-pausable"
+
+#include "ide-pausable.h"
+
+struct _IdePausable
+{
+ GObject parent_instance;
+
+ gchar *title;
+ gchar *subtitle;
+
+ guint paused : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_TITLE,
+ PROP_SUBTITLE,
+ PROP_PAUSED,
+ N_PROPS
+};
+
+enum {
+ PAUSED,
+ UNPAUSED,
+ N_SIGNALS
+};
+
+G_DEFINE_TYPE (IdePausable, ide_pausable, G_TYPE_OBJECT)
+
+static GParamSpec *properties [N_PROPS];
+static guint signals [N_SIGNALS];
+
+static void
+ide_pausable_finalize (GObject *object)
+{
+ IdePausable *self = (IdePausable *)object;
+
+ g_clear_pointer (&self->title, g_free);
+ g_clear_pointer (&self->subtitle, g_free);
+
+ G_OBJECT_CLASS (ide_pausable_parent_class)->finalize (object);
+}
+
+static void
+ide_pausable_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ IdePausable *self = IDE_PAUSABLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_TITLE:
+ g_value_set_string (value, self->title);
+ break;
+
+ case PROP_SUBTITLE:
+ g_value_set_string (value, self->subtitle);
+ break;
+
+ case PROP_PAUSED:
+ g_value_set_boolean (value, ide_pausable_get_paused (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_pausable_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ IdePausable *self = IDE_PAUSABLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_TITLE:
+ ide_pausable_set_title (self, g_value_get_string (value));
+ break;
+
+ case PROP_SUBTITLE:
+ ide_pausable_set_subtitle (self, g_value_get_string (value));
+ break;
+
+ case PROP_PAUSED:
+ ide_pausable_set_paused (self, g_value_get_boolean (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ide_pausable_class_init (IdePausableClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ide_pausable_finalize;
+ object_class->get_property = ide_pausable_get_property;
+ object_class->set_property = ide_pausable_set_property;
+
+ properties [PROP_PAUSED] =
+ g_param_spec_boolean ("paused", NULL, NULL, FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties [PROP_TITLE] =
+ g_param_spec_string ("title", NULL, NULL, NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ properties [PROP_SUBTITLE] =
+ g_param_spec_string ("subtitle", NULL, NULL, NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ signals [PAUSED] =
+ g_signal_new ("paused",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals [UNPAUSED] =
+ g_signal_new ("unpaused",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+ide_pausable_init (IdePausable *self)
+{
+}
+
+IdePausable *
+ide_pausable_new (void)
+{
+ return g_object_new (IDE_TYPE_PAUSABLE, NULL);
+}
+
+const gchar *
+ide_pausable_get_title (IdePausable *self)
+{
+ g_return_val_if_fail (IDE_IS_PAUSABLE (self), NULL);
+
+ return self->title;
+}
+
+void
+ide_pausable_set_title (IdePausable *self,
+ const gchar *title)
+{
+ if (g_strcmp0 (title, self->title) != 0)
+ {
+ g_free (self->title);
+ self->title = g_strdup (title);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]);
+ }
+}
+
+const gchar *
+ide_pausable_get_subtitle (IdePausable *self)
+{
+ g_return_val_if_fail (IDE_IS_PAUSABLE (self), NULL);
+
+ return self->subtitle;
+}
+
+void
+ide_pausable_set_subtitle (IdePausable *self,
+ const gchar *subtitle)
+{
+ if (g_strcmp0 (subtitle, self->subtitle) != 0)
+ {
+ g_free (self->subtitle);
+ self->subtitle = g_strdup (subtitle);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SUBTITLE]);
+ }
+}
+
+gboolean
+ide_pausable_get_paused (IdePausable *self)
+{
+ g_return_val_if_fail (IDE_IS_PAUSABLE (self), FALSE);
+
+ return self->paused;
+}
+
+void
+ide_pausable_set_paused (IdePausable *self,
+ gboolean paused)
+{
+ g_return_if_fail (IDE_IS_PAUSABLE (self));
+
+ paused = !!paused;
+
+ if (self->paused != paused)
+ {
+ self->paused = paused;
+
+ if (paused)
+ g_signal_emit (self, signals [PAUSED], 0);
+ else
+ g_signal_emit (self, signals [UNPAUSED], 0);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_PAUSED]);
+ }
+}
+
+void
+ide_pausable_pause (IdePausable *self)
+{
+ g_return_if_fail (IDE_IS_PAUSABLE (self));
+
+ ide_pausable_set_paused (self, TRUE);
+}
+
+void
+ide_pausable_unpause (IdePausable *self)
+{
+ g_return_if_fail (IDE_IS_PAUSABLE (self));
+
+ ide_pausable_set_paused (self, FALSE);
+}
diff --git a/libide/ide-pausable.h b/libide/ide-pausable.h
new file mode 100644
index 0000000..b9b669f
--- /dev/null
+++ b/libide/ide-pausable.h
@@ -0,0 +1,42 @@
+/* ide-pausable.h
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_PAUSABLE (ide_pausable_get_type())
+
+G_DECLARE_FINAL_TYPE (IdePausable, ide_pausable, IDE, PAUSABLE, GObject)
+
+IdePausable *ide_pausable_new (void);
+gboolean ide_pausable_get_paused (IdePausable *self);
+void ide_pausable_set_paused (IdePausable *self,
+ gboolean paused);
+void ide_pausable_pause (IdePausable *self);
+void ide_pausable_unpause (IdePausable *self);
+const gchar *ide_pausable_get_title (IdePausable *self);
+void ide_pausable_set_title (IdePausable *self,
+ const gchar *title);
+const gchar *ide_pausable_get_subtitle (IdePausable *self);
+void ide_pausable_set_subtitle (IdePausable *self,
+ const gchar *subtitle);
+
+G_END_DECLS
diff --git a/libide/ide-types.h b/libide/ide-types.h
index 0661c15..32f0f60 100644
--- a/libide/ide-types.h
+++ b/libide/ide-types.h
@@ -84,6 +84,8 @@ typedef struct _IdeIndenter IdeIndenter;
typedef struct _IdeObject IdeObject;
+typedef struct _IdePausable IdePausable;
+
typedef struct _IdeProgress IdeProgress;
typedef struct _IdeProject IdeProject;
diff --git a/libide/ide.h b/libide/ide.h
index 71a52b7..421f901 100644
--- a/libide/ide.h
+++ b/libide/ide.h
@@ -33,6 +33,7 @@ G_BEGIN_DECLS
#include "ide-global.h"
#include "ide-macros.h"
#include "ide-object.h"
+#include "ide-pausable.h"
#include "ide-service.h"
#include "ide-version.h"
diff --git a/libide/meson.build b/libide/meson.build
index 72b6d0f..d63e58e 100644
--- a/libide/meson.build
+++ b/libide/meson.build
@@ -49,13 +49,14 @@ libide_enums = gnome.mkenums('ide-enums',
)
libide_public_headers = [
+ 'ide.h',
'ide-context.h',
'ide-global.h',
'ide-macros.h',
'ide-object.h',
+ 'ide-pausable.h',
'ide-service.h',
'ide-types.h',
- 'ide.h',
'application/ide-application-addin.h',
'application/ide-application-credits.h',
'application/ide-application-tool.h',
@@ -271,6 +272,11 @@ libide_icons_resources = gnome.compile_resources('ide-icons-resources',
)
libide_public_sources = [
+ 'ide.c',
+ 'ide-context.c',
+ 'ide-object.c',
+ 'ide-pausable.c',
+ 'ide-service.c',
'application/ide-application-addin.c',
'application/ide-application-tool.c',
'application/ide-application.c',
@@ -344,10 +350,6 @@ libide_public_sources = [
'highlighting/ide-highlight-engine.c',
'highlighting/ide-highlight-index.c',
'highlighting/ide-highlighter.c',
- 'ide-context.c',
- 'ide-object.c',
- 'ide-service.c',
- 'ide.c',
'langserv/ide-langserv-client.c',
'langserv/ide-langserv-completion-provider.c',
'langserv/ide-langserv-diagnostic-provider.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]