[gnome-builder] plugins/vcsui: port to GTK 4
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] plugins/vcsui: port to GTK 4
- Date: Tue, 12 Jul 2022 06:39:20 +0000 (UTC)
commit f9ea46184667753a3752ade77bba8c3de1a8d108
Author: Christian Hergert <chergert redhat com>
Date: Mon Jul 11 23:28:40 2022 -0700
plugins/vcsui: port to GTK 4
- Remove libdazzle usage
- Add new clone page to greeter
- Add --greeter command line option w/ application addin
- Wire up new GSV variable API
- Add switcher popover (but dont actually switch yet, still more work
to be done before release).
- Add workspace addin to add switcher
- Update .plugin
src/plugins/vcsui/gbp-vcsui-application-addin.c | 117 +++++++
src/plugins/vcsui/gbp-vcsui-application-addin.h | 31 ++
src/plugins/vcsui/gbp-vcsui-clone-page.c | 444 ++++++++++++++++++++++++
src/plugins/vcsui/gbp-vcsui-clone-page.h | 36 ++
src/plugins/vcsui/gbp-vcsui-clone-page.ui | 303 ++++++++++++++++
src/plugins/vcsui/gbp-vcsui-editor-page-addin.c | 22 +-
src/plugins/vcsui/gbp-vcsui-switcher-popover.c | 244 +++++++++++++
src/plugins/vcsui/gbp-vcsui-switcher-popover.h | 38 ++
src/plugins/vcsui/gbp-vcsui-switcher-popover.ui | 151 ++++++++
src/plugins/vcsui/gbp-vcsui-tree-addin.c | 22 +-
src/plugins/vcsui/gbp-vcsui-workbench-addin.c | 16 +-
src/plugins/vcsui/gbp-vcsui-workspace-addin.c | 194 +++++++++++
src/plugins/vcsui/gbp-vcsui-workspace-addin.h | 31 ++
src/plugins/vcsui/meson.build | 6 +-
src/plugins/vcsui/vcsui-plugin.c | 9 +
src/plugins/vcsui/vcsui.gresource.xml | 2 +
src/plugins/vcsui/vcsui.plugin | 7 +-
17 files changed, 1642 insertions(+), 31 deletions(-)
---
diff --git a/src/plugins/vcsui/gbp-vcsui-application-addin.c b/src/plugins/vcsui/gbp-vcsui-application-addin.c
new file mode 100644
index 000000000..a874573b8
--- /dev/null
+++ b/src/plugins/vcsui/gbp-vcsui-application-addin.c
@@ -0,0 +1,117 @@
+/* gbp-vcsui-application-addin.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-vcsui-application-addin"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <libide-greeter.h>
+
+#include "gbp-vcsui-application-addin.h"
+#include "gbp-vcsui-clone-page.h"
+
+struct _GbpVcsuiApplicationAddin
+{
+ GObject parent_instance;
+};
+
+static void
+gbp_vcsui_application_addin_handle_command_line (IdeApplicationAddin *addin,
+ IdeApplication *app,
+ GApplicationCommandLine *cmdline)
+{
+ g_auto(GStrv) argv = NULL;
+ GVariantDict *dict;
+ const char *clone_uri = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_VCSUI_APPLICATION_ADDIN (addin));
+ g_assert (IDE_IS_APPLICATION (app));
+ g_assert (G_IS_APPLICATION_COMMAND_LINE (cmdline));
+
+ dict = g_application_command_line_get_options_dict (cmdline);
+ argv = ide_application_get_argv (app, cmdline);
+
+ /*
+ * If the --clone=URI option was provided, switch the greeter to the
+ * clone page and begin cloning.
+ */
+ if (dict != NULL && g_variant_dict_lookup (dict, "clone", "&s", &clone_uri))
+ {
+ IdeGreeterWorkspace *workspace;
+ IdeWorkbench *workbench;
+ GtkWidget *page;
+
+ workbench = ide_workbench_new ();
+ ide_application_add_workbench (app, workbench);
+
+ workspace = ide_greeter_workspace_new (app);
+ ide_workbench_add_workspace (workbench, IDE_WORKSPACE (workspace));
+
+ ide_greeter_workspace_set_page_name (workspace, "clone");
+ page = ide_greeter_workspace_get_page_named (workspace, "clone");
+
+ if (GBP_IS_VCSUI_CLONE_PAGE (page))
+ gbp_vcsui_clone_page_set_uri (GBP_VCSUI_CLONE_PAGE (page), clone_uri);
+
+ ide_workbench_focus_workspace (workbench, IDE_WORKSPACE (workspace));
+ }
+
+ IDE_EXIT;
+}
+
+static void
+gbp_vcsui_application_addin_add_option_entries (IdeApplicationAddin *addin,
+ IdeApplication *app)
+{
+ g_assert (GBP_IS_VCSUI_APPLICATION_ADDIN (addin));
+ g_assert (IDE_IS_APPLICATION (app));
+
+ g_application_add_main_option (G_APPLICATION (app),
+ "clone",
+ 0,
+ G_OPTION_FLAG_IN_MAIN,
+ G_OPTION_ARG_STRING,
+ _("Begin cloning project from URI"),
+ "URI");
+}
+
+static void
+application_addin_iface_init (IdeApplicationAddinInterface *iface)
+{
+ iface->add_option_entries = gbp_vcsui_application_addin_add_option_entries;
+ iface->handle_command_line = gbp_vcsui_application_addin_handle_command_line;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpVcsuiApplicationAddin, gbp_vcsui_application_addin, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_APPLICATION_ADDIN,
application_addin_iface_init))
+
+static void
+gbp_vcsui_application_addin_class_init (GbpVcsuiApplicationAddinClass *klass)
+{
+}
+
+static void
+gbp_vcsui_application_addin_init (GbpVcsuiApplicationAddin *self)
+{
+}
diff --git a/src/plugins/vcsui/gbp-vcsui-application-addin.h b/src/plugins/vcsui/gbp-vcsui-application-addin.h
new file mode 100644
index 000000000..e41f67cd8
--- /dev/null
+++ b/src/plugins/vcsui/gbp-vcsui-application-addin.h
@@ -0,0 +1,31 @@
+/* gbp-vcsui-application-addin.h
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_VCSUI_APPLICATION_ADDIN (gbp_vcsui_application_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpVcsuiApplicationAddin, gbp_vcsui_application_addin, GBP, VCSUI_APPLICATION_ADDIN,
GObject)
+
+G_END_DECLS
diff --git a/src/plugins/vcsui/gbp-vcsui-clone-page.c b/src/plugins/vcsui/gbp-vcsui-clone-page.c
new file mode 100644
index 000000000..5f3c3a647
--- /dev/null
+++ b/src/plugins/vcsui/gbp-vcsui-clone-page.c
@@ -0,0 +1,444 @@
+/* gbp-vcsui-clone-page.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-vcsui-clone-page"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <adwaita.h>
+#include <vte/vte.h>
+
+#include <libide-greeter.h>
+#include <libide-gtk.h>
+#include <libide-gui.h>
+#include <libide-projects.h>
+
+#include "gbp-vcsui-clone-page.h"
+
+struct _GbpVcsuiClonePage
+{
+ GtkWidget parent_instance;
+
+ AdwEntryRow *author_email_row;
+ AdwEntryRow *author_name_row;
+ GtkMenuButton *branch_button;
+ GtkLabel *branch_label;
+ AdwEntryRow *location_row;
+ GtkWidget *main;
+ GtkStack *stack;
+ VteTerminal *terminal;
+ AdwEntryRow *uri_row;
+ IdeProgressIcon *progress;
+ GtkLabel *failure_message;
+
+ IdeVcsCloneRequest *request;
+};
+
+G_DEFINE_FINAL_TYPE (GbpVcsuiClonePage, gbp_vcsui_clone_page, GTK_TYPE_WIDGET)
+
+static void
+location_row_changed_cb (GbpVcsuiClonePage *self,
+ GtkEditable *editable)
+{
+ g_autofree char *expanded = NULL;
+ g_autoptr(GFile) directory = NULL;
+ const char *text;
+
+ g_assert (GBP_IS_VCSUI_CLONE_PAGE (self));
+ g_assert (GTK_IS_EDITABLE (editable));
+
+ text = gtk_editable_get_text (editable);
+ expanded = ide_path_expand (text);
+ directory = g_file_new_for_path (expanded);
+
+ ide_vcs_clone_request_set_directory (self->request, directory);
+}
+
+static void
+select_folder_response_cb (GbpVcsuiClonePage *self,
+ int response_id,
+ GtkFileChooserNative *native)
+{
+ g_assert (GBP_IS_VCSUI_CLONE_PAGE (self));
+ g_assert (GTK_IS_FILE_CHOOSER_NATIVE (native));
+
+ if (response_id == GTK_RESPONSE_ACCEPT)
+ {
+ g_autoptr(GFile) file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (native));
+ g_autofree char *path = ide_path_collapse (g_file_peek_path (file));
+
+ gtk_editable_set_text (GTK_EDITABLE (self->location_row), path);
+ }
+
+ gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (native));
+}
+
+static void
+select_folder_action (GtkWidget *widget,
+ const char *action_name,
+ GVariant *param)
+{
+ GbpVcsuiClonePage *self = (GbpVcsuiClonePage *)widget;
+ GtkFileChooserNative *native;
+ GtkRoot *root;
+
+ g_assert (GBP_IS_VCSUI_CLONE_PAGE (self));
+
+ root = gtk_widget_get_root (widget);
+ native = gtk_file_chooser_native_new (_("Select Location"),
+ GTK_WINDOW (root),
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+ _("Select"),
+ _("Cancel"));
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (native),
+ ide_vcs_clone_request_get_directory (self->request),
+ NULL);
+ g_signal_connect_object (native,
+ "response",
+ G_CALLBACK (select_folder_response_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ gtk_native_dialog_show (GTK_NATIVE_DIALOG (native));
+}
+
+static void
+gbp_vcsui_clone_page_clone_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeVcsCloneRequest *request = (IdeVcsCloneRequest *)object;
+ g_autoptr(GbpVcsuiClonePage) self = user_data;
+ IdeGreeterWorkspace *greeter;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GFile) directory = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_VCS_CLONE_REQUEST (request));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (GBP_IS_VCSUI_CLONE_PAGE (self));
+
+ greeter = IDE_GREETER_WORKSPACE (ide_widget_get_workspace (GTK_WIDGET (self)));
+
+ gtk_widget_hide (GTK_WIDGET (self->progress));
+
+ if (!(directory = ide_vcs_clone_request_clone_finish (request, result, &error)))
+ {
+ g_message ("Failed to clone repository: %s", error->message);
+ gtk_stack_set_visible_child_name (self->stack, "details");
+ gtk_label_set_label (self->failure_message,
+ _("A failure occurred while cloning the repository."));
+ IDE_GOTO (failure);
+ }
+ else
+ {
+ g_autoptr(IdeProjectInfo) project_info = NULL;
+
+ g_debug ("Clone request complete\n");
+
+ project_info = ide_project_info_new ();
+ ide_project_info_set_file (project_info, directory);
+ ide_project_info_set_directory (project_info, directory);
+
+ ide_greeter_workspace_open_project (greeter, project_info);
+ }
+
+failure:
+ ide_greeter_workspace_end (greeter);
+
+ IDE_EXIT;
+}
+
+static void
+notify_progress_cb (IdeNotification *notif,
+ GParamSpec *pspec,
+ IdeProgressIcon *icon)
+{
+ IdeAnimation *anim;
+ double progress;
+
+ g_assert (IDE_IS_NOTIFICATION (notif));
+ g_assert (IDE_IS_PROGRESS_ICON (icon));
+
+ anim = g_object_get_data (G_OBJECT (icon), "ANIMATION");
+ if (anim != NULL)
+ ide_animation_stop (anim);
+
+ progress = ide_notification_get_progress (notif);
+ anim = ide_object_animate (icon,
+ IDE_ANIMATION_LINEAR,
+ 200,
+ NULL,
+ "progress", progress,
+ NULL);
+ g_object_set_data_full (G_OBJECT (icon),
+ "ANIMATION",
+ g_object_ref (anim),
+ g_object_unref);
+}
+
+static void
+notify_body_cb (IdeNotification *notif,
+ GParamSpec *pspec,
+ VteTerminal *terminal)
+{
+ g_autofree char *body = NULL;
+
+ g_assert (IDE_IS_NOTIFICATION (notif));
+ g_assert (VTE_IS_TERMINAL (terminal));
+
+ /* TODO: we need to plumb something better than IdeNotification to pass
+ * essentially PTY data between the worker and the UI process. but this
+ * will be fine for now until we can get to it.
+ */
+
+ if ((body = ide_notification_dup_body (notif)))
+ vte_terminal_feed (terminal, body, -1);
+}
+
+static void
+clone_action (GtkWidget *widget,
+ const char *action_name,
+ GVariant *param)
+{
+ GbpVcsuiClonePage *self = (GbpVcsuiClonePage *)widget;
+ g_autoptr(IdeNotification) notif = NULL;
+ IdeGreeterWorkspace *greeter;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_VCSUI_CLONE_PAGE (self));
+
+ gtk_stack_set_visible_child_name (self->stack, "progress");
+ gtk_widget_show (GTK_WIDGET (self->progress));
+
+ notif = ide_notification_new ();
+ g_signal_connect_object (notif,
+ "notify::progress",
+ G_CALLBACK (notify_progress_cb),
+ self->progress,
+ 0);
+ g_signal_connect_object (notif,
+ "notify::body",
+ G_CALLBACK (notify_body_cb),
+ self->terminal,
+ 0);
+
+ greeter = IDE_GREETER_WORKSPACE (ide_widget_get_workspace (widget));
+ ide_greeter_workspace_begin (greeter);
+ gtk_widget_action_set_enabled (widget, "clone-page.clone", FALSE);
+
+ gtk_label_set_label (self->failure_message, NULL);
+
+ ide_vcs_clone_request_clone_async (self->request,
+ notif,
+ NULL,
+ gbp_vcsui_clone_page_clone_cb,
+ g_object_ref (self));
+
+ IDE_EXIT;
+}
+
+static void
+branch_activated_cb (GbpVcsuiClonePage *self,
+ guint position,
+ GtkListView *list_view)
+{
+ g_autoptr(IdeVcsBranch) branch = NULL;
+ g_autofree char *branch_id = NULL;
+ GListModel *model;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_VCSUI_CLONE_PAGE (self));
+ g_assert (GTK_IS_LIST_VIEW (list_view));
+
+ model = G_LIST_MODEL (gtk_list_view_get_model (list_view));
+ branch = g_list_model_get_item (model, position);
+ branch_id = ide_vcs_branch_dup_id (branch);
+
+ ide_vcs_clone_request_set_branch_name (self->request, branch_id);
+
+ gtk_menu_button_popdown (self->branch_button);
+
+ IDE_EXIT;
+}
+
+static void
+branch_popover_show_cb (GbpVcsuiClonePage *self,
+ GtkPopover *popover)
+{
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_VCSUI_CLONE_PAGE (self));
+ g_assert (GTK_IS_POPOVER (popover));
+
+ ide_vcs_clone_request_populate_branches (self->request);
+
+ IDE_EXIT;
+}
+
+static void
+branch_name_changed_cb (GbpVcsuiClonePage *self,
+ GParamSpec *pspec,
+ IdeVcsCloneRequest *request)
+{
+ const char *branch_name;
+ gboolean empty;
+
+ g_assert (GBP_IS_VCSUI_CLONE_PAGE (self));
+ g_assert (IDE_IS_VCS_CLONE_REQUEST (request));
+
+ branch_name = ide_vcs_clone_request_get_branch_name (request);
+
+ /* Very much a git-ism, but that's all we support right now */
+ if (branch_name != NULL && g_str_has_prefix (branch_name, "refs/heads/"))
+ branch_name += strlen ("refs/heads/");
+
+ empty = ide_str_empty0 (branch_name);
+
+ gtk_widget_set_tooltip_text (GTK_WIDGET (self->branch_label),
+ empty ? NULL : branch_name);
+ gtk_label_set_label (self->branch_label, branch_name);
+ gtk_widget_set_visible (GTK_WIDGET (self->branch_label), !empty);
+}
+
+static void
+request_notify_cb (GbpVcsuiClonePage *self,
+ GParamSpec *pspec,
+ IdeVcsCloneRequest *request)
+{
+ IdeVcsCloneRequestValidation flags = 0;
+
+ g_assert (GBP_IS_VCSUI_CLONE_PAGE (self));
+ g_assert (IDE_IS_VCS_CLONE_REQUEST (request));
+
+ flags = ide_vcs_clone_request_validate (request);
+
+ if (flags & IDE_VCS_CLONE_REQUEST_INVAL_URI)
+ gtk_widget_add_css_class (GTK_WIDGET (self->uri_row), "error");
+ else
+ gtk_widget_remove_css_class (GTK_WIDGET (self->uri_row), "error");
+
+ if (flags & IDE_VCS_CLONE_REQUEST_INVAL_DIRECTORY)
+ gtk_widget_add_css_class (GTK_WIDGET (self->location_row), "error");
+ else
+ gtk_widget_remove_css_class (GTK_WIDGET (self->location_row), "error");
+
+ if (flags & IDE_VCS_CLONE_REQUEST_INVAL_EMAIL)
+ gtk_widget_add_css_class (GTK_WIDGET (self->author_email_row), "error");
+ else
+ gtk_widget_remove_css_class (GTK_WIDGET (self->author_email_row), "error");
+
+ gtk_widget_action_set_enabled (GTK_WIDGET (self), "clone-page.clone", flags == 0);
+}
+
+static void
+gbp_vcsui_clone_page_root (GtkWidget *widget)
+{
+ GbpVcsuiClonePage *self = (GbpVcsuiClonePage *)widget;
+ IdeContext *context;
+
+ g_assert (GBP_IS_VCSUI_CLONE_PAGE (self));
+
+ GTK_WIDGET_CLASS (gbp_vcsui_clone_page_parent_class)->root (widget);
+
+ if ((context = ide_widget_get_context (widget)))
+ ide_object_append (IDE_OBJECT (context), IDE_OBJECT (self->request));
+}
+
+static void
+gbp_vcsui_clone_page_dispose (GObject *object)
+{
+ GbpVcsuiClonePage *self = (GbpVcsuiClonePage *)object;
+
+ ide_object_destroy (IDE_OBJECT (self->request));
+ g_clear_pointer (&self->main, gtk_widget_unparent);
+
+ G_OBJECT_CLASS (gbp_vcsui_clone_page_parent_class)->dispose (object);
+}
+
+static void
+gbp_vcsui_clone_page_class_init (GbpVcsuiClonePageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = gbp_vcsui_clone_page_dispose;
+
+ widget_class->root = gbp_vcsui_clone_page_root;
+
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+ gtk_widget_class_set_template_from_resource (widget_class, "/plugins/vcsui/gbp-vcsui-clone-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiClonePage, author_email_row);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiClonePage, author_name_row);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiClonePage, branch_button);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiClonePage, branch_label);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiClonePage, failure_message);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiClonePage, location_row);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiClonePage, main);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiClonePage, progress);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiClonePage, request);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiClonePage, stack);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiClonePage, terminal);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiClonePage, uri_row);
+
+ gtk_widget_class_bind_template_callback (widget_class, location_row_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, branch_activated_cb);
+ gtk_widget_class_bind_template_callback (widget_class, branch_name_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, branch_popover_show_cb);
+ gtk_widget_class_bind_template_callback (widget_class, request_notify_cb);
+
+ gtk_widget_class_install_action (widget_class, "clone-page.select-folder", NULL, select_folder_action);
+ gtk_widget_class_install_action (widget_class, "clone-page.clone", NULL, clone_action);
+
+ g_type_ensure (IDE_TYPE_PROGRESS_ICON);
+ g_type_ensure (VTE_TYPE_TERMINAL);
+ g_type_ensure (IDE_TYPE_VCS_CLONE_REQUEST);
+}
+
+static void
+gbp_vcsui_clone_page_init (GbpVcsuiClonePage *self)
+{
+ g_autofree char *projects_dir = ide_path_collapse (ide_get_projects_dir ());
+ static GdkRGBA transparent = {0, 0, 0, 0};
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_editable_set_text (GTK_EDITABLE (self->location_row), projects_dir);
+ gtk_editable_set_text (GTK_EDITABLE (self->author_name_row), g_get_real_name ());
+
+ vte_terminal_set_colors (self->terminal, NULL, &transparent, NULL, 0);
+}
+
+void
+gbp_vcsui_clone_page_set_uri (GbpVcsuiClonePage *self,
+ const char *uri)
+{
+ g_return_if_fail (GBP_IS_VCSUI_CLONE_PAGE (self));
+
+ if (uri == NULL)
+ uri = "";
+
+ gtk_editable_set_text (GTK_EDITABLE (self->uri_row), uri);
+}
diff --git a/src/plugins/vcsui/gbp-vcsui-clone-page.h b/src/plugins/vcsui/gbp-vcsui-clone-page.h
new file mode 100644
index 000000000..02289653f
--- /dev/null
+++ b/src/plugins/vcsui/gbp-vcsui-clone-page.h
@@ -0,0 +1,36 @@
+/* gbp-vcsui-clone-page.h
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <libide-vcs.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_VCSUI_CLONE_PAGE (gbp_vcsui_clone_page_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpVcsuiClonePage, gbp_vcsui_clone_page, GBP, VCSUI_CLONE_PAGE, GtkWidget)
+
+void gbp_vcsui_clone_page_set_uri (GbpVcsuiClonePage *self,
+ const char *uri);
+
+G_END_DECLS
diff --git a/src/plugins/vcsui/gbp-vcsui-clone-page.ui b/src/plugins/vcsui/gbp-vcsui-clone-page.ui
new file mode 100644
index 000000000..81783d896
--- /dev/null
+++ b/src/plugins/vcsui/gbp-vcsui-clone-page.ui
@@ -0,0 +1,303 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="Adw" version="1.0"/>
+ <template class="GbpVcsuiClonePage" parent="GtkWidget">
+ <child>
+ <object class="AdwClamp" id="main">
+ <property name="orientation">horizontal</property>
+ <property name="maximum-size">550</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">64</property>
+ <property name="margin-bottom">64</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">24</property>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwEntryRow" id="uri_row">
+ <property name="title" translatable="yes">Repository URL</property>
+ <property name="text" bind-source="request" bind-property="uri"
bind-flags="sync-create|bidirectional"/>
+ <child type="suffix">
+ <object class="GtkLabel" id="branch_label">
+ <property name="ellipsize">end</property>
+ <property name="selectable">true</property>
+ <property name="max-width-chars">10</property>
+ <property name="visible">false</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child type="suffix">
+ <object class="GtkMenuButton" id="branch_button">
+ <style>
+ <class name="flat"/>
+ </style>
+ <property name="icon-name">builder-vcs-branch-symbolic</property>
+ <property name="tooltip-text" translatable="yes">Choose an alternate
branch</property>
+ <property name="valign">center</property>
+ <property name="popover">
+ <object class="GtkPopover">
+ <style>
+ <class name="menu"/>
+ </style>
+ <signal name="show" handler="branch_popover_show_cb" swapped="true"
object="GbpVcsuiClonePage"/>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="margin-top">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Branches</property>
+ <property name="hexpand">true</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="heading"/>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSpinner">
+ <property name="spinning" bind-source="request"
bind-property="branch-model-busy"/>
+ <property name="visible" bind-source="request"
bind-property="branch-model-busy"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="propagate-natural-height">true</property>
+ <property name="propagate-natural-width">true</property>
+ <property name="min-content-width">300</property>
+ <property name="max-content-width">300</property>
+ <property name="max-content-height">500</property>
+ <child>
+ <object class="GtkListView">
+ <signal name="activate" handler="branch_activated_cb" swapped="true"
object="GbpVcsuiClonePage"/>
+ <property name="model">
+ <object class="GtkSingleSelection">
+ <property name="model" bind-source="request"
bind-property="branch-model" bind-flags="sync-create"/>
+ </object>
+ </property>
+ <property name="orientation">vertical</property>
+ <property name="single-click-activate">true</property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property name="bytes"><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkListItem">
+ <property name="child">
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="ellipsize">end</property>
+ <property name="hexpand">true</property>
+ <binding name="label">
+ <lookup name="name" type="IdeVcsBranch">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </child>
+ </object>
+ </property>
+ </template>
+</interface>
+]]>
+ </property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ <property name="sensitive" bind-source="request" bind-property="can-select-branch"
bind-flags="sync-create"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="margin-top">12</property>
+ <property name="wrap">true</property>
+ <property name="label" translatable="yes">Enter the URL of the source code repository
for the project you would like to clone.</property>
+ <style>
+ <class name="caption"/>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <child>
+ <object class="AdwEntryRow" id="location_row">
+ <property name="title" translatable="yes">Location</property>
+ <signal name="changed" handler="location_row_changed_cb" swapped="true"
object="GbpVcsuiClonePage"/>
+ <child type="suffix">
+ <object class="GtkButton">
+ <property name="action-name">clone-page.select-folder</property>
+ <property name="valign">center</property>
+ <property name="icon-name">folder-symbolic</property>
+ <style>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">The repository will be cloned into a new
subdirectory.</property>
+ <property name="margin-top">12</property>
+ <property name="wrap">true</property>
+ <property name="xalign">0</property>
+ <style>
+ <class name="caption"/>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="hhomogeneous">true</property>
+ <property name="vhomogeneous">true</property>
+ <property name="transition-type">crossfade</property>
+ <property name="transition-duration">300</property>
+ <property name="vexpand">false</property>
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">details</property>
+ <property name="child">
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Author Details</property>
+ <child>
+ <object class="AdwEntryRow" id="author_name_row">
+ <property name="title" translatable="yes">Name</property>
+ <property name="text" bind-source="request" bind-property="author-name"
bind-flags="sync-create|bidirectional"/>
+ </object>
+ </child>
+ <child>
+ <object class="AdwEntryRow" id="author_email_row">
+ <property name="title" translatable="yes">Email</property>
+ <property name="text" bind-source="request" bind-property="author-email"
bind-flags="sync-create|bidirectional"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="xalign">0</property>
+ <property name="margin-top">12</property>
+ <property name="wrap">true</property>
+ <property name="label" translatable="yes">You may specify authorship information
to override defaults.</property>
+ <style>
+ <class name="caption"/>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">progress</property>
+ <property name="child">
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="yes">Status</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <style>
+ <class name="card"/>
+ </style>
+ <property name="has-frame">false</property>
+ <property name="min-content-height">100</property>
+ <property name="max-content-height">300</property>
+ <property name="vscrollbar-policy">external</property>
+ <property name="hscrollbar-policy">never</property>
+ <property name="vexpand">true</property>
+ <child>
+ <object class="VteTerminal" id="terminal">
+ <property name="margin-top">9</property>
+ <property name="margin-bottom">9</property>
+ <property name="margin-start">9</property>
+ <property name="margin-end">9</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="margin-top">12</property>
+ <property name="spacing">16</property>
+ <child>
+ <object class="GtkLabel" id="failure_message">
+ <property name="wrap">true</property>
+ <property name="hexpand">true</property>
+ <property name="xalign">0</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="error"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="IdeProgressIcon" id="progress">
+ <property name="visible">false</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="action-name">clone-page.clone</property>
+ <property name="label" translatable="yes">Clone Repository</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="IdeVcsCloneRequest" id="request">
+ <!--
+ Currently only `git` clone is supported. Happy to support other
+ version-control systems if someone 1) writes the IdeVcs backend
+ and 2) sticks around to maintain it with me.
+ -->
+ <property name="module-name">git</property>
+ <signal name="notify::branch-name" handler="branch_name_changed_cb" swapped="true"
object="GbpVcsuiClonePage"/>
+ <!-- All the following queue validation requests -->
+ <signal name="notify::author-email" handler="request_notify_cb" swapped="true"
object="GbpVcsuiClonePage"/>
+ <signal name="notify::directory" handler="request_notify_cb" swapped="true" object="GbpVcsuiClonePage"/>
+ <signal name="notify::uri" handler="request_notify_cb" swapped="true" object="GbpVcsuiClonePage"/>
+ </object>
+</interface>
diff --git a/src/plugins/vcsui/gbp-vcsui-editor-page-addin.c b/src/plugins/vcsui/gbp-vcsui-editor-page-addin.c
index e08d57826..03dcf50e6 100644
--- a/src/plugins/vcsui/gbp-vcsui-editor-page-addin.c
+++ b/src/plugins/vcsui/gbp-vcsui-editor-page-addin.c
@@ -33,25 +33,27 @@ struct _GbpVcsuiEditorPageAddin
static void
on_push_snippet_cb (GbpVcsuiEditorPageAddin *self,
- IdeSnippet *snippet,
+ GtkSourceSnippet *snippet,
GtkTextIter *iter,
IdeSourceView *source_view)
{
g_autoptr(IdeVcsConfig) vcs_config = NULL;
g_autoptr(IdeContext) ide_context = NULL;
- IdeSnippetContext *context;
+ GtkSourceSnippetContext *context;
IdeBuffer *buffer;
IdeVcs *vcs;
+ IDE_ENTRY;
+
g_assert (IDE_IS_MAIN_THREAD ());
g_assert (GBP_IS_VCSUI_EDITOR_PAGE_ADDIN (self));
- g_assert (IDE_IS_SNIPPET (snippet));
+ g_assert (GTK_SOURCE_IS_SNIPPET (snippet));
g_assert (iter != NULL);
g_assert (IDE_IS_SOURCE_VIEW (source_view));
buffer = IDE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (source_view)));
ide_context = ide_buffer_ref_context (buffer);
- context = ide_snippet_get_context (snippet);
+ context = gtk_source_snippet_get_context (snippet);
if ((vcs = ide_vcs_from_context (ide_context)) &&
(vcs_config = ide_vcs_get_config (vcs)))
@@ -64,9 +66,9 @@ on_push_snippet_cb (GbpVcsuiEditorPageAddin *self,
if (!ide_str_empty0 (g_value_get_string (&value)))
{
- ide_snippet_context_add_shared_variable (context, "author", g_value_get_string (&value));
- ide_snippet_context_add_shared_variable (context, "fullname", g_value_get_string (&value));
- ide_snippet_context_add_shared_variable (context, "username", g_value_get_string (&value));
+ gtk_source_snippet_context_set_variable (context, "author", g_value_get_string (&value));
+ gtk_source_snippet_context_set_variable (context, "fullname", g_value_get_string (&value));
+ gtk_source_snippet_context_set_variable (context, "username", g_value_get_string (&value));
}
g_value_reset (&value);
@@ -74,10 +76,12 @@ on_push_snippet_cb (GbpVcsuiEditorPageAddin *self,
ide_vcs_config_get_config (vcs_config, IDE_VCS_CONFIG_EMAIL, &value);
if (!ide_str_empty0 (g_value_get_string (&value)))
- ide_snippet_context_add_shared_variable (context, "email", g_value_get_string (&value));
+ gtk_source_snippet_context_set_variable (context, "email", g_value_get_string (&value));
g_value_unset (&value);
}
+
+ IDE_EXIT;
}
static void
@@ -124,7 +128,7 @@ editor_page_addin_iface_init (IdeEditorPageAddinInterface *iface)
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GbpVcsuiEditorPageAddin, gbp_vcsui_editor_page_addin, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (IDE_TYPE_EDITOR_PAGE_ADDIN, editor_page_addin_iface_init))
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_EDITOR_PAGE_ADDIN,
editor_page_addin_iface_init))
static void
gbp_vcsui_editor_page_addin_class_init (GbpVcsuiEditorPageAddinClass *klass)
diff --git a/src/plugins/vcsui/gbp-vcsui-switcher-popover.c b/src/plugins/vcsui/gbp-vcsui-switcher-popover.c
new file mode 100644
index 000000000..ea7048a1c
--- /dev/null
+++ b/src/plugins/vcsui/gbp-vcsui-switcher-popover.c
@@ -0,0 +1,244 @@
+/* gbp-vcsui-switcher-popover.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-vcsui-switcher-popover"
+
+#include "config.h"
+
+#include "gbp-vcsui-switcher-popover.h"
+
+struct _GbpVcsuiSwitcherPopover
+{
+ GtkPopover parent_instance;
+
+ IdeVcs *vcs;
+
+ GtkListView *branches_view;
+ GListStore *branches_model;
+ GtkListView *tags_view;
+ GListStore *tags_model;
+};
+
+enum {
+ PROP_0,
+ PROP_VCS,
+ N_PROPS
+};
+
+G_DEFINE_FINAL_TYPE (GbpVcsuiSwitcherPopover, gbp_vcsui_switcher_popover, GTK_TYPE_POPOVER)
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gbp_vcsui_switcher_popover_list_branches_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeVcs *vcs = (IdeVcs *)object;
+ g_autoptr(GbpVcsuiSwitcherPopover) self = user_data;
+ g_autoptr(GPtrArray) ar = NULL;
+ g_autoptr(GError) error = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_VCS (vcs));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (GBP_IS_VCSUI_SWITCHER_POPOVER (self));
+
+ if (!(ar = ide_vcs_list_branches_finish (vcs, result, &error)))
+ {
+ g_warning ("Failed to list branches: %s\n", error->message);
+ IDE_EXIT;
+ }
+
+ g_ptr_array_set_free_func (ar, g_object_unref);
+ g_list_store_remove_all (self->branches_model);
+
+ for (guint i = 0; i < ar->len; i++)
+ g_list_store_append (self->branches_model, g_ptr_array_index (ar, i));
+
+ IDE_EXIT;
+}
+
+static void
+gbp_vcsui_switcher_popover_list_tags_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdeVcs *vcs = (IdeVcs *)object;
+ g_autoptr(GbpVcsuiSwitcherPopover) self = user_data;
+ g_autoptr(GPtrArray) ar = NULL;
+ g_autoptr(GError) error = NULL;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_VCS (vcs));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (GBP_IS_VCSUI_SWITCHER_POPOVER (self));
+
+ if (!(ar = ide_vcs_list_tags_finish (vcs, result, &error)))
+ {
+ g_warning ("Failed to list tags: %s\n", error->message);
+ IDE_EXIT;
+ }
+
+ g_ptr_array_set_free_func (ar, g_object_unref);
+ g_list_store_remove_all (self->tags_model);
+
+ for (guint i = 0; i < ar->len; i++)
+ g_list_store_append (self->tags_model, g_ptr_array_index (ar, i));
+
+ IDE_EXIT;
+}
+
+static void
+gbp_vcsui_switcher_popover_dispose (GObject *object)
+{
+ GbpVcsuiSwitcherPopover *self = (GbpVcsuiSwitcherPopover *)object;
+
+ g_clear_object (&self->vcs);
+
+ G_OBJECT_CLASS (gbp_vcsui_switcher_popover_parent_class)->dispose (object);
+}
+
+static void
+gbp_vcsui_switcher_popover_show (GtkWidget *widget)
+{
+ GbpVcsuiSwitcherPopover *self = (GbpVcsuiSwitcherPopover *)widget;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_VCSUI_SWITCHER_POPOVER (self));
+
+ if (self->vcs != NULL)
+ {
+ ide_vcs_list_branches_async (self->vcs,
+ NULL,
+ gbp_vcsui_switcher_popover_list_branches_cb,
+ g_object_ref (self));
+ ide_vcs_list_tags_async (self->vcs,
+ NULL,
+ gbp_vcsui_switcher_popover_list_tags_cb,
+ g_object_ref (self));
+ }
+
+ GTK_WIDGET_CLASS (gbp_vcsui_switcher_popover_parent_class)->show (widget);
+
+ IDE_EXIT;
+}
+
+static void
+gbp_vcsui_switcher_popover_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpVcsuiSwitcherPopover *self = GBP_VCSUI_SWITCHER_POPOVER (object);
+
+ switch (prop_id)
+ {
+ case PROP_VCS:
+ g_value_set_object (value, self->vcs);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_vcsui_switcher_popover_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpVcsuiSwitcherPopover *self = GBP_VCSUI_SWITCHER_POPOVER (object);
+
+ switch (prop_id)
+ {
+ case PROP_VCS:
+ gbp_vcsui_switcher_popover_set_vcs (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_vcsui_switcher_popover_class_init (GbpVcsuiSwitcherPopoverClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->dispose = gbp_vcsui_switcher_popover_dispose;
+ object_class->get_property = gbp_vcsui_switcher_popover_get_property;
+ object_class->set_property = gbp_vcsui_switcher_popover_set_property;
+
+ widget_class->show = gbp_vcsui_switcher_popover_show;
+
+ properties [PROP_VCS] =
+ g_param_spec_object ("vcs",
+ "Vcs",
+ "The version control system",
+ IDE_TYPE_VCS,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/plugins/vcsui/gbp-vcsui-switcher-popover.ui");
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiSwitcherPopover, branches_view);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiSwitcherPopover, branches_model);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiSwitcherPopover, tags_view);
+ gtk_widget_class_bind_template_child (widget_class, GbpVcsuiSwitcherPopover, tags_model);
+}
+
+static void
+gbp_vcsui_switcher_popover_init (GbpVcsuiSwitcherPopover *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+IdeVcs *
+gbp_vcsui_switcher_popover_get_vcs (GbpVcsuiSwitcherPopover *self)
+{
+ g_return_val_if_fail (GBP_IS_VCSUI_SWITCHER_POPOVER (self), NULL);
+
+ return self->vcs;
+}
+
+void
+gbp_vcsui_switcher_popover_set_vcs (GbpVcsuiSwitcherPopover *self,
+ IdeVcs *vcs)
+{
+ g_return_if_fail (GBP_IS_VCSUI_SWITCHER_POPOVER (self));
+ g_return_if_fail (!vcs || IDE_IS_VCS (vcs));
+
+ if (g_set_object (&self->vcs, vcs))
+ {
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_VCS]);
+ }
+}
+
+GtkWidget *
+gbp_vcsui_switcher_popover_new (void)
+{
+ return g_object_new (GBP_TYPE_VCSUI_SWITCHER_POPOVER, NULL);
+}
diff --git a/src/plugins/vcsui/gbp-vcsui-switcher-popover.h b/src/plugins/vcsui/gbp-vcsui-switcher-popover.h
new file mode 100644
index 000000000..3948133b5
--- /dev/null
+++ b/src/plugins/vcsui/gbp-vcsui-switcher-popover.h
@@ -0,0 +1,38 @@
+/* gbp-vcsui-switcher-popover.h
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include <libide-vcs.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_VCSUI_SWITCHER_POPOVER (gbp_vcsui_switcher_popover_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpVcsuiSwitcherPopover, gbp_vcsui_switcher_popover, GBP, VCSUI_SWITCHER_POPOVER,
GtkPopover)
+
+GtkWidget *gbp_vcsui_switcher_popover_new (void);
+IdeVcs *gbp_vcsui_switcher_popover_get_vcs (GbpVcsuiSwitcherPopover *self);
+void gbp_vcsui_switcher_popover_set_vcs (GbpVcsuiSwitcherPopover *self,
+ IdeVcs *vcs);
+
+G_END_DECLS
diff --git a/src/plugins/vcsui/gbp-vcsui-switcher-popover.ui b/src/plugins/vcsui/gbp-vcsui-switcher-popover.ui
new file mode 100644
index 000000000..1ebddfdef
--- /dev/null
+++ b/src/plugins/vcsui/gbp-vcsui-switcher-popover.ui
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GbpVcsuiSwitcherPopover" parent="GtkPopover">
+ <style>
+ <class name="menu"/>
+ </style>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkStackSwitcher">
+ <property name="stack">stack</property>
+ <property name="margin-top">6</property>
+ <property name="margin-start">6</property>
+ <property name="margin-end">6</property>
+ <property name="margin-bottom">6</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="vhomogeneous">false</property>
+ <property name="interpolate-size">true</property>
+ <property name="transition-type">crossfade</property>
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">branches</property>
+ <property name="title" translatable="yes">_Branches</property>
+ <property name="use-underline">true</property>
+ <property name="child">
+ <object class="GtkScrolledWindow">
+ <property name="propagate-natural-height">true</property>
+ <property name="propagate-natural-width">true</property>
+ <property name="min-content-height">100</property>
+ <property name="max-content-height">600</property>
+ <property name="min-content-width">300</property>
+ <property name="max-content-width">300</property>
+ <child>
+ <object class="GtkListView" id="branches_view">
+ <!--signal name="activate" handler="activate_branch_cb" swapped="true"
object="GbpVcsuiSwitcherPopover"/-->
+ <property name="orientation">vertical</property>
+ <property name="single-click-activate">true</property>
+ <property name="model">
+ <object class="GtkNoSelection">
+ <property name="model">branches_model</property>
+ </object>
+ </property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property name="bytes"><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkListItem">
+ <property name="child">
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">start</property>
+ <property name="hexpand">true</property>
+ <property name="ellipsize">start</property>
+ <binding name="label">
+ <lookup name="name" type="IdeVcsBranch">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </child>
+ </object>
+ </property>
+ </template>
+</interface>
+]]>
+ </property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">tags</property>
+ <property name="title" translatable="yes">_Tags</property>
+ <property name="use-underline">true</property>
+ <property name="child">
+ <object class="GtkScrolledWindow">
+ <property name="propagate-natural-height">true</property>
+ <property name="propagate-natural-width">true</property>
+ <property name="min-content-height">100</property>
+ <property name="max-content-height">600</property>
+ <property name="min-content-width">300</property>
+ <property name="max-content-width">300</property>
+ <child>
+ <object class="GtkListView" id="tags_view">
+ <!--signal name="activate" handler="activate_tag_cb" swapped="true"
object="GbpVcsuiSwitcherPopover"/-->
+ <property name="orientation">vertical</property>
+ <property name="single-click-activate">true</property>
+ <property name="model">
+ <object class="GtkNoSelection">
+ <property name="model">tags_model</property>
+ </object>
+ </property>
+ <property name="factory">
+ <object class="GtkBuilderListItemFactory">
+ <property name="bytes"><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkListItem">
+ <property name="child">
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="halign">start</property>
+ <property name="hexpand">true</property>
+ <property name="ellipsize">start</property>
+ <binding name="label">
+ <lookup name="name" type="IdeVcsTag">
+ <lookup name="item">GtkListItem</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </child>
+ </object>
+ </property>
+ </template>
+</interface>
+]]>
+ </property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+ <object class="GListStore" id="branches_model">
+ <property name="item-type">IdeVcsBranch</property>
+ </object>
+ <object class="GListStore" id="tags_model">
+ <property name="item-type">IdeVcsTag</property>
+ </object>
+</interface>
diff --git a/src/plugins/vcsui/gbp-vcsui-tree-addin.c b/src/plugins/vcsui/gbp-vcsui-tree-addin.c
index 9b8adac71..70c833698 100644
--- a/src/plugins/vcsui/gbp-vcsui-tree-addin.c
+++ b/src/plugins/vcsui/gbp-vcsui-tree-addin.c
@@ -37,6 +37,8 @@ struct _GbpVcsuiTreeAddin
{
GObject parent_instance;
+ GActionMap *actions;
+
IdeTree *tree;
IdeTreeModel *model;
IdeVcs *vcs;
@@ -170,6 +172,7 @@ gbp_vcsui_tree_addin_load (IdeTreeAddin *addin,
gtk_widget_insert_action_group (GTK_WIDGET (tree),
"vcsui",
G_ACTION_GROUP (group));
+ self->actions = g_object_ref (G_ACTION_MAP (group));
if ((workbench = ide_widget_get_workbench (GTK_WIDGET (tree))) &&
(vcs = ide_workbench_get_vcs (workbench)) &&
@@ -199,6 +202,7 @@ gbp_vcsui_tree_addin_unload (IdeTreeAddin *addin,
gtk_widget_insert_action_group (GTK_WIDGET (tree), "vcsui", NULL);
+ g_clear_object (&self->actions);
g_clear_object (&self->monitor);
g_clear_object (&self->vcs);
self->model = NULL;
@@ -211,6 +215,7 @@ gbp_vcsui_tree_addin_selection_changed (IdeTreeAddin *addin,
{
GbpVcsuiTreeAddin *self = (GbpVcsuiTreeAddin *)addin;
gboolean is_branch = FALSE;
+ GAction *action;
g_assert (IDE_IS_MAIN_THREAD ());
g_assert (GBP_IS_VCSUI_TREE_ADDIN (self));
@@ -219,12 +224,11 @@ gbp_vcsui_tree_addin_selection_changed (IdeTreeAddin *addin,
if (node != NULL)
is_branch = ide_tree_node_holds (node, IDE_TYPE_VCS_BRANCH);
- dzl_gtk_widget_action_set (GTK_WIDGET (self->tree), "vcsui", "switch-branch",
- "enabled", is_branch,
- NULL);
- dzl_gtk_widget_action_set (GTK_WIDGET (self->tree), "vcsui", "push-branch",
- "enabled", is_branch,
- NULL);
+ action = g_action_map_lookup_action (self->actions, "switch-branch");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), is_branch);
+
+ action = g_action_map_lookup_action (self->actions, "push-branch");
+ g_simple_action_set_enabled (G_SIMPLE_ACTION (action), is_branch);
}
static void
@@ -289,7 +293,7 @@ gbp_vcsui_tree_addin_list_branches_cb (GObject *object,
for (guint i = 0; i < branches->len; i++)
{
IdeVcsBranch *branch = g_ptr_array_index (branches, i);
- g_autofree gchar *name = ide_vcs_branch_get_name (branch);
+ g_autofree gchar *name = ide_vcs_branch_dup_name (branch);
g_autoptr(IdeTreeNode) child = NULL;
child = g_object_new (IDE_TYPE_TREE_NODE,
@@ -329,7 +333,7 @@ gbp_vcsui_tree_addin_list_tags_cb (GObject *object,
for (guint i = 0; i < tags->len; i++)
{
IdeVcsTag *tag = g_ptr_array_index (tags, i);
- g_autofree gchar *name = ide_vcs_tag_get_name (tag);
+ g_autofree gchar *name = ide_vcs_tag_dup_name (tag);
g_autoptr(IdeTreeNode) child = NULL;
child = g_object_new (IDE_TYPE_TREE_NODE,
@@ -461,7 +465,7 @@ tree_addin_iface_init (IdeTreeAddinInterface *iface)
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GbpVcsuiTreeAddin, gbp_vcsui_tree_addin, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (IDE_TYPE_TREE_ADDIN, tree_addin_iface_init))
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_TREE_ADDIN, tree_addin_iface_init))
static void
gbp_vcsui_tree_addin_class_init (GbpVcsuiTreeAddinClass *klass)
diff --git a/src/plugins/vcsui/gbp-vcsui-workbench-addin.c b/src/plugins/vcsui/gbp-vcsui-workbench-addin.c
index 6fa7e1cec..8e04beee0 100644
--- a/src/plugins/vcsui/gbp-vcsui-workbench-addin.c
+++ b/src/plugins/vcsui/gbp-vcsui-workbench-addin.c
@@ -22,7 +22,6 @@
#include "config.h"
-#include <dazzle.h>
#include <libide-gui.h>
#include <libide-vcs.h>
@@ -30,9 +29,8 @@
struct _GbpVcsuiWorkbenchAddin
{
- GObject parent_instance;
-
- DzlSignalGroup *vcs_signals;
+ GObject parent_instance;
+ IdeSignalGroup *vcs_signals;
};
static void
@@ -71,7 +69,7 @@ gbp_vcsui_workbench_addin_vcs_changed (IdeWorkbenchAddin *addin,
g_assert (GBP_IS_VCSUI_WORKBENCH_ADDIN (self));
g_assert (!vcs || IDE_IS_VCS (vcs));
- dzl_signal_group_set_target (self->vcs_signals, vcs);
+ ide_signal_group_set_target (self->vcs_signals, vcs);
if (vcs != NULL)
on_notify_branch_name (self, NULL, vcs);
@@ -87,8 +85,8 @@ gbp_vcsui_workbench_addin_load (IdeWorkbenchAddin *addin,
g_assert (GBP_IS_VCSUI_WORKBENCH_ADDIN (self));
g_assert (IDE_IS_WORKBENCH (workbench));
- self->vcs_signals = dzl_signal_group_new (G_TYPE_OBJECT);
- dzl_signal_group_connect_object (self->vcs_signals,
+ self->vcs_signals = ide_signal_group_new (G_TYPE_OBJECT);
+ ide_signal_group_connect_object (self->vcs_signals,
"notify::branch-name",
G_CALLBACK (on_notify_branch_name),
self,
@@ -104,7 +102,7 @@ gbp_vcsui_workbench_addin_unload (IdeWorkbenchAddin *addin,
g_assert (GBP_IS_VCSUI_WORKBENCH_ADDIN (self));
g_assert (IDE_IS_WORKBENCH (workbench));
- dzl_signal_group_set_target (self->vcs_signals, NULL);
+ ide_signal_group_set_target (self->vcs_signals, NULL);
g_clear_object (&self->vcs_signals);
}
@@ -117,7 +115,7 @@ workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface)
}
G_DEFINE_FINAL_TYPE_WITH_CODE (GbpVcsuiWorkbenchAddin, gbp_vcsui_workbench_addin, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKBENCH_ADDIN, workbench_addin_iface_init))
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKBENCH_ADDIN, workbench_addin_iface_init))
static void
gbp_vcsui_workbench_addin_class_init (GbpVcsuiWorkbenchAddinClass *klass)
diff --git a/src/plugins/vcsui/gbp-vcsui-workspace-addin.c b/src/plugins/vcsui/gbp-vcsui-workspace-addin.c
new file mode 100644
index 000000000..c9930fe0a
--- /dev/null
+++ b/src/plugins/vcsui/gbp-vcsui-workspace-addin.c
@@ -0,0 +1,194 @@
+/* gbp-vcsui-workspace-addin.c
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-vcsui-workspace-addin"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <libide-gui.h>
+#include <libide-greeter.h>
+
+#include "gbp-vcsui-clone-page.h"
+#include "gbp-vcsui-switcher-popover.h"
+#include "gbp-vcsui-workspace-addin.h"
+
+struct _GbpVcsuiWorkspaceAddin
+{
+ GObject parent_instance;
+
+ GbpVcsuiClonePage *clone;
+
+ GtkMenuButton *branch_button;
+ GtkLabel *branch_label;
+ IdeBindingGroup *vcs_bindings;
+};
+
+static gboolean
+greeter_open_project_cb (GbpVcsuiWorkspaceAddin *self,
+ IdeProjectInfo *project_info,
+ IdeGreeterWorkspace *greeter)
+{
+ const char *vcs_uri;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_VCSUI_WORKSPACE_ADDIN (self));
+ g_assert (IDE_IS_PROJECT_INFO (project_info));
+ g_assert (IDE_IS_GREETER_WORKSPACE (greeter));
+
+ if (!ide_project_info_get_file (project_info) &&
+ !ide_project_info_get_directory (project_info) &&
+ (vcs_uri = ide_project_info_get_vcs_uri (project_info)))
+ {
+ gbp_vcsui_clone_page_set_uri (self->clone, vcs_uri);
+ ide_greeter_workspace_set_page_name (greeter, "clone");
+ IDE_RETURN (TRUE);
+ }
+
+ IDE_RETURN (FALSE);
+}
+
+static void
+gbp_vcsui_workspace_addin_load (IdeWorkspaceAddin *addin,
+ IdeWorkspace *workspace)
+{
+ GbpVcsuiWorkspaceAddin *self = (GbpVcsuiWorkspaceAddin *)addin;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_VCSUI_WORKSPACE_ADDIN (self));
+
+ if (IDE_IS_GREETER_WORKSPACE (workspace))
+ {
+ g_signal_connect_object (workspace,
+ "open-project",
+ G_CALLBACK (greeter_open_project_cb),
+ self,
+ G_CONNECT_AFTER | G_CONNECT_SWAPPED);
+ self->clone = g_object_new (GBP_TYPE_VCSUI_CLONE_PAGE,
+ NULL);
+ ide_greeter_workspace_add_page (IDE_GREETER_WORKSPACE (workspace),
+ GTK_WIDGET (self->clone),
+ "clone",
+ _("Clone Repository"));
+ ide_greeter_workspace_add_button (IDE_GREETER_WORKSPACE (workspace),
+ g_object_new (GTK_TYPE_BUTTON,
+ "label", _("_Clone Repository…"),
+ "action-name", "greeter.page",
+ "action-target", g_variant_new_string ("clone"),
+ "use-underline", TRUE,
+ NULL),
+ 100);
+ }
+ else if (IDE_IS_PRIMARY_WORKSPACE (workspace))
+ {
+ PanelStatusbar *statusbar;
+ IdeWorkbench *workbench;
+ GtkWidget *popover;
+ GtkImage *image;
+ GtkBox *box;
+
+ workbench = ide_workspace_get_workbench (workspace);
+ statusbar = ide_workspace_get_statusbar (workspace);
+
+ box = g_object_new (GTK_TYPE_BOX,
+ "orientation", GTK_ORIENTATION_HORIZONTAL,
+ "spacing", 6,
+ NULL);
+ image = g_object_new (GTK_TYPE_IMAGE,
+ "icon-name", "builder-vcs-branch-symbolic",
+ "pixel-size", 16,
+ NULL);
+ self->branch_label = g_object_new (GTK_TYPE_LABEL,
+ "xalign", .0f,
+ NULL);
+ gtk_box_append (box, GTK_WIDGET (image));
+ gtk_box_append (box, GTK_WIDGET (self->branch_label));
+
+ popover = gbp_vcsui_switcher_popover_new ();
+ g_object_bind_property (workbench, "vcs",
+ popover, "vcs",
+ G_BINDING_SYNC_CREATE);
+
+ self->branch_button = g_object_new (GTK_TYPE_MENU_BUTTON,
+ "child", box,
+ "direction", GTK_ARROW_UP,
+ "popover", popover,
+ NULL);
+ panel_statusbar_add_prefix (statusbar, G_MININT, GTK_WIDGET (self->branch_button));
+
+ self->vcs_bindings = ide_binding_group_new ();
+ ide_binding_group_bind (self->vcs_bindings, "branch-name",
+ self->branch_label, "label",
+ G_BINDING_SYNC_CREATE);
+ g_object_bind_property (workbench, "vcs",
+ self->vcs_bindings, "source",
+ G_BINDING_SYNC_CREATE);
+ }
+
+ IDE_EXIT;
+}
+
+static void
+gbp_vcsui_workspace_addin_unload (IdeWorkspaceAddin *addin,
+ IdeWorkspace *workspace)
+{
+ GbpVcsuiWorkspaceAddin *self = (GbpVcsuiWorkspaceAddin *)addin;
+
+ IDE_ENTRY;
+
+ g_assert (GBP_IS_VCSUI_WORKSPACE_ADDIN (self));
+
+ if (IDE_IS_GREETER_WORKSPACE (workspace))
+ {
+ ide_greeter_workspace_remove_page (IDE_GREETER_WORKSPACE (workspace),
+ GTK_WIDGET (self->clone));
+ self->clone = NULL;
+ }
+ else if (IDE_IS_PRIMARY_WORKSPACE (workspace))
+ {
+ g_clear_object (&self->vcs_bindings);
+ }
+
+ IDE_EXIT;
+}
+
+static void
+workspace_addin_iface_init (IdeWorkspaceAddinInterface *iface)
+{
+ iface->load = gbp_vcsui_workspace_addin_load;
+ iface->unload = gbp_vcsui_workspace_addin_unload;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpVcsuiWorkspaceAddin, gbp_vcsui_workspace_addin, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKSPACE_ADDIN, workspace_addin_iface_init))
+
+static void
+gbp_vcsui_workspace_addin_class_init (GbpVcsuiWorkspaceAddinClass *klass)
+{
+ g_type_ensure (GBP_TYPE_VCSUI_SWITCHER_POPOVER);
+}
+
+static void
+gbp_vcsui_workspace_addin_init (GbpVcsuiWorkspaceAddin *self)
+{
+}
diff --git a/src/plugins/vcsui/gbp-vcsui-workspace-addin.h b/src/plugins/vcsui/gbp-vcsui-workspace-addin.h
new file mode 100644
index 000000000..1a3b3ba5a
--- /dev/null
+++ b/src/plugins/vcsui/gbp-vcsui-workspace-addin.h
@@ -0,0 +1,31 @@
+/* gbp-vcsui-workspace-addin.h
+ *
+ * Copyright 2022 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_VCSUI_WORKSPACE_ADDIN (gbp_vcsui_workspace_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpVcsuiWorkspaceAddin, gbp_vcsui_workspace_addin, GBP, VCSUI_WORKSPACE_ADDIN, GObject)
+
+G_END_DECLS
diff --git a/src/plugins/vcsui/meson.build b/src/plugins/vcsui/meson.build
index 35d44e02c..f860da30a 100644
--- a/src/plugins/vcsui/meson.build
+++ b/src/plugins/vcsui/meson.build
@@ -1,8 +1,12 @@
plugins_sources += files([
'vcsui-plugin.c',
- 'gbp-vcsui-tree-addin.c',
+ 'gbp-vcsui-application-addin.c',
+ 'gbp-vcsui-clone-page.c',
'gbp-vcsui-editor-page-addin.c',
+ 'gbp-vcsui-switcher-popover.c',
+ 'gbp-vcsui-tree-addin.c',
'gbp-vcsui-workbench-addin.c',
+ 'gbp-vcsui-workspace-addin.c',
])
plugin_vcsui_resources = gnome.compile_resources(
diff --git a/src/plugins/vcsui/vcsui-plugin.c b/src/plugins/vcsui/vcsui-plugin.c
index 0645ba3cc..5e5a46067 100644
--- a/src/plugins/vcsui/vcsui-plugin.c
+++ b/src/plugins/vcsui/vcsui-plugin.c
@@ -23,17 +23,23 @@
#include "config.h"
#include <libpeas/peas.h>
+
#include <libide-editor.h>
#include <libide-gui.h>
#include <libide-tree.h>
+#include "gbp-vcsui-application-addin.h"
#include "gbp-vcsui-editor-page-addin.h"
#include "gbp-vcsui-tree-addin.h"
#include "gbp-vcsui-workbench-addin.h"
+#include "gbp-vcsui-workspace-addin.h"
_IDE_EXTERN void
_gbp_vcsui_register_types (PeasObjectModule *module)
{
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_APPLICATION_ADDIN,
+ GBP_TYPE_VCSUI_APPLICATION_ADDIN);
peas_object_module_register_extension_type (module,
IDE_TYPE_EDITOR_PAGE_ADDIN,
GBP_TYPE_VCSUI_EDITOR_PAGE_ADDIN);
@@ -43,4 +49,7 @@ _gbp_vcsui_register_types (PeasObjectModule *module)
peas_object_module_register_extension_type (module,
IDE_TYPE_WORKBENCH_ADDIN,
GBP_TYPE_VCSUI_WORKBENCH_ADDIN);
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_WORKSPACE_ADDIN,
+ GBP_TYPE_VCSUI_WORKSPACE_ADDIN);
}
diff --git a/src/plugins/vcsui/vcsui.gresource.xml b/src/plugins/vcsui/vcsui.gresource.xml
index 3dd0a29b3..03f8a5be9 100644
--- a/src/plugins/vcsui/vcsui.gresource.xml
+++ b/src/plugins/vcsui/vcsui.gresource.xml
@@ -3,5 +3,7 @@
<gresource prefix="/plugins/vcsui">
<file>vcsui.plugin</file>
<file preprocess="xml-stripblanks">gtk/menus.ui</file>
+ <file preprocess="xml-stripblanks">gbp-vcsui-clone-page.ui</file>
+ <file preprocess="xml-stripblanks">gbp-vcsui-switcher-popover.ui</file>
</gresource>
</gresources>
diff --git a/src/plugins/vcsui/vcsui.plugin b/src/plugins/vcsui/vcsui.plugin
index 8772dac74..9dc625106 100644
--- a/src/plugins/vcsui/vcsui.plugin
+++ b/src/plugins/vcsui/vcsui.plugin
@@ -1,11 +1,12 @@
[Plugin]
Authors=Christian Hergert <christian hergert me>
Builtin=true
-Copyright=Copyright © 2015-2018 Christian Hergert
-Depends=editor;project-tree;
+Copyright=Copyright © 2015-2022 Christian Hergert
+Depends=project-tree;
Description=Provides user interface components to display VCS
Embedded=_gbp_vcsui_register_types
Hidden=true
Module=vcsui
Name=VCS interface extensions
-X-Workspace-Kind=primary;
+X-At-Startup=true
+X-Workspace-Kind=primary;greeter;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]