[geany/geany-plugins] ca1912: Add file operations to Project Organizer.

Daniel Guerrero git-noreply at xxxxx
Mon Apr 1 01:03:38 UTC 2019


Branch:      refs/heads/master
Author:      Daniel Guerrero <dgm at aquilessolutions.com>
Committer:   Daniel Guerrero <dgm at aquilessolutions.com>
Date:        Fri, 10 Aug 2018 15:07:25 UTC
Commit:      ca1912d6c5ebf671af36851b63c2508da6b464e0
             https://github.com/geany/geany-plugins/commit/ca1912d6c5ebf671af36851b63c2508da6b464e0

Log Message:
-----------
Add file operations to Project Organizer.

Add file and directory creation, renaming and removal operations to the Project Organizer sidebar.


Modified Paths:
--------------
    projectorganizer/src/prjorg-project.c
    projectorganizer/src/prjorg-project.h
    projectorganizer/src/prjorg-sidebar.c
    projectorganizer/src/prjorg-utils.c
    projectorganizer/src/prjorg-utils.h

Modified: projectorganizer/src/prjorg-project.c
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -114,6 +114,7 @@ static GSList *get_file_list(const gchar *utf8_path, GSList *patterns,
 
 			if (!patterns_match(ignored_dirs_patterns, utf8_name))
 			{
+				list = g_slist_prepend(list, g_build_path(G_DIR_SEPARATOR_S, utf8_filename, PROJORG_SENTINEL_FILENAME, NULL));
 				lst = get_file_list(utf8_filename, patterns, ignored_dirs_patterns,
 						ignored_file_patterns, visited_paths);
 				if (lst)


Modified: projectorganizer/src/prjorg-project.h
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -63,4 +63,6 @@ void prjorg_project_remove_single_tm_file(gchar *utf8_filename);
 
 gboolean prjorg_project_is_in_project(const gchar *utf8_filename);
 
+#define PROJORG_SENTINEL_FILENAME "..."
+
 #endif


Modified: projectorganizer/src/prjorg-sidebar.c
253 lines changed, 253 insertions(+), 0 deletions(-)
===================================================================
@@ -105,6 +105,11 @@ static struct
 	GtkWidget *find_tag;
 	GtkWidget *expand;
 	GtkWidget *remove_external_dir;
+
+	GtkWidget *create_file;
+	GtkWidget *create_dir;
+	GtkWidget *rename;
+	GtkWidget *delete;
 } s_popup_menu;
 
 
@@ -350,6 +355,206 @@ static void on_remove_external_dir(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_U
 }
 
 
+// returned string must be freed
+static gchar* parent_dir_for_create()
+{
+	GtkTreeSelection *treesel;
+	GtkTreeModel *model;
+	GtkTreeIter iter, parent;
+	gchar *path = NULL;
+
+	treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(s_file_view));
+	if (gtk_tree_selection_get_selected(treesel, &model, &iter))
+	{
+		path = build_path(&iter);
+		if (!g_file_test(path, G_FILE_TEST_IS_DIR))
+		{
+			g_print("%s is not dir\n", path);
+			g_free(path);
+			path = NULL;
+			if (gtk_tree_model_iter_parent(model, &parent, &iter))
+			{
+				path = build_path(&parent);
+			}
+		}
+	}
+	return path;
+}
+
+
+static void on_create_file(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer user_data)
+{
+	gchar *dir, *name, *path;
+
+	dir = parent_dir_for_create();
+	if (NULL == dir)
+	{
+		return;
+	}
+
+	g_print("Creating file in %s\n", dir);
+
+	name = dialogs_show_input(_("New File"), GTK_WINDOW(geany->main_widgets->window),
+		_("Name:"), _("newfile.txt"));
+
+	if (NULL != name)
+	{
+		path = g_build_path(G_DIR_SEPARATOR_S, dir, name, NULL);
+		g_free(name);
+		g_print("new file: %s", path);
+
+		if (create_file(path))
+		{
+			open_file(path);
+			prjorg_project_rescan();
+			prjorg_sidebar_update(TRUE);
+			project_write_config();
+		}
+		else
+		{
+			dialogs_show_msgbox(GTK_MESSAGE_ERROR, _("Cannot create new file %s"), path);
+		}
+		g_free(path);
+	}
+	g_free(dir);
+}
+
+
+static void on_create_dir(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer user_data)
+{
+	gchar *dir, *name, *path;
+
+	dir = parent_dir_for_create();
+	if (NULL == dir)
+	{
+		return;
+	}
+
+	g_print("Creating dir in %s\n", dir);
+
+	name = dialogs_show_input(_("New Directory"), GTK_WINDOW(geany->main_widgets->window),
+		_("Name:"), _("newdir"));
+
+	if (NULL != name)
+	{
+		path = g_build_path(G_DIR_SEPARATOR_S, dir, name, NULL);
+		g_free(name);
+		g_print("new dir: %s", path);
+
+		if (create_dir(path))
+		{
+			prjorg_project_rescan();
+			prjorg_sidebar_update(TRUE);
+			project_write_config();
+		}
+		else
+		{
+			dialogs_show_msgbox(GTK_MESSAGE_ERROR, _("Cannot create directory %s"), path);
+		}
+		g_free(path);
+	}
+	g_free(dir);
+}
+
+
+static void on_rename(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer user_data)
+{
+	GtkTreeSelection *treesel;
+	GtkTreeModel *model;
+	GtkTreeIter iter, parent;
+	gchar *name, *dir, *newname, *oldpath, *newpath;
+
+	g_print("Renaming");
+
+	treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(s_file_view));
+	if (!gtk_tree_selection_get_selected(treesel, &model, &iter))
+	{
+		return;
+	}
+	if (!gtk_tree_model_iter_parent(model, &parent, &iter))
+	{
+		return;
+	}
+	dir = build_path(&parent);
+	if (NULL == dir)
+	{
+		return;
+	}
+
+	gtk_tree_model_get(model, &iter, FILEVIEW_COLUMN_NAME, &name, -1);
+	if (NULL != name)
+	{
+		newname = dialogs_show_input(_("Rename"), GTK_WINDOW(geany->main_widgets->window),
+			_("New name:"), name);
+
+		if (NULL != newname)
+		{
+			oldpath = g_build_path(G_DIR_SEPARATOR_S, dir, name, NULL);
+			newpath = g_build_path(G_DIR_SEPARATOR_S, dir, newname, NULL);
+			if (rename_file_or_dir(oldpath, newpath))
+			{
+				prjorg_project_rescan();
+				prjorg_sidebar_update(TRUE);
+				project_write_config();
+			}
+			else
+			{
+				dialogs_show_msgbox(GTK_MESSAGE_ERROR, _("Cannot rename %s to %s"),
+					oldpath, newpath);
+			}
+			g_free(oldpath);
+			g_free(newpath);
+			g_free(newname);
+		}
+		g_free(name);
+	}
+	g_free(dir);
+}
+
+
+static void on_delete(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer user_data)
+{
+	GtkTreeSelection *treesel;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	gchar *name;
+	gchar *path;
+
+	treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(s_file_view));
+	if (!gtk_tree_selection_get_selected(treesel, &model, &iter))
+	{
+		return;
+	}
+
+	gtk_tree_model_get(model, &iter, FILEVIEW_COLUMN_NAME, &name, -1);
+
+	if (dialogs_show_question(_("Do you really want to delete '%s'"), name))
+	{
+		path = build_path(&iter);
+		printf("deleting '%s'\n", path);
+
+		//TODO: recurse into directories
+
+		if (remove_file_or_dir(path))
+		{
+			close_file(path);
+		}
+		else
+		{
+			dialogs_show_msgbox(GTK_MESSAGE_ERROR, _("Cannot delete file %s"), path);
+		}
+
+		g_free(path);
+
+		prjorg_project_rescan();
+		prjorg_sidebar_update(TRUE);
+		project_write_config();
+	}
+
+	g_free(name);
+}
+
+
 static void find_file_recursive(GtkTreeIter *iter, gboolean case_sensitive, gboolean full_path, GPatternSpec *pattern)
 {
 	GtkTreeModel *model = GTK_TREE_MODEL(s_file_store);
@@ -900,6 +1105,10 @@ static void create_branch(gint level, GSList *leaf_list, GtkTreeIter *parent,
 		GtkTreeIter iter;
 		gchar **path_arr = elem->data;
 		GIcon *icon = NULL;
+
+		if (0 == g_strcmp0(PROJORG_SENTINEL_FILENAME, path_arr[level]))
+			continue;
+
 		gchar *content_type = g_content_type_guess(path_arr[level], NULL, 0, NULL);
 
 		if (content_type)
@@ -1468,6 +1677,50 @@ void prjorg_sidebar_init(void)
 	g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_remove_external_dir), NULL);
 	s_popup_menu.remove_external_dir = item;
 
