[gnome-builder] ls: add simple directory view
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] ls: add simple directory view
- Date: Thu, 1 Nov 2018 06:46:03 +0000 (UTC)
commit 45707133b9735434878ba9494b2dd0403ae427e3
Author: Christian Hergert <chergert redhat com>
Date: Tue Oct 30 22:47:58 2018 -0700
ls: add simple directory view
This is handy for users of vim that are used to being able to open a
directory and get a list of files. You can quickly type-ahead search and
press enter to open the target file.
meson_options.txt | 1 +
po/POTFILES.in | 2 +
src/plugins/ls/gbp-ls-model.c | 546 ++++++++++++++++++++++++++++++++
src/plugins/ls/gbp-ls-model.h | 44 +++
src/plugins/ls/gbp-ls-plugin.c | 34 ++
src/plugins/ls/gbp-ls-view.c | 353 +++++++++++++++++++++
src/plugins/ls/gbp-ls-view.h | 36 +++
src/plugins/ls/gbp-ls-view.ui | 74 +++++
src/plugins/ls/gbp-ls-workbench-addin.c | 179 +++++++++++
src/plugins/ls/gbp-ls-workbench-addin.h | 31 ++
src/plugins/ls/ls.gresource.xml | 9 +
src/plugins/ls/ls.plugin | 9 +
src/plugins/ls/meson.build | 19 ++
src/plugins/meson.build | 2 +
14 files changed, 1339 insertions(+)
---
diff --git a/meson_options.txt b/meson_options.txt
index ae5c8d73a..68fe4227c 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -58,6 +58,7 @@ option('with_html_completion', type: 'boolean')
option('with_html_preview', type: 'boolean')
option('with_jedi', type: 'boolean')
option('with_jhbuild', type: 'boolean')
+option('with_ls', type: 'boolean')
option('with_make', type: 'boolean')
option('with_maven', type: 'boolean')
option('with_meson', type: 'boolean')
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e319b7c52..e95b49d10 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -202,6 +202,8 @@ src/plugins/grep/gtk/menus.ui
src/plugins/html-preview/gtk/menus.ui
src/plugins/html-preview/html_preview.py
src/plugins/jedi/jedi_plugin.py
+src/plugins/ls/gbp-ls-view.c
+src/plugins/ls/gbp-ls-view.ui
src/plugins/make/make_plugin.py
src/plugins/maven/maven_plugin.py
src/plugins/meson/gbp-meson-build-system.c
diff --git a/src/plugins/ls/gbp-ls-model.c b/src/plugins/ls/gbp-ls-model.c
new file mode 100644
index 000000000..252b0b756
--- /dev/null
+++ b/src/plugins/ls/gbp-ls-model.c
@@ -0,0 +1,546 @@
+/* gbp-ls-model.c
+ *
+ * Copyright © 2018 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
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "gbp-ls-model"
+
+#include <ide.h>
+
+#include "gbp-ls-model.h"
+
+struct _GbpLsModel
+{
+ GObject parent_instance;
+ GFile *directory;
+ GPtrArray *items;
+};
+
+enum {
+ PROP_0,
+ PROP_DIRECTORY,
+ N_PROPS
+};
+
+static void async_initable_iface_init (GAsyncInitableIface *iface);
+static void tree_model_iface_init (GtkTreeModelIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GbpLsModel, gbp_ls_model, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, tree_model_iface_init))
+
+static GParamSpec *properties [N_PROPS];
+
+static gint
+compare_by_name (gconstpointer a,
+ gconstpointer b)
+{
+ GFileInfo *info_a = *(GFileInfo **)a;
+ GFileInfo *info_b = *(GFileInfo **)b;
+ GFileType type_a = g_file_info_get_file_type (info_a);
+ GFileType type_b = g_file_info_get_file_type (info_b);
+ const gchar *display_a;
+ const gchar *display_b;
+
+ if (type_a != type_b)
+ {
+ if (type_a == G_FILE_TYPE_DIRECTORY)
+ return -1;
+ else if (type_b == G_FILE_TYPE_DIRECTORY)
+ return 1;
+ }
+
+ display_a = g_file_info_get_display_name (info_a);
+ display_b = g_file_info_get_display_name (info_b);
+
+ if (g_strcmp0 (display_a, "..") == 0)
+ return -1;
+ else if (g_strcmp0 (display_b, "..") == 0)
+ return 1;
+ else
+ return g_utf8_collate (display_a, display_b);
+}
+
+static void
+gbp_ls_model_finalize (GObject *object)
+{
+ GbpLsModel *self = (GbpLsModel *)object;
+
+ g_clear_object (&self->directory);
+ g_clear_pointer (&self->items, g_ptr_array_unref);
+
+ G_OBJECT_CLASS (gbp_ls_model_parent_class)->finalize (object);
+}
+
+static void
+gbp_ls_model_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpLsModel *self = GBP_LS_MODEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_DIRECTORY:
+ g_value_set_object (value, self->directory);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_ls_model_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpLsModel *self = GBP_LS_MODEL (object);
+
+ switch (prop_id)
+ {
+ case PROP_DIRECTORY:
+ self->directory = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_ls_model_class_init (GbpLsModelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gbp_ls_model_finalize;
+ object_class->get_property = gbp_ls_model_get_property;
+ object_class->set_property = gbp_ls_model_set_property;
+
+ properties [PROP_DIRECTORY] =
+ g_param_spec_object ("directory",
+ "Directory",
+ "The directory to display contents from",
+ G_TYPE_FILE,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gbp_ls_model_init (GbpLsModel *self)
+{
+ self->items = g_ptr_array_new_with_free_func (g_object_unref);
+}
+
+static gint
+gbp_ls_model_get_n_columns (GtkTreeModel *model)
+{
+ return GBP_LS_MODEL_N_COLUMNS;
+}
+
+static GType
+gbp_ls_model_get_column_type (GtkTreeModel *model,
+ gint column)
+{
+ switch (column)
+ {
+ case GBP_LS_MODEL_COLUMN_GICON: return G_TYPE_ICON;
+ case GBP_LS_MODEL_COLUMN_NAME: return G_TYPE_STRING;
+ case GBP_LS_MODEL_COLUMN_SIZE: return G_TYPE_INT64;
+ case GBP_LS_MODEL_COLUMN_MODIFIED: return G_TYPE_DATE_TIME;
+ case GBP_LS_MODEL_COLUMN_FILE: return G_TYPE_FILE;
+ case GBP_LS_MODEL_N_COLUMNS:
+ default:
+ g_return_val_if_reached (G_TYPE_INVALID);
+ }
+}
+
+static gboolean
+gbp_ls_model_get_iter (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkTreePath *path)
+{
+ GbpLsModel *self = (GbpLsModel *)model;
+ gint *indicies;
+ gint depth = 0;
+
+ g_assert (GBP_IS_LS_MODEL (model));
+ g_assert (iter != NULL);
+
+ indicies = gtk_tree_path_get_indices_with_depth (path, &depth);
+
+ if (depth == 1 && indicies[0] < self->items->len)
+ {
+ iter->user_data = g_ptr_array_index (self->items, indicies[0]);
+ iter->user_data2 = GUINT_TO_POINTER (indicies[0]);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+gbp_ls_model_get_value (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gint column,
+ GValue *value)
+{
+ GbpLsModel *self = (GbpLsModel *)model;
+ GFileInfo *info;
+
+ g_assert (GBP_IS_LS_MODEL (self));
+ g_assert (iter != NULL);
+ g_assert (value != NULL);
+
+ info = iter->user_data;
+
+ g_assert (G_IS_FILE_INFO (info));
+
+ switch (column)
+ {
+ case GBP_LS_MODEL_COLUMN_GICON:
+ g_value_init (value, G_TYPE_ICON);
+ g_value_set_object (value,
+ g_file_info_get_attribute_object (info,
+ G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON));
+ break;
+
+ case GBP_LS_MODEL_COLUMN_NAME:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, g_file_info_get_display_name (info));
+ break;
+
+ case GBP_LS_MODEL_COLUMN_SIZE:
+ g_value_init (value, G_TYPE_INT64);
+ g_value_set_int64 (value, g_file_info_get_size (info));
+ break;
+
+ case GBP_LS_MODEL_COLUMN_MODIFIED:
+ {
+ GTimeVal tv;
+
+ g_file_info_get_modification_time (info, &tv);
+ g_value_init (value, G_TYPE_DATE_TIME);
+ g_value_take_boxed (value, g_date_time_new_from_timeval_local (&tv));
+
+ break;
+ }
+
+ case GBP_LS_MODEL_COLUMN_FILE:
+ {
+ g_value_init (value, G_TYPE_FILE);
+ g_value_take_object (value,
+ g_file_get_child (self->directory,
+ g_file_info_get_name (info)));
+ break;
+ }
+
+ case GBP_LS_MODEL_COLUMN_TYPE:
+ {
+ g_value_init (value, G_TYPE_FILE_TYPE);
+ g_value_set_enum (value, g_file_info_get_file_type (info));
+ break;
+ }
+
+ case GBP_LS_MODEL_N_COLUMNS:
+ default:
+ g_return_if_reached ();
+ }
+}
+
+static gint
+gbp_ls_model_iter_n_children (GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ GbpLsModel *self = (GbpLsModel *)model;
+
+ g_assert (GBP_IS_LS_MODEL (self));
+
+ return iter ? 0 : self->items->len;
+}
+
+static gboolean
+gbp_ls_model_iter_children (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent)
+{
+ GbpLsModel *self = (GbpLsModel *)model;
+
+ g_assert (GBP_IS_LS_MODEL (self));
+
+ if (iter != NULL || self->items->len == 0)
+ return FALSE;
+
+ iter->user_data = g_ptr_array_index (self->items, 0);
+ iter->user_data2 = GUINT_TO_POINTER (0);
+
+ return TRUE;
+}
+
+static gboolean
+gbp_ls_model_iter_next (GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ GbpLsModel *self = (GbpLsModel *)model;
+ guint index_;
+
+ g_assert (GBP_IS_LS_MODEL (self));
+ g_assert (iter != NULL);
+
+ index_ = GPOINTER_TO_UINT (iter->user_data2);
+
+ if (index_ != G_MAXUINT && index_ + 1 < self->items->len)
+ {
+ index_++;
+
+ iter->user_data = g_ptr_array_index (self->items, index_);
+ iter->user_data2 = GUINT_TO_POINTER (index_);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+gbp_ls_model_iter_nth_child (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent,
+ gint n)
+{
+ GbpLsModel *self = (GbpLsModel *)model;
+
+ g_assert (GBP_IS_LS_MODEL (model));
+ g_assert (iter != NULL);
+
+ if (parent != NULL)
+ return FALSE;
+
+ if (n < self->items->len)
+ {
+ iter->user_data = g_ptr_array_index (self->items, n);
+ iter->user_data2 = GINT_TO_POINTER (n);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static GtkTreePath *
+gbp_ls_model_get_path (GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ g_assert (GBP_IS_LS_MODEL (model));
+ g_assert (iter != NULL);
+
+ return gtk_tree_path_new_from_indices (GPOINTER_TO_UINT (iter->user_data2), -1);
+}
+
+static gboolean
+gbp_ls_model_iter_has_child (GtkTreeModel *model,
+ GtkTreeIter *parent)
+{
+ GbpLsModel *self = (GbpLsModel *)model;
+
+ g_assert (GBP_IS_LS_MODEL (self));
+
+ return parent ? 0 : self->items->len > 0;
+}
+
+static void
+tree_model_iface_init (GtkTreeModelIface *iface)
+{
+ iface->get_n_columns = gbp_ls_model_get_n_columns;
+ iface->get_iter = gbp_ls_model_get_iter;
+ iface->get_column_type = gbp_ls_model_get_column_type;
+ iface->get_value = gbp_ls_model_get_value;
+ iface->iter_n_children = gbp_ls_model_iter_n_children;
+ iface->iter_children = gbp_ls_model_iter_children;
+ iface->iter_next = gbp_ls_model_iter_next;
+ iface->iter_nth_child = gbp_ls_model_iter_nth_child;
+ iface->iter_has_child = gbp_ls_model_iter_has_child;
+ iface->get_path = gbp_ls_model_get_path;
+}
+
+static void
+gbp_ls_model_worker (IdeTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ g_autoptr(GFileEnumerator) enumerator = NULL;
+ g_autoptr(GPtrArray) items = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GIcon) icon = NULL;
+ g_autoptr(GFile) parent = NULL;
+ GFile *directory = task_data;
+ GFileInfo *info;
+
+ g_assert (IDE_IS_TASK (task));
+ g_assert (G_IS_FILE (directory));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ enumerator = g_file_enumerate_children (directory,
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME","
+ G_FILE_ATTRIBUTE_STANDARD_SIZE","
+ G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED",",
+ G_FILE_QUERY_INFO_NONE,
+ cancellable,
+ &error);
+
+ if (enumerator == NULL)
+ {
+ ide_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ /* Prefer folder-symbolic over queried icon */
+ icon = g_themed_icon_new ("folder-symbolic");
+
+ items = g_ptr_array_new_with_free_func (g_object_unref);
+
+ if ((parent = g_file_get_parent (directory)))
+ {
+ g_autoptr(GFileInfo) dot = NULL;
+
+ dot = g_file_query_info (parent,
+ G_FILE_ATTRIBUTE_STANDARD_SIZE","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED",",
+ G_FILE_QUERY_INFO_NONE,
+ cancellable,
+ NULL);
+
+ if (dot != NULL)
+ {
+ g_file_info_set_name (dot, "..");
+ g_file_info_set_display_name (dot, "..");
+ g_file_info_set_file_type (dot, G_FILE_TYPE_DIRECTORY);
+ g_file_info_set_attribute_object (dot,
+ G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON,
+ G_OBJECT (icon));
+ g_ptr_array_add (items, g_steal_pointer (&dot));
+ }
+ }
+
+ while ((info = g_file_enumerator_next_file (enumerator, cancellable, &error)))
+ {
+ GFileType file_type = g_file_info_get_file_type (info);
+
+ /* Prefer our symbolic icon for folders */
+ if (file_type == G_FILE_TYPE_DIRECTORY)
+ g_file_info_set_attribute_object (info, G_FILE_ATTRIBUTE_STANDARD_SYMBOLIC_ICON, G_OBJECT (icon));
+
+ g_ptr_array_add (items, info);
+ }
+
+ if (error != NULL)
+ {
+ ide_task_return_error (task, g_steal_pointer (&error));
+ return;
+ }
+
+ g_ptr_array_sort (items, compare_by_name);
+
+ ide_task_return_pointer (task,
+ g_steal_pointer (&items),
+ (GDestroyNotify)g_ptr_array_unref);
+}
+
+static void
+gbp_ls_model_init_async (GAsyncInitable *initable,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GbpLsModel *self = (GbpLsModel *)initable;
+ g_autoptr(IdeTask) task = NULL;
+
+ g_assert (GBP_IS_LS_MODEL (self));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_ls_model_init_async);
+ ide_task_set_priority (task, io_priority);
+
+ if (self->directory == NULL)
+ {
+ ide_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_FILENAME,
+ "No directory found to enumerate");
+ return;
+ }
+
+ ide_task_set_task_data (task, g_object_ref (self->directory), g_object_unref);
+ ide_task_run_in_thread (task, gbp_ls_model_worker);
+}
+
+static gboolean
+gbp_ls_model_init_finish (GAsyncInitable *initable,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_autoptr(GPtrArray) items = NULL;
+ GbpLsModel *self = (GbpLsModel *)initable;
+
+ g_assert (GBP_IS_LS_MODEL (initable));
+ g_assert (IDE_IS_TASK (result));
+
+ items = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+ if (items != NULL)
+ {
+ g_clear_pointer (&self->items, g_ptr_array_unref);
+ self->items = g_steal_pointer (&items);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+async_initable_iface_init (GAsyncInitableIface *iface)
+{
+ iface->init_async = gbp_ls_model_init_async;
+ iface->init_finish = gbp_ls_model_init_finish;
+}
+
+GbpLsModel *
+gbp_ls_model_new (GFile *directory)
+{
+ g_return_val_if_fail (G_IS_FILE (directory), NULL);
+
+ return g_object_new (GBP_TYPE_LS_MODEL,
+ "directory", directory,
+ NULL);
+}
+
+GFile *
+gbp_ls_model_get_directory (GbpLsModel *self)
+{
+ g_return_val_if_fail (GBP_IS_LS_MODEL (self), NULL);
+
+ return self->directory;
+}
diff --git a/src/plugins/ls/gbp-ls-model.h b/src/plugins/ls/gbp-ls-model.h
new file mode 100644
index 000000000..00993a761
--- /dev/null
+++ b/src/plugins/ls/gbp-ls-model.h
@@ -0,0 +1,44 @@
+/* gbp-ls-model.h
+ *
+ * Copyright © 2018 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 <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_LS_MODEL (gbp_ls_model_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpLsModel, gbp_ls_model, GBP, LS_MODEL, GObject)
+
+typedef enum {
+ GBP_LS_MODEL_COLUMN_GICON,
+ GBP_LS_MODEL_COLUMN_NAME,
+ GBP_LS_MODEL_COLUMN_SIZE,
+ GBP_LS_MODEL_COLUMN_MODIFIED,
+ GBP_LS_MODEL_COLUMN_FILE,
+ GBP_LS_MODEL_COLUMN_TYPE,
+ GBP_LS_MODEL_N_COLUMNS
+} GbpLsModelColumn;
+
+GbpLsModel *gbp_ls_model_new (GFile *directory);
+GFile *gbp_ls_model_get_directory (GbpLsModel *self);
+
+G_END_DECLS
diff --git a/src/plugins/ls/gbp-ls-plugin.c b/src/plugins/ls/gbp-ls-plugin.c
new file mode 100644
index 000000000..b0842a515
--- /dev/null
+++ b/src/plugins/ls/gbp-ls-plugin.c
@@ -0,0 +1,34 @@
+/* gbp-ls-plugin.c
+ *
+ * Copyright © 2018 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
+ */
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+#include <ide.h>
+
+#include "gbp-ls-workbench-addin.h"
+
+void
+gbp_ls_register_types (PeasObjectModule *module)
+{
+ peas_object_module_register_extension_type (module,
+ IDE_TYPE_WORKBENCH_ADDIN,
+ GBP_TYPE_LS_WORKBENCH_ADDIN);
+}
diff --git a/src/plugins/ls/gbp-ls-view.c b/src/plugins/ls/gbp-ls-view.c
new file mode 100644
index 000000000..0040b5ec9
--- /dev/null
+++ b/src/plugins/ls/gbp-ls-view.c
@@ -0,0 +1,353 @@
+/* gbp-ls-view.c
+ *
+ * Copyright © 2018 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
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "gbp-ls-view"
+
+#include <glib/gi18n.h>
+
+#include "gbp-ls-model.h"
+#include "gbp-ls-view.h"
+
+struct _GbpLsView
+{
+ IdeLayoutView parent_instance;
+
+ GCancellable *model_cancellable;
+ GbpLsModel *model;
+
+ GtkScrolledWindow *scroller;
+ GtkTreeView *tree_view;
+ GtkTreeViewColumn *modified_column;
+ GtkCellRenderer *modified_cell;
+ GtkTreeViewColumn *size_column;
+ GtkCellRenderer *size_cell;
+
+ guint close_on_activate : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_CLOSE_ON_ACTIVATE,
+ PROP_DIRECTORY,
+ N_PROPS
+};
+
+G_DEFINE_TYPE (GbpLsView, gbp_ls_view, IDE_TYPE_LAYOUT_VIEW)
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gbp_ls_view_row_activated_cb (GbpLsView *self,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ GtkTreeView *tree_view)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ g_assert (GBP_IS_LS_VIEW (self));
+ g_assert (path != NULL);
+
+ if ((model = gtk_tree_view_get_model (tree_view)) &&
+ gtk_tree_model_get_iter (model, &iter, path))
+ {
+ g_autoptr(GFile) file = NULL;
+ GFileType file_type;
+
+ gtk_tree_model_get (model, &iter,
+ GBP_LS_MODEL_COLUMN_FILE, &file,
+ GBP_LS_MODEL_COLUMN_TYPE, &file_type,
+ -1);
+
+ if (file_type == G_FILE_TYPE_DIRECTORY)
+ gbp_ls_view_set_directory (self, file);
+ else
+ {
+ g_autoptr(IdeUri) uri = ide_uri_new_from_file (file);
+ IdeWorkbench *workbench = ide_widget_get_workbench (GTK_WIDGET (self));
+
+ ide_workbench_open_uri_async (workbench,
+ uri,
+ NULL,
+ IDE_WORKBENCH_OPEN_FLAGS_NONE,
+ NULL,
+ NULL,
+ NULL);
+
+ if (self->close_on_activate)
+ dzl_gtk_widget_action (GTK_WIDGET (self), "layoutstack", "close-view", NULL);
+ }
+ }
+}
+
+static void
+modified_cell_data_func (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ g_autofree gchar *format = NULL;
+ g_autoptr(GDateTime) when = NULL;
+
+ gtk_tree_model_get (tree_model, iter,
+ GBP_LS_MODEL_COLUMN_MODIFIED, &when,
+ -1);
+ format = dzl_g_date_time_format_for_display (when);
+ g_object_set (cell, "text", format, NULL);
+}
+
+static void
+size_cell_data_func (GtkCellLayout *cell_layout,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ g_autofree gchar *format = NULL;
+ gint64 size = -1;
+
+ gtk_tree_model_get (tree_model, iter,
+ GBP_LS_MODEL_COLUMN_SIZE, &size,
+ -1);
+ format = g_format_size (size);
+ g_object_set (cell, "text", format, NULL);
+}
+
+static void
+gbp_ls_view_finalize (GObject *object)
+{
+ GbpLsView *self = (GbpLsView *)object;
+
+ g_clear_object (&self->model_cancellable);
+ g_clear_object (&self->model);
+
+ G_OBJECT_CLASS (gbp_ls_view_parent_class)->finalize (object);
+}
+
+static void
+gbp_ls_view_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GbpLsView *self = GBP_LS_VIEW (object);
+
+ switch (prop_id)
+ {
+ case PROP_DIRECTORY:
+ g_value_set_object (value, gbp_ls_view_get_directory (self));
+ break;
+
+ case PROP_CLOSE_ON_ACTIVATE:
+ g_value_set_boolean (value, self->close_on_activate);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_ls_view_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GbpLsView *self = GBP_LS_VIEW (object);
+
+ switch (prop_id)
+ {
+ case PROP_DIRECTORY:
+ gbp_ls_view_set_directory (self, g_value_get_object (value));
+ break;
+
+ case PROP_CLOSE_ON_ACTIVATE:
+ self->close_on_activate = g_value_get_boolean (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gbp_ls_view_class_init (GbpLsViewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = gbp_ls_view_finalize;
+ object_class->get_property = gbp_ls_view_get_property;
+ object_class->set_property = gbp_ls_view_set_property;
+
+ properties [PROP_DIRECTORY] =
+ g_param_spec_object ("directory",
+ "Directory",
+ "The directory to be displayed",
+ G_TYPE_FILE,
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_CLOSE_ON_ACTIVATE] =
+ g_param_spec_boolean ("close-on-activate", NULL, NULL,
+ FALSE,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/builder/plugins/ls/gbp-ls-view.ui");
+ gtk_widget_class_bind_template_child (widget_class, GbpLsView, modified_cell);
+ gtk_widget_class_bind_template_child (widget_class, GbpLsView, modified_column);
+ gtk_widget_class_bind_template_child (widget_class, GbpLsView, size_cell);
+ gtk_widget_class_bind_template_child (widget_class, GbpLsView, size_column);
+ gtk_widget_class_bind_template_child (widget_class, GbpLsView, scroller);
+ gtk_widget_class_bind_template_child (widget_class, GbpLsView, tree_view);
+}
+
+static void
+gbp_ls_view_init (GbpLsView *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ ide_layout_view_set_icon_name (IDE_LAYOUT_VIEW (self), "folder-symbolic");
+
+ g_signal_connect_object (self->tree_view,
+ "row-activated",
+ G_CALLBACK (gbp_ls_view_row_activated_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (self->size_column),
+ self->size_cell,
+ size_cell_data_func,
+ NULL, NULL);
+
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (self->modified_column),
+ self->modified_cell,
+ modified_cell_data_func,
+ NULL, NULL);
+}
+
+GtkWidget *
+gbp_ls_view_new (void)
+{
+ return g_object_new (GBP_TYPE_LS_VIEW, NULL);
+}
+
+GFile *
+gbp_ls_view_get_directory (GbpLsView *self)
+{
+ g_return_val_if_fail (GBP_IS_LS_VIEW (self), NULL);
+
+ if (self->model != NULL)
+ return gbp_ls_model_get_directory (GBP_LS_MODEL (self->model));
+
+ return NULL;
+}
+
+static void
+gbp_ls_view_init_model_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GbpLsModel *model = (GbpLsModel *)object;
+ g_autoptr(GbpLsView) self = user_data;
+ g_autoptr(GError) error = NULL;
+ GtkTreeIter iter;
+
+ g_assert (GBP_IS_LS_MODEL (model));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (GBP_IS_LS_VIEW (self));
+
+ if (model != self->model)
+ return;
+
+ if (!g_async_initable_init_finish (G_ASYNC_INITABLE (model), result, &error))
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ ide_layout_view_report_error (IDE_LAYOUT_VIEW (self),
+ _("Failed to load directory: %s"),
+ error->message);
+ return;
+ }
+
+ gtk_tree_view_set_model (self->tree_view, GTK_TREE_MODEL (model));
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
+ {
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (self->tree_view));
+ gtk_tree_selection_select_iter (selection, &iter);
+ }
+
+ gtk_widget_grab_focus (GTK_WIDGET (self->tree_view));
+}
+
+void
+gbp_ls_view_set_directory (GbpLsView *self,
+ GFile *directory)
+{
+ g_autofree gchar *title = NULL;
+ g_autofree gchar *name = NULL;
+ GFile *old_directory;
+
+ g_return_if_fail (GBP_IS_LS_VIEW (self));
+ g_return_if_fail (!directory || G_IS_FILE (directory));
+
+ if (directory == NULL)
+ {
+ IdeContext *context = ide_widget_get_context (GTK_WIDGET (self));
+ IdeVcs *vcs = ide_context_get_vcs (context);
+
+ directory = ide_vcs_get_working_directory (vcs);
+ }
+
+ g_assert (directory != NULL);
+
+ old_directory = gbp_ls_view_get_directory (self);
+
+ if (directory != NULL &&
+ old_directory != NULL &&
+ g_file_equal (directory, old_directory))
+ return;
+
+ g_clear_object (&self->model);
+
+ g_cancellable_cancel (self->model_cancellable);
+ g_clear_object (&self->model_cancellable);
+
+ self->model_cancellable = g_cancellable_new ();
+ self->model = gbp_ls_model_new (directory);
+
+ g_async_initable_init_async (G_ASYNC_INITABLE (self->model),
+ G_PRIORITY_DEFAULT,
+ self->model_cancellable,
+ gbp_ls_view_init_model_cb,
+ g_object_ref (self));
+
+ name = g_file_get_basename (directory);
+ title = g_strdup_printf (_("%s — Directory"), name);
+ ide_layout_view_set_title (IDE_LAYOUT_VIEW (self), title);
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DIRECTORY]);
+}
diff --git a/src/plugins/ls/gbp-ls-view.h b/src/plugins/ls/gbp-ls-view.h
new file mode 100644
index 000000000..231004753
--- /dev/null
+++ b/src/plugins/ls/gbp-ls-view.h
@@ -0,0 +1,36 @@
+/* gbp-ls-view.h
+ *
+ * Copyright © 2018 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 <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_LS_VIEW (gbp_ls_view_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpLsView, gbp_ls_view, GBP, LS_VIEW, IdeLayoutView)
+
+GtkWidget *gbp_ls_view_new (void);
+GFile *gbp_ls_view_get_directory (GbpLsView *self);
+void gbp_ls_view_set_directory (GbpLsView *self,
+ GFile *directory);
+
+G_END_DECLS
diff --git a/src/plugins/ls/gbp-ls-view.ui b/src/plugins/ls/gbp-ls-view.ui
new file mode 100644
index 000000000..cc5a797f4
--- /dev/null
+++ b/src/plugins/ls/gbp-ls-view.ui
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GbpLsView" parent="IdeLayoutView">
+ <child>
+ <object class="GtkScrolledWindow" id="scroller">
+ <property name="vexpand">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkTreeView" id="tree_view">
+ <property name="vexpand">true</property>
+ <property name="headers-visible">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkTreeViewColumn" id="name_column">
+ <property name="title" translatable="yes">Name</property>
+ <property name="expand">true</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkCellRendererPixbuf" id="pixbuf_cell">
+ <property name="xpad">8</property>
+ <property name="ypad">6</property>
+ </object>
+ <attributes>
+ <attribute name="gicon">0</attribute>
+ </attributes>
+ <cell-packing>
+ <property name="expand">false</property>
+ </cell-packing>
+ </child>
+ <child>
+ <object class="GtkCellRendererText" id="name_cell">
+ <property name="ellipsize">end</property>
+ </object>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ <cell-packing>
+ <property name="expand">true</property>
+ </cell-packing>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="size_column">
+ <property name="title" translatable="yes">Size</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkCellRendererText" id="size_cell">
+ </object>
+ <cell-packing>
+ <property name="expand">true</property>
+ </cell-packing>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="modified_column">
+ <property name="title" translatable="yes">Modified</property>
+ <property name="visible">true</property>
+ <child>
+ <object class="GtkCellRendererText" id="modified_cell">
+ </object>
+ <cell-packing>
+ <property name="expand">true</property>
+ </cell-packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/src/plugins/ls/gbp-ls-workbench-addin.c b/src/plugins/ls/gbp-ls-workbench-addin.c
new file mode 100644
index 000000000..5786a683b
--- /dev/null
+++ b/src/plugins/ls/gbp-ls-workbench-addin.c
@@ -0,0 +1,179 @@
+/* gbp-ls-workbench-addin.c
+ *
+ * Copyright © 2018 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
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "gbp-ls-workbench-addin"
+
+#include "gbp-ls-workbench-addin.h"
+#include "gbp-ls-view.h"
+
+struct _GbpLsWorkbenchAddin
+{
+ GObject parent_instance;
+ IdeWorkbench *workbench;
+};
+
+typedef struct
+{
+ GFile *file;
+ GbpLsView *view;
+} LocateView;
+
+static gchar *
+gbp_ls_workbench_addin_get_id (IdeWorkbenchAddin *addin)
+{
+ return g_strdup ("directory");
+}
+
+static gboolean
+gbp_ls_workbench_addin_can_open (IdeWorkbenchAddin *addin,
+ IdeUri *uri,
+ const gchar *content_type,
+ gint *priority)
+{
+ g_assert (GBP_IS_LS_WORKBENCH_ADDIN (addin));
+ g_assert (priority != NULL);
+
+ if (g_strcmp0 (content_type, "inode/directory") == 0)
+ {
+ *priority = -100;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+locate_view (GtkWidget *view,
+ gpointer user_data)
+{
+ LocateView *locate = user_data;
+ GFile *file;
+
+ g_assert (IDE_IS_LAYOUT_VIEW (view));
+ g_assert (locate != NULL);
+
+ if (locate->view != NULL)
+ return;
+
+ if (!GBP_IS_LS_VIEW (view))
+ return;
+
+ file = gbp_ls_view_get_directory (GBP_LS_VIEW (view));
+ if (g_file_equal (file, locate->file))
+ locate->view = GBP_LS_VIEW (view);
+}
+
+static void
+gbp_ls_workbench_addin_open_async (IdeWorkbenchAddin *addin,
+ IdeUri *uri,
+ const gchar *content_type,
+ IdeWorkbenchOpenFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GbpLsWorkbenchAddin *self = (GbpLsWorkbenchAddin *)addin;
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GFile) file = NULL;
+ IdePerspective *editor;
+ GbpLsView *view;
+ LocateView locate = { 0 };
+
+ g_assert (GBP_IS_LS_WORKBENCH_ADDIN (self));
+ g_assert (IDE_IS_WORKBENCH (self->workbench));
+ g_assert (uri != NULL);
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_ls_workbench_addin_open_async);
+
+ editor = ide_workbench_get_perspective_by_name (self->workbench, "editor");
+ file = ide_uri_to_file (uri);
+
+ /* First try to find an existing view for the file */
+ locate.file = file;
+ ide_workbench_views_foreach (self->workbench, locate_view, &locate);
+ if (locate.view != NULL)
+ {
+ ide_workbench_focus (self->workbench, GTK_WIDGET (locate.view));
+ ide_task_return_boolean (task, TRUE);
+ return;
+ }
+
+ view = g_object_new (GBP_TYPE_LS_VIEW,
+ "close-on-activate", TRUE,
+ "directory", file,
+ "visible", TRUE,
+ NULL);
+ gtk_container_add (GTK_CONTAINER (editor), GTK_WIDGET (view));
+
+ ide_task_return_boolean (task, TRUE);
+}
+
+static gboolean
+gbp_ls_workbench_addin_open_finish (IdeWorkbenchAddin *addin,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_assert (GBP_IS_LS_WORKBENCH_ADDIN (addin));
+ g_assert (IDE_IS_TASK (result));
+
+ return ide_task_propagate_boolean (IDE_TASK (result), error);
+}
+
+static void
+gbp_ls_workbench_addin_load (IdeWorkbenchAddin *addin,
+ IdeWorkbench *workbench)
+{
+ GBP_LS_WORKBENCH_ADDIN (addin)->workbench = workbench;
+}
+
+static void
+gbp_ls_workbench_addin_unload (IdeWorkbenchAddin *addin,
+ IdeWorkbench *workbench)
+{
+ GBP_LS_WORKBENCH_ADDIN (addin)->workbench = NULL;
+}
+
+static void
+workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface)
+{
+ iface->get_id = gbp_ls_workbench_addin_get_id;
+ iface->can_open = gbp_ls_workbench_addin_can_open;
+ iface->open_async = gbp_ls_workbench_addin_open_async;
+ iface->open_finish = gbp_ls_workbench_addin_open_finish;
+ iface->load = gbp_ls_workbench_addin_load;
+ iface->unload = gbp_ls_workbench_addin_unload;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GbpLsWorkbenchAddin, gbp_ls_workbench_addin, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKBENCH_ADDIN, workbench_addin_iface_init))
+
+static void
+gbp_ls_workbench_addin_class_init (GbpLsWorkbenchAddinClass *klass)
+{
+}
+
+static void
+gbp_ls_workbench_addin_init (GbpLsWorkbenchAddin *self)
+{
+}
diff --git a/src/plugins/ls/gbp-ls-workbench-addin.h b/src/plugins/ls/gbp-ls-workbench-addin.h
new file mode 100644
index 000000000..b494e30e5
--- /dev/null
+++ b/src/plugins/ls/gbp-ls-workbench-addin.h
@@ -0,0 +1,31 @@
+/* gbp-ls-workbench-addin.h
+ *
+ * Copyright © 2018 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 <ide.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_LS_WORKBENCH_ADDIN (gbp_ls_workbench_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpLsWorkbenchAddin, gbp_ls_workbench_addin, GBP, LS_WORKBENCH_ADDIN, GObject)
+
+G_END_DECLS
diff --git a/src/plugins/ls/ls.gresource.xml b/src/plugins/ls/ls.gresource.xml
new file mode 100644
index 000000000..26e2dec94
--- /dev/null
+++ b/src/plugins/ls/ls.gresource.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/builder/plugins">
+ <file>ls.plugin</file>
+ </gresource>
+ <gresource prefix="/org/gnome/builder/plugins/ls">
+ <file preprocess="xml-stripblanks">gbp-ls-view.ui</file>
+ </gresource>
+</gresources>
diff --git a/src/plugins/ls/ls.plugin b/src/plugins/ls/ls.plugin
new file mode 100644
index 000000000..18af04853
--- /dev/null
+++ b/src/plugins/ls/ls.plugin
@@ -0,0 +1,9 @@
+[Plugin]
+Module=ls
+Name=View Directory Listings
+Description=List files in a directory as a view
+Authors=Christian Hergert <christian hergert me>
+Copyright=Copyright © 2018 Christian Hergert
+Builtin=true
+Depends=editor;
+Embedded=gbp_ls_register_types
diff --git a/src/plugins/ls/meson.build b/src/plugins/ls/meson.build
new file mode 100644
index 000000000..1dcea074e
--- /dev/null
+++ b/src/plugins/ls/meson.build
@@ -0,0 +1,19 @@
+if get_option('with_ls')
+
+grep_resources = gnome.compile_resources(
+ 'ls-resources',
+ 'ls.gresource.xml',
+ c_name: 'gbp_ls',
+)
+
+grep_sources = [
+ 'gbp-ls-model.c',
+ 'gbp-ls-plugin.c',
+ 'gbp-ls-view.c',
+ 'gbp-ls-workbench-addin.c',
+]
+
+gnome_builder_plugins_sources += files(grep_sources)
+gnome_builder_plugins_sources += grep_resources[0]
+
+endif
diff --git a/src/plugins/meson.build b/src/plugins/meson.build
index 76603122e..14e7061a1 100644
--- a/src/plugins/meson.build
+++ b/src/plugins/meson.build
@@ -43,6 +43,7 @@ subdir('html-completion')
subdir('html-preview')
subdir('jedi')
subdir('jhbuild')
+subdir('ls')
subdir('make')
subdir('maven')
subdir('meson')
@@ -129,6 +130,7 @@ status += [
'HTML Preview .......... : @0@'.format(get_option('with_html_preview')),
'Python Jedi ........... : @0@'.format(get_option('with_jedi')),
'JHBuild ............... : @0@'.format(get_option('with_jhbuild')),
+ 'Directory View ........ : @0@'.format(get_option('with_ls')),
'Make .................. : @0@'.format(get_option('with_make')),
'Maven.................. : @0@'.format(get_option('with_maven')),
'Meson ................. : @0@'.format(get_option('with_meson')),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]