Branch: refs/heads/master Author: Daniel Guerrero dgm@aquilessolutions.com Committer: Daniel Guerrero dgm@aquilessolutions.com Date: Fri, 10 Aug 2018 15:07:25 UTC Commit: ca1912d6c5ebf671af36851b63c2508da6b464e0 https://github.com/geany/geany-plugins/commit/ca1912d6c5ebf671af36851b63c250...
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).
plugins-commits@lists.geany.org