+
+
+	item = gtk_separator_menu_item_new();
+	gtk_widget_show(item);
+	gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item);
+
+	image = gtk_image_new_from_stock(GTK_STOCK_FILE, GTK_ICON_SIZE_MENU);
+	gtk_widget_show(image);
+	item = gtk_image_menu_item_new_with_mnemonic(_("New File"));
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
+	gtk_widget_show(item);
+	gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item);
+	g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_create_file), NULL);
+	s_popup_menu.create_file = item;
+
+	image = gtk_image_new_from_stock(GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU);
+	gtk_widget_show(image);
+	item = gtk_image_menu_item_new_with_mnemonic(_("New Directory"));
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
+	gtk_widget_show(item);
+	gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item);
+	g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_create_dir), NULL);
+	s_popup_menu.create_dir = item;
+
+	image = gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
+	gtk_widget_show(image);
+	item = gtk_image_menu_item_new_with_mnemonic(_("Rename"));
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
+	gtk_widget_show(item);
+	gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item);
+	g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_rename), NULL);
+	s_popup_menu.rename = item;
+
+	image = gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU);
+	gtk_widget_show(image);
+	item = gtk_image_menu_item_new_with_mnemonic(_("Delete"));
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
+	gtk_widget_show(item);
+	gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item);
+	g_signal_connect((gpointer) item, "activate", G_CALLBACK(on_delete), NULL);
+	s_popup_menu.delete = item;
+
+
+
 	item = gtk_separator_menu_item_new();
 	gtk_widget_show(item);
 	gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item);


Modified: projectorganizer/src/prjorg-utils.c
78 lines changed, 78 insertions(+), 0 deletions(-)
===================================================================
@@ -19,6 +19,11 @@
 #include <string.h>
 #include <glib.h>
 
+#include <glib/gstdio.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
 #include <geanyplugin.h>
 
 #include "prjorg-utils.h"
@@ -104,6 +109,79 @@ void open_file(gchar *utf8_name)
 }
 
 
+void close_file(gchar *utf8_name)
+{
+	GeanyDocument *doc;
+
+	doc = document_find_by_filename(utf8_name);
+	if (doc)
+	{
+		document_set_text_changed(doc, FALSE);
+		document_close(doc);
+	}
+}
+
+
+gboolean create_file(gchar *utf8_name)
+{
+	int fd;
+	GError *err;
+
+	fd = g_open(utf8_name, O_CREAT|O_EXCL, 0660); // rw-rw----
+	if (-1 == fd) // not created?
+	{
+		return FALSE;
+	}
+	g_close(fd, &err);
+	return TRUE;
+}
+
+
+gboolean create_dir(char *utf8_name)
+{
+	return 0 == g_mkdir_with_parents(utf8_name, 0770); // rwxrwx---
+}
+
+
+gboolean remove_file_or_dir(char *utf8_name)
+{
+	return 0 == g_remove(utf8_name);
+}
+
+
+
+static gboolean document_rename(GeanyDocument *document, gchar *utf8_name)
+{
+	// IMHO: this is wrong. If save as fails Geany's state becomes inconsistent.
+	document_rename_file(document, utf8_name);
+	return document_save_file_as(document, utf8_name);
+}
+
+
+gboolean rename_file_or_dir(gchar *utf8_oldname, gchar *utf8_newname)
+{
+	GeanyDocument *doc;
+	gchar *oldname;
+	gchar *newname;
+	int res;
+
+	doc = document_find_by_filename(utf8_oldname);
+	if (doc)
+	{
+		return document_rename(doc, utf8_newname);
+	}
+	else
+	{
+		oldname = utils_get_locale_from_utf8(utf8_oldname);
+		newname = utils_get_locale_from_utf8(utf8_newname);
+		res = g_rename(oldname, newname);
+		g_free(oldname);
+		g_free(newname);
+		return 0 == res;
+	}
+}
+
+
 gchar *get_selection(void)
 {
 	GeanyDocument *doc = document_get_current();


Modified: projectorganizer/src/prjorg-utils.h
7 lines changed, 7 insertions(+), 0 deletions(-)
===================================================================
@@ -25,6 +25,13 @@ gboolean patterns_match(GSList *patterns, const gchar *str);
 GSList *get_precompiled_patterns(gchar **patterns);
 
 void open_file(gchar *utf8_name);
+void close_file(gchar *utf8_name);
+
+gboolean create_file(char *utf8_name);
+gboolean create_dir(char *utf8_name);
+gboolean remove_file_or_dir(char *utf8_name);
+gboolean rename_file_or_dir(gchar *utf8_oldname, gchar *utf8_newname);
+
 gchar *get_selection(void);
 gchar *get_project_base_path(void);
 



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Plugins-Commits mailing list