lists.geany.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
List overview
Plugins-Commits
March 2018
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
plugins-commits@lists.geany.org
1 participants
33 discussions
Start a n
N
ew thread
[geany/geany-plugins] 87a640: workbench: removed compile-time checks
by LarsDW223
07 Mar '18
07 Mar '18
Branch: refs/heads/master Author: LarsDW223 <lars_paulsen(a)web.de> Committer: LarsDW223 <lars_paulsen(a)web.de> Date: Wed, 07 Mar 2018 19:49:08 UTC Commit: 87a6400a159daaeed755b1765972f49604c1eeb2
https://github.com/geany/geany-plugins/commit/87a6400a159daaeed755b1765972f…
Log Message: ----------- workbench: removed compile-time checks Modified Paths: -------------- workbench/src/dialogs.c workbench/src/wb_monitor.c workbench/src/wb_monitor.h workbench/src/wb_project.c workbench/src/workbench.c Modified: workbench/src/dialogs.c 9 lines changed, 0 insertions(+), 9 deletions(-) =================================================================== @@ -440,19 +440,10 @@ gboolean dialogs_workbench_settings(WORKBENCH *workbench) w_enable_live_update = gtk_check_button_new_with_mnemonic(_("_Enable live update")); ui_table_add_row(GTK_TABLE(table), 1, w_enable_live_update, NULL); -#ifdef __WB_LIVE_UPDATE gtk_widget_set_tooltip_text(w_enable_live_update, _("If the option is activated (default), then the list of files and the sidebar" " will be updated automatically if a file or directory is created, removed or renamed." "A manual re-scan is not required if the option is enabled.")); -#else - gtk_widget_set_sensitive(w_enable_live_update, FALSE); - gtk_widget_set_tooltip_text(w_enable_live_update, - _("If the option is activated (default), then the list of files and the sidebar" - " will be updated automatically if a file or directory is created, removed or renamed." - "A manual re-scan is not required if the option is enabled.\n\n" - "This feature has been disabled because it is not available on your system.")); -#endif enable_live_update_old = workbench_get_enable_live_update(workbench); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w_enable_live_update), enable_live_update_old); Modified: workbench/src/wb_monitor.c 2 lines changed, 0 insertions(+), 2 deletions(-) =================================================================== @@ -31,7 +31,6 @@ #include "wb_monitor.h" #include "utils.h" -#ifdef __WB_LIVE_UPDATE struct S_WB_MONITOR { @@ -247,4 +246,3 @@ void wb_monitor_free(WB_MONITOR *monitor) } } } -#endif Modified: workbench/src/wb_monitor.h 6 lines changed, 0 insertions(+), 6 deletions(-) =================================================================== @@ -22,18 +22,12 @@ #include <glib.h> #include "wb_project.h" -#if defined(HAVE_GIO) -#define __WB_LIVE_UPDATE 1 -#endif - typedef struct S_WB_MONITOR WB_MONITOR; -#ifdef __WB_LIVE_UPDATE WB_MONITOR *wb_monitor_new(void); void wb_monitor_add_dir(WB_MONITOR *monitor, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *dirpath); gboolean wb_monitor_remove_dir(WB_MONITOR *monitor, const gchar *dirpath); void wb_monitor_free(WB_MONITOR *monitor); -#endif #endif Modified: workbench/src/wb_project.c 10 lines changed, 0 insertions(+), 10 deletions(-) =================================================================== @@ -569,7 +569,6 @@ static guint wb_project_dir_rescan_int(WB_PROJECT *prj, WB_PROJECT_DIR *root) /* Add a new file to the project directory and update the sidebar. */ -#ifdef __WB_LIVE_UPDATE static void wb_project_dir_add_file_int(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) { gboolean matches; @@ -634,7 +633,6 @@ static void wb_project_dir_add_file_int(WB_PROJECT *prj, WB_PROJECT_DIR *root, c g_slist_free(scanned); } } -#endif /** Add a new file to the project directory and update the sidebar. @@ -646,19 +644,16 @@ static void wb_project_dir_add_file_int(WB_PROJECT *prj, WB_PROJECT_DIR *root, c * @param filepath The file to add. * **/ -#ifdef __WB_LIVE_UPDATE void wb_project_dir_add_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) { wb_project_dir_add_file_int(prj, root, filepath); wb_project_add_idle_action(WB_PROJECT_IDLE_ACTION_ID_UPDATE_TAGS, root, NULL); } -#endif /* Check if the filepath is equal for the length of the directory path in px_temp */ -#ifdef __WB_LIVE_UPDATE static gboolean wb_project_dir_remove_child (gpointer key, gpointer value, gpointer user_data) { WB_PROJECT_TEMP_DATA *px_temp; @@ -680,7 +675,6 @@ static gboolean wb_project_dir_remove_child (gpointer key, gpointer value, gpoin } return FALSE; } -#endif /** Remove a file from the project directory and update the sidebar. @@ -692,7 +686,6 @@ static gboolean wb_project_dir_remove_child (gpointer key, gpointer value, gpoin * @param filepath The file to remove. * **/ -#ifdef __WB_LIVE_UPDATE void wb_project_dir_remove_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) { gboolean matches, was_dir; @@ -768,7 +761,6 @@ void wb_project_dir_remove_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gch } } } -#endif /* Stolen and modified version from Geany. The only difference is that Geany @@ -932,7 +924,6 @@ void wb_project_rescan(WB_PROJECT *prj) } /* Create file monitors for directories. */ -#ifdef __WB_LIVE_UPDATE if (workbench_get_enable_live_update(wb_globals.opened_wb) == TRUE) { WB_MONITOR *monitor; @@ -962,7 +953,6 @@ void wb_project_rescan(WB_PROJECT *prj) } } } -#endif } Modified: workbench/src/workbench.c 14 lines changed, 0 insertions(+), 14 deletions(-) =================================================================== @@ -92,9 +92,7 @@ WORKBENCH *workbench_new(void) new_wb->enable_live_update = TRUE; new_wb->projects = g_ptr_array_new(); new_wb->bookmarks = g_ptr_array_new(); -#ifdef __WB_LIVE_UPDATE new_wb->monitor = wb_monitor_new(); -#endif return new_wb; } @@ -125,9 +123,7 @@ void workbench_free(WORKBENCH *wb) } } -#ifdef __WB_LIVE_UPDATE wb_monitor_free(wb->monitor); -#endif g_ptr_array_free (wb->projects, TRUE); g_free(wb); } @@ -920,7 +916,6 @@ static gboolean workbench_references_are_valid(WORKBENCH *wb, WB_PROJECT *prj, W * @param file The new file to add to project/directory * **/ -#ifdef __WB_LIVE_UPDATE void workbench_process_add_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *file) { if (workbench_references_are_valid(wb, prj, dir) == FALSE) @@ -933,7 +928,6 @@ void workbench_process_add_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT wb_project_dir_add_file(prj, dir, file); } -#endif /** Process the remove file event. @@ -948,7 +942,6 @@ void workbench_process_add_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT * @param file The file to remove from project/directory * **/ -#ifdef __WB_LIVE_UPDATE void workbench_process_remove_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *file) { if (workbench_references_are_valid(wb, prj, dir) == FALSE) @@ -961,11 +954,9 @@ void workbench_process_remove_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJ wb_project_dir_remove_file(prj, dir, file); } -#endif /* Foreach callback function for creating file monitors. */ -#ifdef __WB_LIVE_UPDATE static void workbench_enable_live_update_foreach_cb(SIDEBAR_CONTEXT *context, gpointer userdata) { @@ -995,7 +986,6 @@ static void workbench_enable_live_update_foreach_cb(SIDEBAR_CONTEXT *context, g_free(abs_path); } -#endif /** Enable live update. @@ -1008,15 +998,13 @@ static void workbench_enable_live_update_foreach_cb(SIDEBAR_CONTEXT *context, **/ void workbench_enable_live_update(WORKBENCH *wb) { -#ifdef __WB_LIVE_UPDATE if (wb != NULL) { sidebar_call_foreach(DATA_ID_DIRECTORY, workbench_enable_live_update_foreach_cb, wb->monitor); sidebar_call_foreach(DATA_ID_SUB_DIRECTORY, workbench_enable_live_update_foreach_cb, wb->monitor); } -#endif } @@ -1030,10 +1018,8 @@ void workbench_enable_live_update(WORKBENCH *wb) **/ void workbench_disable_live_update(WORKBENCH *wb) { -#ifdef __WB_LIVE_UPDATE if (wb != NULL) { wb_monitor_free(wb->monitor); } -#endif } -------------- This E-Mail was brought to you by github_commit_mail.py (Source:
https://github.com/geany/infrastructure
).
1
0
0
0
[geany/geany-plugins] 909660: workbench: use simple/old file monitor events only
by LarsDW223
05 Mar '18
05 Mar '18
Branch: refs/heads/master Author: LarsDW223 <lars_paulsen(a)web.de> Committer: LarsDW223 <lars_paulsen(a)web.de> Date: Mon, 05 Mar 2018 20:44:40 UTC Commit: 9096605eb280528a46b7cc446d550bb75dfb22af
https://github.com/geany/geany-plugins/commit/9096605eb280528a46b7cc446d550…
Log Message: ----------- workbench: use simple/old file monitor events only This removes the dependency/the requirement for GLib version 2.46. Modified Paths: -------------- workbench/src/plugin_main.c workbench/src/wb_monitor.c workbench/src/wb_monitor.h Modified: workbench/src/plugin_main.c 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -130,7 +130,7 @@ void geany_load_module(GeanyPlugin *plugin) /* Set metadata */ plugin->info->name = _("Workbench"); plugin->info->description = _("Manage and customize multiple projects."); - plugin->info->version = "1.03"; + plugin->info->version = "1.04"; plugin->info->author = "LarsGit223"; /* Set functions */ Modified: workbench/src/wb_monitor.c 22 lines changed, 1 insertions(+), 21 deletions(-) =================================================================== @@ -122,26 +122,6 @@ static void wb_monitor_file_changed_cb(G_GNUC_UNUSED GFileMonitor *monitor, entry->prj, entry->dir, file_path); break; - case G_FILE_MONITOR_EVENT_RENAMED: - event_string = "FILE_RENAMED"; - workbench_process_remove_file_event (wb_globals.opened_wb, - entry->prj, entry->dir, file_path); - workbench_process_add_file_event (wb_globals.opened_wb, - entry->prj, entry->dir, other_file_path); - break; - - case G_FILE_MONITOR_EVENT_MOVED_IN: - event_string = "FILE_MOVED_IN"; - workbench_process_add_file_event (wb_globals.opened_wb, - entry->prj, entry->dir, file_path); - break; - - case G_FILE_MONITOR_EVENT_MOVED_OUT: - event_string = "FILE_MOVED_OUT"; - workbench_process_remove_file_event (wb_globals.opened_wb, - entry->prj, entry->dir, file_path); - break; - default: break; } @@ -204,7 +184,7 @@ void wb_monitor_add_dir(WB_MONITOR *monitor, WB_PROJECT *prj, /* Setup file monitor for directory */ file = g_file_new_for_path(dirpath); newmon = g_file_monitor_directory - (file, G_FILE_MONITOR_WATCH_MOVES, NULL, &error); + (file, G_FILE_MONITOR_NONE, NULL, &error); if (newmon == NULL) { /* Create monitor failed. Report error. */ Modified: workbench/src/wb_monitor.h 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -22,7 +22,7 @@ #include <glib.h> #include "wb_project.h" -#if defined(HAVE_GIO) && GLIB_CHECK_VERSION (2, 46, 0) +#if defined(HAVE_GIO) #define __WB_LIVE_UPDATE 1 #endif -------------- This E-Mail was brought to you by github_commit_mail.py (Source:
https://github.com/geany/infrastructure
).
1
0
0
0
[geany/geany-plugins] b70e86: Merge pull request #712 from LarsGit223/wb-remove
by Frank Lanitz
05 Mar '18
05 Mar '18
Branch: refs/heads/master Author: Frank Lanitz <frank(a)frank.uvena.de> Committer: GitHub <noreply(a)github.com> Date: Mon, 05 Mar 2018 06:49:10 UTC Commit: b70e8602f424c100d1463d243c3a7aaea14e6fee
https://github.com/geany/geany-plugins/commit/b70e8602f424c100d1463d243c3a7…
Log Message: ----------- Merge pull request #712 from LarsGit223/wb-remove workbench: remove files or directories. Modified Paths: -------------- workbench/src/popup_menu.c workbench/src/sidebar.c workbench/src/sidebar.h Modified: workbench/src/popup_menu.c 165 lines changed, 159 insertions(+), 6 deletions(-) =================================================================== @@ -62,6 +62,7 @@ static struct GtkWidget *remove_bookmark; GtkWidget *new_file; GtkWidget *new_directory; + GtkWidget *remove_file_or_dir; } s_popup_menu; @@ -98,6 +99,7 @@ void popup_menu_show(POPUP_CONTEXT context, GdkEventButton *event) gtk_widget_set_sensitive (s_popup_menu.subdir_close_all, FALSE); gtk_widget_set_sensitive (s_popup_menu.new_file, FALSE); gtk_widget_set_sensitive (s_popup_menu.new_directory, FALSE); + gtk_widget_set_sensitive (s_popup_menu.remove_file_or_dir, FALSE); break; case POPUP_CONTEXT_DIRECTORY: gtk_widget_set_sensitive (s_popup_menu.add_project, TRUE); @@ -119,6 +121,7 @@ void popup_menu_show(POPUP_CONTEXT context, GdkEventButton *event) gtk_widget_set_sensitive (s_popup_menu.subdir_close_all, FALSE); gtk_widget_set_sensitive (s_popup_menu.new_file, TRUE); gtk_widget_set_sensitive (s_popup_menu.new_directory, TRUE); + gtk_widget_set_sensitive (s_popup_menu.remove_file_or_dir, TRUE); break; case POPUP_CONTEXT_SUB_DIRECTORY: gtk_widget_set_sensitive (s_popup_menu.add_project, TRUE); @@ -140,6 +143,7 @@ void popup_menu_show(POPUP_CONTEXT context, GdkEventButton *event) gtk_widget_set_sensitive (s_popup_menu.subdir_close_all, TRUE); gtk_widget_set_sensitive (s_popup_menu.new_file, TRUE); gtk_widget_set_sensitive (s_popup_menu.new_directory, TRUE); + gtk_widget_set_sensitive (s_popup_menu.remove_file_or_dir, TRUE); break; case POPUP_CONTEXT_FILE: gtk_widget_set_sensitive (s_popup_menu.add_project, TRUE); @@ -161,6 +165,7 @@ void popup_menu_show(POPUP_CONTEXT context, GdkEventButton *event) gtk_widget_set_sensitive (s_popup_menu.subdir_close_all, TRUE); gtk_widget_set_sensitive (s_popup_menu.new_file, TRUE); gtk_widget_set_sensitive (s_popup_menu.new_directory, TRUE); + gtk_widget_set_sensitive (s_popup_menu.remove_file_or_dir, TRUE); break; case POPUP_CONTEXT_BACKGROUND: gtk_widget_set_sensitive (s_popup_menu.add_project, TRUE); @@ -182,6 +187,7 @@ void popup_menu_show(POPUP_CONTEXT context, GdkEventButton *event) gtk_widget_set_sensitive (s_popup_menu.subdir_close_all, FALSE); gtk_widget_set_sensitive (s_popup_menu.new_file, FALSE); gtk_widget_set_sensitive (s_popup_menu.new_directory, FALSE); + gtk_widget_set_sensitive (s_popup_menu.remove_file_or_dir, FALSE); break; case POPUP_CONTEXT_WB_BOOKMARK: gtk_widget_set_sensitive (s_popup_menu.add_project, TRUE); @@ -203,6 +209,7 @@ void popup_menu_show(POPUP_CONTEXT context, GdkEventButton *event) gtk_widget_set_sensitive (s_popup_menu.subdir_close_all, FALSE); gtk_widget_set_sensitive (s_popup_menu.new_file, FALSE); gtk_widget_set_sensitive (s_popup_menu.new_directory, FALSE); + gtk_widget_set_sensitive (s_popup_menu.remove_file_or_dir, FALSE); break; case POPUP_CONTEXT_PRJ_BOOKMARK: gtk_widget_set_sensitive (s_popup_menu.add_project, TRUE); @@ -224,6 +231,7 @@ void popup_menu_show(POPUP_CONTEXT context, GdkEventButton *event) gtk_widget_set_sensitive (s_popup_menu.subdir_close_all, FALSE); gtk_widget_set_sensitive (s_popup_menu.new_file, FALSE); gtk_widget_set_sensitive (s_popup_menu.new_directory, FALSE); + gtk_widget_set_sensitive (s_popup_menu.remove_file_or_dir, FALSE); break; } gtk_menu_popup(GTK_MENU(s_popup_menu.widget), NULL, NULL, NULL, NULL, @@ -321,7 +329,7 @@ static void popup_menu_on_project_open_all (G_GNUC_UNUSED GtkMenuItem *menuitem, { GPtrArray *list; - list = sidebar_get_selected_project_filelist(); + list = sidebar_get_selected_project_filelist(FALSE); if (list != NULL) { open_all_files_in_list(list); @@ -335,7 +343,7 @@ static void popup_menu_on_project_close_all (G_GNUC_UNUSED GtkMenuItem *menuitem { GPtrArray *list; - list = sidebar_get_selected_project_filelist(); + list = sidebar_get_selected_project_filelist(FALSE); if (list != NULL) { close_all_files_in_list(list); @@ -426,7 +434,7 @@ static void popup_menu_on_directory_open_all (G_GNUC_UNUSED GtkMenuItem *menuite { GPtrArray *list; - list = sidebar_get_selected_directory_filelist(); + list = sidebar_get_selected_directory_filelist(FALSE); if (list != NULL) { open_all_files_in_list(list); @@ -440,7 +448,7 @@ static void popup_menu_on_directory_close_all (G_GNUC_UNUSED GtkMenuItem *menuit { GPtrArray *list; - list = sidebar_get_selected_directory_filelist(); + list = sidebar_get_selected_directory_filelist(FALSE); if (list != NULL) { close_all_files_in_list(list); @@ -502,7 +510,7 @@ static void popup_menu_on_subdir_open_all (G_GNUC_UNUSED GtkMenuItem *menuitem, { GPtrArray *list; - list = sidebar_get_selected_subdir_filelist(); + list = sidebar_get_selected_subdir_filelist(FALSE); if (list != NULL) { open_all_files_in_list(list); @@ -516,7 +524,7 @@ static void popup_menu_on_subdir_close_all (G_GNUC_UNUSED GtkMenuItem *menuitem, { GPtrArray *list; - list = sidebar_get_selected_subdir_filelist(); + list = sidebar_get_selected_subdir_filelist(FALSE); if (list != NULL) { close_all_files_in_list(list); @@ -616,6 +624,145 @@ static void popup_menu_on_new_directory(G_GNUC_UNUSED GtkMenuItem *menuitem, G_G } +/* Handle popup menu item "Remove..." */ +static void popup_menu_on_remove_file_or_dir(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer user_data) +{ + gboolean remove_it, dir, removed_any = FALSE; + gchar *path = NULL, *abs_path = NULL; + SIDEBAR_CONTEXT context; + GPtrArray *files; + + /* Check if a file, a sub-dir or a directory is selected. */ + if (sidebar_file_view_get_selected_context(&context)) + { + if (context.file != NULL) + { + abs_path = g_strdup(context.file); + dir = FALSE; + } + else if (context.subdir != NULL) + { + path = context.subdir; + abs_path = g_strdup(path); + files = sidebar_get_selected_subdir_filelist(TRUE); + dir = TRUE; + } + else if (context.directory != NULL) + { + path = wb_project_dir_get_base_dir(context.directory); + abs_path = get_combined_path(wb_project_get_filename(context.project), path); + files = sidebar_get_selected_directory_filelist(TRUE); + dir = TRUE; + } + } + + if (abs_path == NULL) + { + return; + } + + /* Warn the user. */ + if (dir == FALSE) + { + remove_it = dialogs_show_question(_("Do you really want to remove file \"%s\"?\n\nThis cannot be undone!"), + abs_path); + } + else + { + remove_it = dialogs_show_question(_("Do you really want to remove directory \"%s\" and all files in it?\n\nThis cannot be undone!"), + abs_path); + } + + /* Really remove it? */ + if (remove_it) + { + if (dir == FALSE) + { + if (g_remove(abs_path) != 0) + { + /* Remove file failed. Report error. */ + ui_set_statusbar(TRUE, _("Could not remove file \"%s\"."), + abs_path); + } + else + { + removed_any = TRUE; + } + } + else + { + if (files != NULL) + { + guint index; + gchar *filename; + + /* First remove all files in the directories. */ + for ( index = 0 ; index < files->len ; index++ ) + { + filename = files->pdata[index]; + if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) + { + if (g_remove(filename) != 0) + { + /* Remove file failed. Report error. */ + ui_set_statusbar(TRUE, _("Could not remove file \"%s\"."), + filename); + } + else + { + removed_any = TRUE; + } + } + } + + /* Now try to remove the directories. + This will only succeed if they are empty. */ + for ( index = 0 ; index < files->len ; index++ ) + { + filename = files->pdata[index]; + if (g_file_test(filename, G_FILE_TEST_IS_DIR)) + { + if (g_rmdir(filename) != 0) + { + /* Remove file failed. Report error. */ + ui_set_statusbar(TRUE, _("Could not remove directory \"%s\"."), + filename); + } + else + { + removed_any = TRUE; + } + } + } + + /* At last try to remove the parent dir. */ + if (g_rmdir(abs_path) != 0) + { + /* Remove file failed. Report error. */ + ui_set_statusbar(TRUE, _("Could not remove directory \"%s\"."), + abs_path); + } + else + { + removed_any = TRUE; + } + + g_ptr_array_free(files, TRUE); + } + } + + /* If anything was removed update the filelist and sidebar. */ + if (removed_any) + { + wb_project_dir_rescan(context.project, context.directory); + sidebar_update(SIDEBAR_CONTEXT_DIRECTORY_RESCANNED, &context); + } + } + + g_free(abs_path); +} + + /** Setup/Initialize the popup menu. * **/ @@ -776,4 +923,10 @@ void popup_menu_init(void) gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item); g_signal_connect(item, "activate", G_CALLBACK(popup_menu_on_new_directory), NULL); s_popup_menu.new_directory = item; + + item = gtk_menu_item_new_with_mnemonic(_("_Remove...")); + gtk_widget_show(item); + gtk_container_add(GTK_CONTAINER(s_popup_menu.widget), item); + g_signal_connect(item, "activate", G_CALLBACK(popup_menu_on_remove_file_or_dir), NULL); + s_popup_menu.remove_file_or_dir = item; } Modified: workbench/src/sidebar.c 25 lines changed, 15 insertions(+), 10 deletions(-) =================================================================== @@ -1258,7 +1258,7 @@ gboolean sidebar_file_view_get_selected_context(SIDEBAR_CONTEXT *context) } /* Collect all filenames recursively starting from iter and add them to list */ -static void sidebar_get_filelist_for_iter(GPtrArray *list, GtkTreeIter iter) +static void sidebar_get_filelist_for_iter(GPtrArray *list, GtkTreeIter iter, gboolean dirnames) { GtkTreeModel *model; GtkTreeIter childs; @@ -1278,9 +1278,14 @@ static void sidebar_get_filelist_for_iter(GPtrArray *list, GtkTreeIter iter) break; case DATA_ID_DIRECTORY: case DATA_ID_SUB_DIRECTORY: + if (dirnames == TRUE) + { + gtk_tree_model_get(model, &iter, FILEVIEW_COLUMN_ASSIGNED_DATA_POINTER, &filename, -1); + g_ptr_array_add(list, g_strdup(filename)); + } if (gtk_tree_model_iter_children(model, &childs, &iter) == TRUE) { - sidebar_get_filelist_for_iter(list, childs); + sidebar_get_filelist_for_iter(list, childs, dirnames); } break; } @@ -1292,7 +1297,7 @@ static void sidebar_get_filelist_for_iter(GPtrArray *list, GtkTreeIter iter) /* Get the lkist of files belonging to the current selection for id (id = project, directory, sub-directory) */ -static GPtrArray *sidebar_get_selected_filelist (guint id) +static GPtrArray *sidebar_get_selected_filelist (guint id, gboolean dirnames) { GtkTreeModel *model; GPtrArray *list; @@ -1304,7 +1309,7 @@ static GPtrArray *sidebar_get_selected_filelist (guint id) model = gtk_tree_view_get_model(GTK_TREE_VIEW(sidebar.file_view)); if (gtk_tree_model_iter_children(model, &childs, &iter) == TRUE) { - sidebar_get_filelist_for_iter(list, childs); + sidebar_get_filelist_for_iter(list, childs, dirnames); } return list; } @@ -1318,9 +1323,9 @@ static GPtrArray *sidebar_get_selected_filelist (guint id) * @return GPtrArray containing file names or NULL. * **/ -GPtrArray *sidebar_get_selected_project_filelist (void) +GPtrArray *sidebar_get_selected_project_filelist (gboolean dirnames) { - return sidebar_get_selected_filelist(DATA_ID_PROJECT); + return sidebar_get_selected_filelist(DATA_ID_PROJECT, dirnames); } @@ -1329,9 +1334,9 @@ GPtrArray *sidebar_get_selected_project_filelist (void) * @return GPtrArray containing file names or NULL. * **/ -GPtrArray *sidebar_get_selected_directory_filelist (void) +GPtrArray *sidebar_get_selected_directory_filelist (gboolean dirnames) { - return sidebar_get_selected_filelist(DATA_ID_DIRECTORY); + return sidebar_get_selected_filelist(DATA_ID_DIRECTORY, dirnames); } @@ -1340,9 +1345,9 @@ GPtrArray *sidebar_get_selected_directory_filelist (void) * @return GPtrArray containing file names or NULL. * **/ -GPtrArray *sidebar_get_selected_subdir_filelist (void) +GPtrArray *sidebar_get_selected_subdir_filelist (gboolean dirnames) { - return sidebar_get_selected_filelist(DATA_ID_SUB_DIRECTORY); + return sidebar_get_selected_filelist(DATA_ID_SUB_DIRECTORY, dirnames); } /** Setup the sidebar. Modified: workbench/src/sidebar.h 6 lines changed, 3 insertions(+), 3 deletions(-) =================================================================== @@ -86,9 +86,9 @@ void sidebar_toggle_selected_project_dir_expansion (void); WB_PROJECT *sidebar_file_view_get_selected_project(GtkTreePath **path); gboolean sidebar_file_view_get_selected_context(SIDEBAR_CONTEXT *context); -GPtrArray *sidebar_get_selected_project_filelist (void); -GPtrArray *sidebar_get_selected_directory_filelist (void); -GPtrArray *sidebar_get_selected_subdir_filelist (void); +GPtrArray *sidebar_get_selected_project_filelist (gboolean dirnames); +GPtrArray *sidebar_get_selected_directory_filelist (gboolean dirnames); +GPtrArray *sidebar_get_selected_subdir_filelist (gboolean dirnames); void sidebar_call_foreach(guint dataid, void (func)(SIDEBAR_CONTEXT *, gpointer userdata), gpointer userdata); -------------- This E-Mail was brought to you by github_commit_mail.py (Source:
https://github.com/geany/infrastructure
).
1
0
0
0
[geany/geany-plugins] d66970: Merge pull request #718 from LarsGit223/wb-gio-dep
by Frank Lanitz
04 Mar '18
04 Mar '18
Branch: refs/heads/master Author: Frank Lanitz <frank(a)frank.uvena.de> Committer: GitHub <noreply(a)github.com> Date: Sun, 04 Mar 2018 18:38:24 UTC Commit: d66970e3841eb1c23a376f24981efc825cf30dd5
https://github.com/geany/geany-plugins/commit/d66970e3841eb1c23a376f24981ef…
Log Message: ----------- Merge pull request #718 from LarsGit223/wb-gio-dep workbench: make "live update"-feature depending on GIO and Glib version 2.46 Modified Paths: -------------- build/workbench.m4 workbench/src/dialogs.c workbench/src/wb_monitor.c workbench/src/wb_monitor.h workbench/src/wb_project.c workbench/src/workbench.c Modified: build/workbench.m4 6 lines changed, 6 insertions(+), 0 deletions(-) =================================================================== @@ -2,6 +2,12 @@ AC_DEFUN([GP_CHECK_WORKBENCH], [ GP_ARG_DISABLE([Workbench], [auto]) GP_CHECK_UTILSLIB([Workbench]) + + PKG_CHECK_MODULES([GIO], [gio-2.0], + [AC_DEFINE([HAVE_GIO], 1, [Whether we have GIO]) + have_gio=yes], + [have_gio=no]) + GP_COMMIT_PLUGIN_STATUS([Workbench]) AC_CONFIG_FILES([ workbench/Makefile Modified: workbench/src/dialogs.c 9 lines changed, 9 insertions(+), 0 deletions(-) =================================================================== @@ -440,10 +440,19 @@ gboolean dialogs_workbench_settings(WORKBENCH *workbench) w_enable_live_update = gtk_check_button_new_with_mnemonic(_("_Enable live update")); ui_table_add_row(GTK_TABLE(table), 1, w_enable_live_update, NULL); +#ifdef __WB_LIVE_UPDATE gtk_widget_set_tooltip_text(w_enable_live_update, _("If the option is activated (default), then the list of files and the sidebar" " will be updated automatically if a file or directory is created, removed or renamed." "A manual re-scan is not required if the option is enabled.")); +#else + gtk_widget_set_sensitive(w_enable_live_update, FALSE); + gtk_widget_set_tooltip_text(w_enable_live_update, + _("If the option is activated (default), then the list of files and the sidebar" + " will be updated automatically if a file or directory is created, removed or renamed." + "A manual re-scan is not required if the option is enabled.\n\n" + "This feature has been disabled because it is not available on your system.")); +#endif enable_live_update_old = workbench_get_enable_live_update(workbench); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w_enable_live_update), enable_live_update_old); Modified: workbench/src/wb_monitor.c 3 lines changed, 3 insertions(+), 0 deletions(-) =================================================================== @@ -31,6 +31,8 @@ #include "wb_monitor.h" #include "utils.h" +#ifdef __WB_LIVE_UPDATE + struct S_WB_MONITOR { GHashTable *monitors; @@ -265,3 +267,4 @@ void wb_monitor_free(WB_MONITOR *monitor) } } } +#endif Modified: workbench/src/wb_monitor.h 6 lines changed, 6 insertions(+), 0 deletions(-) =================================================================== @@ -22,12 +22,18 @@ #include <glib.h> #include "wb_project.h" +#if defined(HAVE_GIO) && GLIB_CHECK_VERSION (2, 46, 0) +#define __WB_LIVE_UPDATE 1 +#endif + typedef struct S_WB_MONITOR WB_MONITOR; +#ifdef __WB_LIVE_UPDATE WB_MONITOR *wb_monitor_new(void); void wb_monitor_add_dir(WB_MONITOR *monitor, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *dirpath); gboolean wb_monitor_remove_dir(WB_MONITOR *monitor, const gchar *dirpath); void wb_monitor_free(WB_MONITOR *monitor); +#endif #endif Modified: workbench/src/wb_project.c 11 lines changed, 11 insertions(+), 0 deletions(-) =================================================================== @@ -569,6 +569,7 @@ static guint wb_project_dir_rescan_int(WB_PROJECT *prj, WB_PROJECT_DIR *root) /* Add a new file to the project directory and update the sidebar. */ +#ifdef __WB_LIVE_UPDATE static void wb_project_dir_add_file_int(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) { gboolean matches; @@ -633,6 +634,8 @@ static void wb_project_dir_add_file_int(WB_PROJECT *prj, WB_PROJECT_DIR *root, c g_slist_free(scanned); } } +#endif + /** Add a new file to the project directory and update the sidebar. * @@ -643,16 +646,19 @@ static void wb_project_dir_add_file_int(WB_PROJECT *prj, WB_PROJECT_DIR *root, c * @param filepath The file to add. * **/ +#ifdef __WB_LIVE_UPDATE void wb_project_dir_add_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) { wb_project_dir_add_file_int(prj, root, filepath); wb_project_add_idle_action(WB_PROJECT_IDLE_ACTION_ID_UPDATE_TAGS, root, NULL); } +#endif /* Check if the filepath is equal for the length of the directory path in px_temp */ +#ifdef __WB_LIVE_UPDATE static gboolean wb_project_dir_remove_child (gpointer key, gpointer value, gpointer user_data) { WB_PROJECT_TEMP_DATA *px_temp; @@ -674,6 +680,7 @@ static gboolean wb_project_dir_remove_child (gpointer key, gpointer value, gpoin } return FALSE; } +#endif /** Remove a file from the project directory and update the sidebar. @@ -685,6 +692,7 @@ static gboolean wb_project_dir_remove_child (gpointer key, gpointer value, gpoin * @param filepath The file to remove. * **/ +#ifdef __WB_LIVE_UPDATE void wb_project_dir_remove_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) { gboolean matches, was_dir; @@ -760,6 +768,7 @@ void wb_project_dir_remove_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gch } } } +#endif /* Stolen and modified version from Geany. The only difference is that Geany @@ -923,6 +932,7 @@ void wb_project_rescan(WB_PROJECT *prj) } /* Create file monitors for directories. */ +#ifdef __WB_LIVE_UPDATE if (workbench_get_enable_live_update(wb_globals.opened_wb) == TRUE) { WB_MONITOR *monitor; @@ -952,6 +962,7 @@ void wb_project_rescan(WB_PROJECT *prj) } } } +#endif } Modified: workbench/src/workbench.c 14 lines changed, 14 insertions(+), 0 deletions(-) =================================================================== @@ -92,7 +92,9 @@ WORKBENCH *workbench_new(void) new_wb->enable_live_update = TRUE; new_wb->projects = g_ptr_array_new(); new_wb->bookmarks = g_ptr_array_new(); +#ifdef __WB_LIVE_UPDATE new_wb->monitor = wb_monitor_new(); +#endif return new_wb; } @@ -123,7 +125,9 @@ void workbench_free(WORKBENCH *wb) } } +#ifdef __WB_LIVE_UPDATE wb_monitor_free(wb->monitor); +#endif g_ptr_array_free (wb->projects, TRUE); g_free(wb); } @@ -919,6 +923,7 @@ static gboolean workbench_references_are_valid(WORKBENCH *wb, WB_PROJECT *prj, W * @param file The new file to add to project/directory * **/ +#ifdef __WB_LIVE_UPDATE void workbench_process_add_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *file) { if (workbench_references_are_valid(wb, prj, dir) == FALSE) @@ -931,6 +936,7 @@ void workbench_process_add_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT wb_project_dir_add_file(prj, dir, file); } +#endif /** Process the remove file event. @@ -945,6 +951,7 @@ void workbench_process_add_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT * @param file The file to remove from project/directory * **/ +#ifdef __WB_LIVE_UPDATE void workbench_process_remove_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *file) { if (workbench_references_are_valid(wb, prj, dir) == FALSE) @@ -957,9 +964,11 @@ void workbench_process_remove_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJ wb_project_dir_remove_file(prj, dir, file); } +#endif /* Foreach callback function for creating file monitors. */ +#ifdef __WB_LIVE_UPDATE static void workbench_enable_live_update_foreach_cb(SIDEBAR_CONTEXT *context, gpointer userdata) { @@ -989,6 +998,7 @@ static void workbench_enable_live_update_foreach_cb(SIDEBAR_CONTEXT *context, g_free(abs_path); } +#endif /** Enable live update. @@ -1001,13 +1011,15 @@ static void workbench_enable_live_update_foreach_cb(SIDEBAR_CONTEXT *context, **/ void workbench_enable_live_update(WORKBENCH *wb) { +#ifdef __WB_LIVE_UPDATE if (wb != NULL) { sidebar_call_foreach(DATA_ID_DIRECTORY, workbench_enable_live_update_foreach_cb, wb->monitor); sidebar_call_foreach(DATA_ID_SUB_DIRECTORY, workbench_enable_live_update_foreach_cb, wb->monitor); } +#endif } @@ -1021,8 +1033,10 @@ void workbench_enable_live_update(WORKBENCH *wb) **/ void workbench_disable_live_update(WORKBENCH *wb) { +#ifdef __WB_LIVE_UPDATE if (wb != NULL) { wb_monitor_free(wb->monitor); } +#endif } -------------- This E-Mail was brought to you by github_commit_mail.py (Source:
https://github.com/geany/infrastructure
).
1
0
0
0
[geany/geany-plugins] a8a7db: workbench: make "live update"-feature depending on GIO and Glib version 2.46
by LarsDW223
04 Mar '18
04 Mar '18
Branch: refs/heads/master Author: LarsDW223 <lars_paulsen(a)web.de> Committer: LarsDW223 <lars_paulsen(a)web.de> Date: Sun, 04 Mar 2018 17:06:07 UTC Commit: a8a7dbfb53f22546c4fc6b2f70691111eaf6e327
https://github.com/geany/geany-plugins/commit/a8a7dbfb53f22546c4fc6b2f70691…
Log Message: ----------- workbench: make "live update"-feature depending on GIO and Glib version 2.46 Modified Paths: -------------- build/workbench.m4 workbench/src/dialogs.c workbench/src/wb_monitor.c workbench/src/wb_monitor.h workbench/src/wb_project.c workbench/src/workbench.c Modified: build/workbench.m4 6 lines changed, 6 insertions(+), 0 deletions(-) =================================================================== @@ -2,6 +2,12 @@ AC_DEFUN([GP_CHECK_WORKBENCH], [ GP_ARG_DISABLE([Workbench], [auto]) GP_CHECK_UTILSLIB([Workbench]) + + PKG_CHECK_MODULES([GIO], [gio-2.0], + [AC_DEFINE([HAVE_GIO], 1, [Whether we have GIO]) + have_gio=yes], + [have_gio=no]) + GP_COMMIT_PLUGIN_STATUS([Workbench]) AC_CONFIG_FILES([ workbench/Makefile Modified: workbench/src/dialogs.c 9 lines changed, 9 insertions(+), 0 deletions(-) =================================================================== @@ -440,10 +440,19 @@ gboolean dialogs_workbench_settings(WORKBENCH *workbench) w_enable_live_update = gtk_check_button_new_with_mnemonic(_("_Enable live update")); ui_table_add_row(GTK_TABLE(table), 1, w_enable_live_update, NULL); +#ifdef __WB_LIVE_UPDATE gtk_widget_set_tooltip_text(w_enable_live_update, _("If the option is activated (default), then the list of files and the sidebar" " will be updated automatically if a file or directory is created, removed or renamed." "A manual re-scan is not required if the option is enabled.")); +#else + gtk_widget_set_sensitive(w_enable_live_update, FALSE); + gtk_widget_set_tooltip_text(w_enable_live_update, + _("If the option is activated (default), then the list of files and the sidebar" + " will be updated automatically if a file or directory is created, removed or renamed." + "A manual re-scan is not required if the option is enabled.\n\n" + "This feature has been disabled because it is not available on your system.")); +#endif enable_live_update_old = workbench_get_enable_live_update(workbench); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w_enable_live_update), enable_live_update_old); Modified: workbench/src/wb_monitor.c 3 lines changed, 3 insertions(+), 0 deletions(-) =================================================================== @@ -31,6 +31,8 @@ #include "wb_monitor.h" #include "utils.h" +#ifdef __WB_LIVE_UPDATE + struct S_WB_MONITOR { GHashTable *monitors; @@ -265,3 +267,4 @@ void wb_monitor_free(WB_MONITOR *monitor) } } } +#endif Modified: workbench/src/wb_monitor.h 6 lines changed, 6 insertions(+), 0 deletions(-) =================================================================== @@ -22,12 +22,18 @@ #include <glib.h> #include "wb_project.h" +#if defined(HAVE_GIO) && GLIB_CHECK_VERSION (2, 46, 0) +#define __WB_LIVE_UPDATE 1 +#endif + typedef struct S_WB_MONITOR WB_MONITOR; +#ifdef __WB_LIVE_UPDATE WB_MONITOR *wb_monitor_new(void); void wb_monitor_add_dir(WB_MONITOR *monitor, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *dirpath); gboolean wb_monitor_remove_dir(WB_MONITOR *monitor, const gchar *dirpath); void wb_monitor_free(WB_MONITOR *monitor); +#endif #endif Modified: workbench/src/wb_project.c 11 lines changed, 11 insertions(+), 0 deletions(-) =================================================================== @@ -569,6 +569,7 @@ static guint wb_project_dir_rescan_int(WB_PROJECT *prj, WB_PROJECT_DIR *root) /* Add a new file to the project directory and update the sidebar. */ +#ifdef __WB_LIVE_UPDATE static void wb_project_dir_add_file_int(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) { gboolean matches; @@ -633,6 +634,8 @@ static void wb_project_dir_add_file_int(WB_PROJECT *prj, WB_PROJECT_DIR *root, c g_slist_free(scanned); } } +#endif + /** Add a new file to the project directory and update the sidebar. * @@ -643,16 +646,19 @@ static void wb_project_dir_add_file_int(WB_PROJECT *prj, WB_PROJECT_DIR *root, c * @param filepath The file to add. * **/ +#ifdef __WB_LIVE_UPDATE void wb_project_dir_add_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) { wb_project_dir_add_file_int(prj, root, filepath); wb_project_add_idle_action(WB_PROJECT_IDLE_ACTION_ID_UPDATE_TAGS, root, NULL); } +#endif /* Check if the filepath is equal for the length of the directory path in px_temp */ +#ifdef __WB_LIVE_UPDATE static gboolean wb_project_dir_remove_child (gpointer key, gpointer value, gpointer user_data) { WB_PROJECT_TEMP_DATA *px_temp; @@ -674,6 +680,7 @@ static gboolean wb_project_dir_remove_child (gpointer key, gpointer value, gpoin } return FALSE; } +#endif /** Remove a file from the project directory and update the sidebar. @@ -685,6 +692,7 @@ static gboolean wb_project_dir_remove_child (gpointer key, gpointer value, gpoin * @param filepath The file to remove. * **/ +#ifdef __WB_LIVE_UPDATE void wb_project_dir_remove_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) { gboolean matches, was_dir; @@ -760,6 +768,7 @@ void wb_project_dir_remove_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gch } } } +#endif /* Stolen and modified version from Geany. The only difference is that Geany @@ -923,6 +932,7 @@ void wb_project_rescan(WB_PROJECT *prj) } /* Create file monitors for directories. */ +#ifdef __WB_LIVE_UPDATE if (workbench_get_enable_live_update(wb_globals.opened_wb) == TRUE) { WB_MONITOR *monitor; @@ -952,6 +962,7 @@ void wb_project_rescan(WB_PROJECT *prj) } } } +#endif } Modified: workbench/src/workbench.c 14 lines changed, 14 insertions(+), 0 deletions(-) =================================================================== @@ -92,7 +92,9 @@ WORKBENCH *workbench_new(void) new_wb->enable_live_update = TRUE; new_wb->projects = g_ptr_array_new(); new_wb->bookmarks = g_ptr_array_new(); +#ifdef __WB_LIVE_UPDATE new_wb->monitor = wb_monitor_new(); +#endif return new_wb; } @@ -123,7 +125,9 @@ void workbench_free(WORKBENCH *wb) } } +#ifdef __WB_LIVE_UPDATE wb_monitor_free(wb->monitor); +#endif g_ptr_array_free (wb->projects, TRUE); g_free(wb); } @@ -916,6 +920,7 @@ static gboolean workbench_references_are_valid(WORKBENCH *wb, WB_PROJECT *prj, W * @param file The new file to add to project/directory * **/ +#ifdef __WB_LIVE_UPDATE void workbench_process_add_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *file) { if (workbench_references_are_valid(wb, prj, dir) == FALSE) @@ -928,6 +933,7 @@ void workbench_process_add_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT wb_project_dir_add_file(prj, dir, file); } +#endif /** Process the remove file event. @@ -942,6 +948,7 @@ void workbench_process_add_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT * @param file The file to remove from project/directory * **/ +#ifdef __WB_LIVE_UPDATE void workbench_process_remove_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *file) { if (workbench_references_are_valid(wb, prj, dir) == FALSE) @@ -954,9 +961,11 @@ void workbench_process_remove_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJ wb_project_dir_remove_file(prj, dir, file); } +#endif /* Foreach callback function for creating file monitors. */ +#ifdef __WB_LIVE_UPDATE static void workbench_enable_live_update_foreach_cb(SIDEBAR_CONTEXT *context, gpointer userdata) { @@ -986,6 +995,7 @@ static void workbench_enable_live_update_foreach_cb(SIDEBAR_CONTEXT *context, g_free(abs_path); } +#endif /** Enable live update. @@ -998,13 +1008,15 @@ static void workbench_enable_live_update_foreach_cb(SIDEBAR_CONTEXT *context, **/ void workbench_enable_live_update(WORKBENCH *wb) { +#ifdef __WB_LIVE_UPDATE if (wb != NULL) { sidebar_call_foreach(DATA_ID_DIRECTORY, workbench_enable_live_update_foreach_cb, wb->monitor); sidebar_call_foreach(DATA_ID_SUB_DIRECTORY, workbench_enable_live_update_foreach_cb, wb->monitor); } +#endif } @@ -1018,8 +1030,10 @@ void workbench_enable_live_update(WORKBENCH *wb) **/ void workbench_disable_live_update(WORKBENCH *wb) { +#ifdef __WB_LIVE_UPDATE if (wb != NULL) { wb_monitor_free(wb->monitor); } +#endif } -------------- This E-Mail was brought to you by github_commit_mail.py (Source:
https://github.com/geany/infrastructure
).
1
0
0
0
[geany/geany-plugins] 375449: Merge pull request #710 from LarsGit223/wb-issue709
by Frank Lanitz
04 Mar '18
04 Mar '18
Branch: refs/heads/master Author: Frank Lanitz <frank(a)frank.uvena.de> Committer: GitHub <noreply(a)github.com> Date: Sun, 04 Mar 2018 10:54:01 UTC Commit: 37544948c7600a34d0d3b0ed4a2066d22b15ef18
https://github.com/geany/geany-plugins/commit/37544948c7600a34d0d3b0ed4a206…
Log Message: ----------- Merge pull request #710 from LarsGit223/wb-issue709 workbench: import base path on "Add project..." Modified Paths: -------------- workbench/src/wb_project.c workbench/src/wb_project.h workbench/src/workbench.c Modified: workbench/src/wb_project.c 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -1562,7 +1562,7 @@ gboolean wb_project_save(WB_PROJECT *prj, GError **error) * @return TRUE on success, FALSE otherwise * **/ -gboolean wb_project_load(WB_PROJECT *prj, gchar *filename, GError **error) +gboolean wb_project_load(WB_PROJECT *prj, const gchar *filename, GError **error) { GKeyFile *kf; guint index; Modified: workbench/src/wb_project.h 2 lines changed, 1 insertions(+), 1 deletions(-) =================================================================== @@ -71,7 +71,7 @@ gchar *wb_project_get_bookmark_at_index (WB_PROJECT *prj, guint index); guint wb_project_get_bookmarks_count(WB_PROJECT *prj); gboolean wb_project_save(WB_PROJECT *prj, GError **error); -gboolean wb_project_load(WB_PROJECT *prj, gchar *filename, GError **error); +gboolean wb_project_load(WB_PROJECT *prj, const gchar *filename, GError **error); gchar *wb_project_get_info (WB_PROJECT *prj); Modified: workbench/src/workbench.c 3 lines changed, 3 insertions(+), 0 deletions(-) =================================================================== @@ -457,6 +457,9 @@ gboolean workbench_add_project(WORKBENCH *wb, const gchar *filename) } g_ptr_array_add (wb->projects, entry); + /* Load project to import base path. */ + wb_project_load(project, filename, NULL); + wb->modified = TRUE; return TRUE; } -------------- This E-Mail was brought to you by github_commit_mail.py (Source:
https://github.com/geany/infrastructure
).
1
0
0
0
[geany/geany-plugins] 328cb1: Merge pull request #696 from b4n/pohelper/wip
by Frank Lanitz
04 Mar '18
04 Mar '18
Branch: refs/heads/master Author: Frank Lanitz <frank(a)frank.uvena.de> Committer: GitHub <noreply(a)github.com> Date: Sun, 04 Mar 2018 10:18:50 UTC Commit: 328cb1835f502c581467c5c213946ccf325d4a2a
https://github.com/geany/geany-plugins/commit/328cb1835f502c581467c5c213946…
Log Message: ----------- Merge pull request #696 from b4n/pohelper/wip pohelper: Various fixes and improvements Modified Paths: -------------- pohelper/src/gph-plugin.c Modified: pohelper/src/gph-plugin.c 146 lines changed, 106 insertions(+), 40 deletions(-) =================================================================== @@ -39,7 +39,7 @@ PLUGIN_SET_TRANSLATABLE_INFO ( LOCALEDIR, GETTEXT_PACKAGE, _("Translation Helper"), _("Improves support for GetText translation files."), - "0.1", + VERSION, "Colomban Wendling <ban(a)herbesfolles.org>" ) @@ -453,19 +453,27 @@ goto_next_untranslated_or_fuzzy (GeanyDocument *doc) } } -/* basic regex search/replace without captures or back references */ +/* basic regex search/replace without captures or back references + * + * @sci A ScintillaObject + * @start Position where to start the search + * @end Position where to end the search, or -1 for the buffer's end + * @scire The Scintilla regular expression + * @repl The replacement text */ static gboolean regex_replace (ScintillaObject *sci, + gint start, + gint end, const gchar *scire, const gchar *repl) { struct Sci_TextToFind ttf; - ttf.chrg.cpMin = 0; - ttf.chrg.cpMax = sci_get_length (sci); + ttf.chrg.cpMin = start; + ttf.chrg.cpMax = end >= 0 ? end : sci_get_length (sci); ttf.lpstrText = (gchar *) scire; - if (sci_find_text (sci, SCFIND_REGEXP, &ttf)) { + if (sci_find_text (sci, SCFIND_REGEXP, &ttf) != -1) { sci_set_target_start (sci, (gint) ttf.chrgText.cpMin); sci_set_target_end (sci, (gint) ttf.chrgText.cpMax); sci_replace_target (sci, repl, FALSE); @@ -505,34 +513,6 @@ escape_string (const gchar *str) return new; } -static void -on_document_save (GObject *obj, - GeanyDocument *doc, - gpointer user_data) -{ - if (doc_is_po (doc) && plugin.update_headers) { - gchar *name = escape_string (geany_data->template_prefs->developer); - gchar *mail = escape_string (geany_data->template_prefs->mail); - gchar *date; - gchar *translator; - - date = utils_get_date_time ("\"PO-Revision-Date: %Y-%m-%d %H:%M%z\\n\"", - NULL); - translator = g_strdup_printf ("\"Last-Translator: %s <%s>\\n\"", - name, mail); - - sci_start_undo_action (doc->editor->sci); - regex_replace (doc->editor->sci, "^\"PO-Revision-Date: .*\"$", date); - regex_replace (doc->editor->sci, "^\"Last-Translator: .*\"$", translator); - sci_end_undo_action (doc->editor->sci); - - g_free (date); - g_free (translator); - g_free (name); - g_free (mail); - } -} - static void update_menu_items_sensitivity (GeanyDocument *doc) { @@ -858,6 +838,21 @@ get_msgid_text_at (GeanyDocument *doc, return NULL; } +static const gchar * +find_line_break (const gchar *str) +{ + for (; *str; str++) { + if (*str == '\\') { + if (str[1] == 'n') + return str; + else if (str[1]) + str++; + } + } + + return NULL; +} + /* cuts @str in human-readable chunks for max @len. * cuts first at \n, then at spaces and punctuation */ static gchar ** @@ -870,17 +865,21 @@ split_msg (const gchar *str, GString *chunk = g_string_sized_new (len); while (*str) { - const gchar *nl = strstr (str, "\\n"); - const gchar *p = strpbrk (str, " \t\v\r\n?!,.;:"); + const gchar *nl = find_line_break (str); + const gchar *p = strpbrk (str, " \t\v\r\n?!,.;:-"); glong chunk_len = g_utf8_strlen (chunk->str, (gssize) chunk->len); if (nl) nl += 2; - if (p) - p++; - else /* if there is no separator, use the end of the string */ + if (! p) /* if there is no separator, use the end of the string */ p = strchr (str, 0); + else { + p++; + /* try not to leave a space at the start of a chunk */ + while (*p == ' ') + p++; + } if (nl && ((gsize)(chunk_len + g_utf8_strlen (str, nl - str)) <= len || (nl < p && chunk->len == 0))) { @@ -932,8 +931,9 @@ on_kb_reflow (guint key_id) (uptr_t) start, end + 1 - start); msgstr_kw_len = start - sci_get_position_from_line (sci, sci_get_line_from_position (sci, start)); - if (msgstr_kw_len + len + 2 <= line_len) { - /* if all can go in the msgstr line, put it here */ + if (msgstr_kw_len + len + 2 <= line_len && + find_line_break (msgstr->str) == NULL) { + /* if all can go in the msgstr line and there's no newline, put it here */ gchar *text = g_strconcat ("\"", msgstr->str, "\"", NULL); sci_insert_text (sci, start, text); g_free (text); @@ -1192,6 +1192,72 @@ on_kb_toggle_fuzziness (guint key_id) } } +static gint +find_header_start (GeanyDocument *doc) +{ + if (doc_is_po (doc)) { + for (gint line = 0; line < sci_get_line_count (doc->editor->sci); line++) { + if (find_first_non_default_style_on_line (doc->editor->sci, line) == SCE_PO_MSGID) { + gint pos = sci_get_position_from_line (doc->editor->sci, line); + GString *str = get_msgid_text_at (doc, pos); + + if (str) { + gboolean is_header = (*str->str == 0); + + g_string_free (str, TRUE); + if (is_header) { + return pos; + } + } + } + } + } + + return -1; +} + +static void +on_document_save (GObject *obj, + GeanyDocument *doc, + gpointer user_data) +{ + gint header_start; + + if (doc_is_po (doc) && plugin.update_headers && + (header_start = find_header_start (doc)) >= 0) { + gchar *name = escape_string (geany_data->template_prefs->developer); + gchar *mail = escape_string (geany_data->template_prefs->mail); + gchar *date; + gchar *translator; + gchar *generator; + + date = utils_get_date_time ("\"PO-Revision-Date: %Y-%m-%d %H:%M%z\\n\"", + NULL); + translator = g_strdup_printf ("\"Last-Translator: %s <%s>\\n\"", + name, mail); + generator = g_strdup_printf ("\"X-Generator: Geany / PoHelper %s\\n\"", + VERSION); + + sci_start_undo_action (doc->editor->sci); + regex_replace (doc->editor->sci, + header_start, find_msgstr_end_at (doc, header_start) + 1, + "^\"PO-Revision-Date: .*\"$", date); + regex_replace (doc->editor->sci, + header_start, find_msgstr_end_at (doc, header_start) + 1, + "^\"Last-Translator: .*\"$", translator); + regex_replace (doc->editor->sci, + header_start, find_msgstr_end_at (doc, header_start) + 1, + "^\"X-Generator: .*\"$", generator); + sci_end_undo_action (doc->editor->sci); + + g_free (date); + g_free (translator); + g_free (generator); + g_free (name); + g_free (mail); + } +} + typedef struct { gdouble translated; gdouble fuzzy; -------------- This E-Mail was brought to you by github_commit_mail.py (Source:
https://github.com/geany/infrastructure
).
1
0
0
0
[geany/geany-plugins] ab5a45: Add missing file to POTIFLES.in
by Frank Lanitz
04 Mar '18
04 Mar '18
Branch: refs/heads/master Author: Frank Lanitz <frank(a)frank.uvena.de> Committer: Frank Lanitz <frank(a)frank.uvena.de> Date: Sun, 04 Mar 2018 06:26:10 UTC Commit: ab5a451c1cd58c09fd05816409ebb8a53920d567
https://github.com/geany/geany-plugins/commit/ab5a451c1cd58c09fd05816409ebb…
Log Message: ----------- Add missing file to POTIFLES.in Modified Paths: -------------- po/POTFILES.in Modified: po/POTFILES.in 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -320,6 +320,7 @@ workbench/src/popup_menu.c workbench/src/sidebar.c workbench/src/utils.c workbench/src/wb_globals.c +workbench/src/wb_monitor.c workbench/src/wb_project.c workbench/src/workbench.c -------------- This E-Mail was brought to you by github_commit_mail.py (Source:
https://github.com/geany/infrastructure
).
1
0
0
0
[geany/geany-plugins] da2dc1: Merge pull request #695 from LarsGit223/wb-liveupdate
by Frank Lanitz
04 Mar '18
04 Mar '18
Branch: refs/heads/master Author: Frank Lanitz <frank(a)frank.uvena.de> Committer: GitHub <noreply(a)github.com> Date: Sun, 04 Mar 2018 06:24:29 UTC Commit: da2dc1ef31bfb3a6fe13929d0095952d3a5b5b4c
https://github.com/geany/geany-plugins/commit/da2dc1ef31bfb3a6fe13929d00959…
Log Message: ----------- Merge pull request #695 from LarsGit223/wb-liveupdate workbench: support live update. Closes #659. Modified Paths: -------------- workbench/README workbench/src/Makefile.am workbench/src/dialogs.c workbench/src/menu.c workbench/src/plugin_main.c workbench/src/popup_menu.c workbench/src/sidebar.c workbench/src/sidebar.h workbench/src/wb_monitor.c workbench/src/wb_monitor.h workbench/src/wb_project.c workbench/src/wb_project.h workbench/src/workbench.c workbench/src/workbench.h Modified: workbench/README 31 lines changed, 29 insertions(+), 2 deletions(-) =================================================================== @@ -53,8 +53,8 @@ related settings is done using the context menu on the sidebar. Some items in the context menu will only be active if you right click inside a project, directory or bookmark. -The Workbench context menu: ---------------------------- +The Workbench context menu +-------------------------- These are the available items: @@ -141,6 +141,33 @@ These are the available items: Select this item to create a new directory at the current selected position in the file tree. Available since version 1.02 of the workbench plugin. +The Workbench settings +---------------------- +The following settings exist for a workbench: + +**Rescan all projects on open** + If the option is activated (default), then all projects will be re-scanned + on opening of a workbench. + +**Enable live update** + If the option is activated (default), then the list of files and the sidebar + will be updated automatically if a file or directory is created, removed or renamed. + A manual re-scan is not required if the option is enabled. This feature is available + since version 1.03 of the workbench plugin. If you open a workbench file + which has been created with an older version of the workbench plugin + then the option will be added with value "activated". + +Live update +----------- +From version 1.03 on the workbench plugin supports an automatic live update +of the file list and the sidebar. + +This feature will only work if your system supports directory file monitoring. +If the workbench plugin cannot setup file monitoring for a directory then it +will output a message in the message window. The message has the following form:: + + Could not setup file monitoring for directory: "exampledir". Error: <some error message> + Known issues ============ Modified: workbench/src/Makefile.am 2 lines changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -11,6 +11,8 @@ workbench_la_SOURCES = \ workbench.c \ wb_project.h \ wb_project.c \ + wb_monitor.h \ + wb_monitor.c \ dialogs.h \ dialogs.c \ menu.h \ Modified: workbench/src/dialogs.c 18 lines changed, 17 insertions(+), 1 deletions(-) =================================================================== @@ -407,11 +407,12 @@ gboolean dialogs_directory_settings(WB_PROJECT_DIR *directory) gboolean dialogs_workbench_settings(WORKBENCH *workbench) { gint result; - GtkWidget *w_rescan_projects_on_open; + GtkWidget *w_rescan_projects_on_open, *w_enable_live_update; GtkWidget *dialog, *content_area; GtkWidget *vbox, *hbox, *table; GtkDialogFlags flags; gboolean changed, rescan_projects_on_open, rescan_projects_on_open_old; + gboolean enable_live_update, enable_live_update_old; /* Create the widgets */ flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT; @@ -437,6 +438,15 @@ gboolean dialogs_workbench_settings(WORKBENCH *workbench) rescan_projects_on_open_old = workbench_get_rescan_projects_on_open(workbench); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w_rescan_projects_on_open), rescan_projects_on_open_old); + w_enable_live_update = gtk_check_button_new_with_mnemonic(_("_Enable live update")); + ui_table_add_row(GTK_TABLE(table), 1, w_enable_live_update, NULL); + gtk_widget_set_tooltip_text(w_enable_live_update, + _("If the option is activated (default), then the list of files and the sidebar" + " will be updated automatically if a file or directory is created, removed or renamed." + "A manual re-scan is not required if the option is enabled.")); + enable_live_update_old = workbench_get_enable_live_update(workbench); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w_enable_live_update), enable_live_update_old); + gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 6); hbox = gtk_hbox_new(FALSE, 0); @@ -456,6 +466,12 @@ gboolean dialogs_workbench_settings(WORKBENCH *workbench) changed = TRUE; workbench_set_rescan_projects_on_open(workbench, rescan_projects_on_open); } + enable_live_update = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w_enable_live_update)); + if (enable_live_update != enable_live_update_old) + { + changed = TRUE; + workbench_set_enable_live_update(workbench, enable_live_update); + } } gtk_widget_destroy(dialog); Modified: workbench/src/menu.c 18 lines changed, 18 insertions(+), 0 deletions(-) =================================================================== @@ -148,9 +148,27 @@ static void item_workbench_settings_activate_cb(G_GNUC_UNUSED GtkMenuItem *menui { if (wb_globals.opened_wb != NULL) { + gboolean enable_live_update_old, enable_live_update; + + enable_live_update_old = workbench_get_enable_live_update(wb_globals.opened_wb); if (dialogs_workbench_settings(wb_globals.opened_wb)) { sidebar_update(SIDEBAR_CONTEXT_WB_SETTINGS_CHANGED, NULL); + + enable_live_update = workbench_get_enable_live_update(wb_globals.opened_wb); + if (enable_live_update != enable_live_update_old) + { + if (enable_live_update == TRUE) + { + /* Start/create all file monitors. */ + workbench_enable_live_update(wb_globals.opened_wb); + } + else + { + /* Stop/free all file monitors. */ + workbench_disable_live_update(wb_globals.opened_wb); + } + } } } } Modified: workbench/src/plugin_main.c 8 lines changed, 5 insertions(+), 3 deletions(-) =================================================================== @@ -46,7 +46,8 @@ static void plugin_workbench_on_doc_open(G_GNUC_UNUSED GObject * obj, G_GNUC_UNU project = workbench_file_is_included(wb_globals.opened_wb, doc->file_name); if (project != NULL) { - wb_project_remove_single_tm_file(project, doc->file_name); + wb_project_add_idle_action(WB_PROJECT_IDLE_ACTION_ID_REMOVE_SINGLE_TM_FILE, + project, g_strdup(doc->file_name)); } } @@ -69,7 +70,8 @@ static void plugin_workbench_on_doc_close(G_GNUC_UNUSED GObject * obj, GeanyDocu project = workbench_file_is_included(wb_globals.opened_wb, doc->file_name); if (project != NULL) { - wb_project_add_single_tm_file(project, doc->file_name); + wb_project_add_idle_action(WB_PROJECT_IDLE_ACTION_ID_ADD_SINGLE_TM_FILE, + project, g_strdup(doc->file_name)); } } @@ -128,7 +130,7 @@ void geany_load_module(GeanyPlugin *plugin) /* Set metadata */ plugin->info->name = _("Workbench"); plugin->info->description = _("Manage and customize multiple projects."); - plugin->info->version = "1.02"; + plugin->info->version = "1.03"; plugin->info->author = "LarsGit223"; /* Set functions */ Modified: workbench/src/popup_menu.c 20 lines changed, 16 insertions(+), 4 deletions(-) =================================================================== @@ -561,8 +561,15 @@ static void popup_menu_on_new_file(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_U else { fclose(new_file); - wb_project_dir_rescan(context.project, context.directory); - sidebar_update(SIDEBAR_CONTEXT_DIRECTORY_RESCANNED, &context); + + if (workbench_get_enable_live_update(wb_globals.opened_wb) == FALSE) + { + /* Live update is disabled. We need to update the file list and + the sidebar manually. */ + wb_project_dir_rescan(context.project, context.directory); + sidebar_update(SIDEBAR_CONTEXT_DIRECTORY_RESCANNED, &context); + } + document_open_file(filename, FALSE, NULL, NULL); } } @@ -595,8 +602,13 @@ static void popup_menu_on_new_directory(G_GNUC_UNUSED GtkMenuItem *menuitem, G_G filename = dialogs_create_new_directory(abs_path); if (filename != NULL) { - wb_project_dir_rescan(context.project, context.directory); - sidebar_update(SIDEBAR_CONTEXT_DIRECTORY_RESCANNED, &context); + if (workbench_get_enable_live_update(wb_globals.opened_wb) == FALSE) + { + /* Live update is disabled. We need to update the file list and + the sidebar manually. */ + wb_project_dir_rescan(context.project, context.directory); + sidebar_update(SIDEBAR_CONTEXT_DIRECTORY_RESCANNED, &context); + } } g_free(abs_path); Modified: workbench/src/sidebar.c 374 lines changed, 362 insertions(+), 12 deletions(-) =================================================================== @@ -33,18 +33,6 @@ #include "popup_menu.h" #include "utils.h" -enum -{ - DATA_ID_UNSET = 0, - DATA_ID_WB_BOOKMARK, - DATA_ID_PROJECT, - DATA_ID_PRJ_BOOKMARK, - DATA_ID_DIRECTORY, - DATA_ID_NO_DIRS, - DATA_ID_SUB_DIRECTORY, - DATA_ID_FILE, -}; - enum { FILEVIEW_COLUMN_ICON, @@ -61,12 +49,29 @@ typedef enum MATCH_PATTERN } MatchType; +typedef struct +{ + gboolean iter_valid; + GtkTreeIter iter; + gboolean parent_valid; + GtkTreeIter parent; +}ITER_SEARCH_RESULT; + typedef struct { GeanyProject *project; GPtrArray *expanded_paths; } ExpandData; +typedef struct +{ + SIDEBAR_CONTEXT *context; + GtkTreeModel *model; + guint dataid; + void (*func)(SIDEBAR_CONTEXT *, gpointer userdata); + gpointer userdata; +}SB_CALLFOREACH_CONTEXT; + typedef struct SIDEBAR { GtkWidget *file_view_vbox; @@ -76,6 +81,9 @@ typedef struct SIDEBAR }SIDEBAR; static SIDEBAR sidebar = {NULL, NULL, NULL, NULL}; +static gboolean sidebar_get_directory_iter(WB_PROJECT *prj, WB_PROJECT_DIR *dir, GtkTreeIter *iter); +static gboolean sidebar_get_filepath_iter (WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath, ITER_SEARCH_RESULT *result); + /* Remove all child nodes below parent */ static void sidebar_remove_children(GtkTreeIter *parent) { @@ -363,6 +371,104 @@ static void sidebar_insert_project_directories (WB_PROJECT *project, GtkTreeIter } +/* Add a file to the sidebar. filepath can be a file or directory. */ +static void sidebar_add_file (WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) +{ + GIcon *icon = NULL; + gchar *name; + guint dataid; + ITER_SEARCH_RESULT search_result; + + if (!sidebar_get_filepath_iter(prj, root, filepath, &search_result)) + { + return; + } + else + { + if (search_result.iter_valid) + { + /* Error, file already exists in sidebar tree. */ + return; + } + else + { + /* This is the expected result as we want to add a new file node. + But parent should be valid. */ + if (!search_result.parent_valid) + { + return; + } + } + } + + /* Collect data */ + name = g_path_get_basename(filepath); + if (g_file_test (filepath, G_FILE_TEST_IS_DIR)) + { + dataid = DATA_ID_SUB_DIRECTORY; + icon = g_icon_new_for_string("folder", NULL); + } + else + { + dataid = DATA_ID_FILE; + + gchar *content_type = g_content_type_guess(filepath, NULL, 0, NULL); + if (content_type) + { + icon = g_content_type_get_icon(content_type); + if (icon) + { + GtkIconInfo *icon_info; + + icon_info = gtk_icon_theme_lookup_by_gicon(gtk_icon_theme_get_default(), icon, 16, 0); + if (!icon_info) + { + g_object_unref(icon); + icon = NULL; + } + else + gtk_icon_info_free(icon_info); + } + g_free(content_type); + } + + } + + /* Create new row/node in sidebar tree. */ + gtk_tree_store_insert_with_values(sidebar.file_store, &search_result.iter, &search_result.parent, -1, + FILEVIEW_COLUMN_ICON, icon, + FILEVIEW_COLUMN_NAME, name, + FILEVIEW_COLUMN_DATA_ID, dataid, + FILEVIEW_COLUMN_ASSIGNED_DATA_POINTER, g_strdup(filepath), + -1); + + if (icon) + { + g_object_unref(icon); + } +} + + +/* Remove a file from the sidebar. filepath can be a file or directory. */ +static void sidebar_remove_file (WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) +{ + ITER_SEARCH_RESULT search_result; + + if (!sidebar_get_filepath_iter(prj, root, filepath, &search_result)) + { + return; + } + else + { + if (search_result.iter_valid) + { + /* File was found, remove the node. */ + gtk_tree_store_remove(sidebar.file_store, &search_result.iter); + } + } +} + + /* Get the GtkTreeIter for project prj */ static gboolean sidebar_get_project_iter(WB_PROJECT *prj, GtkTreeIter *iter) { @@ -386,6 +492,140 @@ static gboolean sidebar_get_project_iter(WB_PROJECT *prj, GtkTreeIter *iter) } +/* Get the GtkTreeIter for directory dir in project prj */ +static gboolean sidebar_get_directory_iter(WB_PROJECT *prj, WB_PROJECT_DIR *dir, GtkTreeIter *iter) +{ + GtkTreeIter parent; + GtkTreeModel *model; + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(sidebar.file_view)); + if (sidebar_get_project_iter(prj, iter)) + { + parent = *iter; + if (gtk_tree_model_iter_children (model, iter, &parent)) + { + WB_PROJECT_DIR *current; + + do + { + gtk_tree_model_get(model, iter, FILEVIEW_COLUMN_ASSIGNED_DATA_POINTER, ¤t, -1); + if (current == dir) + { + return TRUE; + } + }while (gtk_tree_model_iter_next(model, iter)); + } + } + return FALSE; +} + + +/* Get the GtkTreeIter for filepath (absolute) in directory root in project prj */ +static gboolean sidebar_get_filepath_iter (WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath, ITER_SEARCH_RESULT *search_result) +{ + guint len, index; + gchar *part, **parts, *found = NULL, *last_found, *abs_base_dir; + GtkTreeIter iter, parent; + GtkTreeModel *model; + + if (search_result == NULL) + { + return FALSE; + } + search_result->iter_valid = FALSE; + search_result->parent_valid = FALSE; + + abs_base_dir = get_combined_path(wb_project_get_filename(prj), wb_project_dir_get_base_dir(root)); + len = strlen(abs_base_dir); + if (strncmp(abs_base_dir, filepath, len) != 0) + { + /* Error, return. */ + return FALSE; + } + if (filepath[len] == G_DIR_SEPARATOR) + { + len++; + } + part = g_strdup(&(filepath[len])); + if (strlen(part) == 0) + { + return FALSE; + } + parts = g_strsplit(part, G_DIR_SEPARATOR_S, -1); + if (parts[0] == NULL) + { + return FALSE; + } + + if (sidebar_get_directory_iter(prj, root, &iter)) + { + index = 0; + last_found = NULL; + model = gtk_tree_view_get_model(GTK_TREE_VIEW(sidebar.file_view)); + + while (parts[index] != NULL) + { + parent = iter; + if (gtk_tree_model_iter_children(model, &iter, &parent)) + { + gchar *current; + + found = NULL; + do + { + gtk_tree_model_get(model, &iter, FILEVIEW_COLUMN_NAME, ¤t, -1); + + if (g_strcmp0(current, parts[index]) == 0) + { + found = current; + last_found = current; + index++; + //parent = iter; + break; + } + }while (gtk_tree_model_iter_next(model, &iter)); + + /* Did we find the next match? */ + if (found == NULL) + { + /* No, abort. */ + break; + } + } + else + { + break; + } + } + + /* Did we find a full match? */ + if (parts[index] == NULL && found != NULL) + { + /* Yes. */ + search_result->iter_valid = TRUE; + search_result->iter = iter; + + search_result->parent_valid = TRUE; + search_result->parent = parent; + } + else if (parts[index+1] == NULL && + (last_found != NULL || parts[1] == NULL)) + { + /* Not a full match but everything but the last part + of the filepath. At least return the parent. */ + search_result->parent_valid = TRUE; + search_result->parent = parent; + } + } + + g_free(part); + g_free(abs_base_dir); + g_strfreev(parts); + + return TRUE; +} + + /* Remove all rows from the side bar tree with the given data id */ static void sidebar_remove_nodes_with_data_id(guint toremove, GtkTreeIter *start) { @@ -710,6 +950,12 @@ void sidebar_update (SIDEBAR_EVENT event, SIDEBAR_CONTEXT *context) } } break; + case SIDEBAR_CONTEXT_FILE_ADDED: + sidebar_add_file(context->project, context->directory, context->file); + break; + case SIDEBAR_CONTEXT_FILE_REMOVED: + sidebar_remove_file(context->project, context->directory, context->file); + break; } } @@ -1325,3 +1571,107 @@ void sidebar_toggle_selected_project_dir_expansion (void) gtk_tree_path_free(path); } } + + +/* Helper function to set context according to given parameters. */ +static void sidebar_set_context (SIDEBAR_CONTEXT *context, guint dataid, gpointer data) +{ + if (data != NULL) + { + switch (dataid) + { + case DATA_ID_WB_BOOKMARK: + memset(context, 0, sizeof(*context)); + context->wb_bookmark = data; + break; + case DATA_ID_PROJECT: + memset(context, 0, sizeof(*context)); + context->project = data; + break; + case DATA_ID_PRJ_BOOKMARK: + context->prj_bookmark = data; + context->directory = NULL; + context->subdir = NULL; + context->file = NULL; + break; + case DATA_ID_DIRECTORY: + context->directory = data; + context->subdir = NULL; + context->file = NULL; + break; + case DATA_ID_NO_DIRS: + /* Has not got any data. */ + break; + case DATA_ID_SUB_DIRECTORY: + context->subdir = data; + context->file = NULL; + break; + case DATA_ID_FILE: + context->file = data; + break; + } + } +} + + +/* Internal call foreach function. Traverses the whole sidebar. */ +void sidebar_call_foreach_int(SB_CALLFOREACH_CONTEXT *foreach_cntxt, + GtkTreeIter *iter) +{ + guint currentid; + gpointer current; + GtkTreeIter children; + + do + { + gtk_tree_model_get(foreach_cntxt->model, iter, FILEVIEW_COLUMN_DATA_ID, ¤tid, -1); + gtk_tree_model_get(foreach_cntxt->model, iter, FILEVIEW_COLUMN_ASSIGNED_DATA_POINTER, ¤t, -1); + + sidebar_set_context(foreach_cntxt->context, currentid, current); + if (currentid == foreach_cntxt->dataid) + { + /* Found requested node. Call callback function. */ + foreach_cntxt->func(foreach_cntxt->context, foreach_cntxt->userdata); + } + + /* If the node has childs then check them to. */ + if (gtk_tree_model_iter_children (foreach_cntxt->model, &children, iter)) + { + sidebar_call_foreach_int(foreach_cntxt, &children); + } + }while (gtk_tree_model_iter_next(foreach_cntxt->model, iter)); +} + + +/** Call a callback function for each matching node. + * + * This function traverses the complete sidebar tree and calls func each time + * a node with dataid is found. The function is passed the sidebar context + * for the current position in hte tree and the given userdata. + * + * @param dataid Which nodes are of interest? + * @param func Callback function + * @param userdata Pointer to user data. Is transparently passed through + * on calling func. + * + **/ +void sidebar_call_foreach(guint dataid, + void (*func)(SIDEBAR_CONTEXT *, gpointer userdata), + gpointer userdata) +{ + GtkTreeIter iter; + GtkTreeModel *model; + SIDEBAR_CONTEXT context; + SB_CALLFOREACH_CONTEXT foreach_cntxt; + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(sidebar.file_view)); + if (gtk_tree_model_get_iter_first (model, &iter)) + { + foreach_cntxt.context = &context; + foreach_cntxt.model = model; + foreach_cntxt.dataid = dataid; + foreach_cntxt.func = func; + foreach_cntxt.userdata = userdata; + sidebar_call_foreach_int(&foreach_cntxt, &iter); + } +} Modified: workbench/src/sidebar.h 17 lines changed, 17 insertions(+), 0 deletions(-) =================================================================== @@ -22,6 +22,18 @@ #include <gtk/gtk.h> #include "wb_project.h" +enum +{ + DATA_ID_UNSET = 0, + DATA_ID_WB_BOOKMARK, + DATA_ID_PROJECT, + DATA_ID_PRJ_BOOKMARK, + DATA_ID_DIRECTORY, + DATA_ID_NO_DIRS, + DATA_ID_SUB_DIRECTORY, + DATA_ID_FILE, +}; + typedef struct { WB_PROJECT *project; @@ -50,6 +62,8 @@ typedef enum SIDEBAR_CONTEXT_WB_BOOKMARK_REMOVED, SIDEBAR_CONTEXT_PRJ_BOOKMARK_ADDED, SIDEBAR_CONTEXT_PRJ_BOOKMARK_REMOVED, + SIDEBAR_CONTEXT_FILE_ADDED, + SIDEBAR_CONTEXT_FILE_REMOVED, }SIDEBAR_EVENT; void sidebar_init(void); @@ -76,4 +90,7 @@ GPtrArray *sidebar_get_selected_project_filelist (void); GPtrArray *sidebar_get_selected_directory_filelist (void); GPtrArray *sidebar_get_selected_subdir_filelist (void); +void sidebar_call_foreach(guint dataid, + void (func)(SIDEBAR_CONTEXT *, gpointer userdata), gpointer userdata); + #endif Modified: workbench/src/wb_monitor.c 267 lines changed, 267 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,267 @@ +/* + * Copyright 2018 LarsGit223 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* + * Code for file monitoring. + */ +#include <glib/gstdio.h> + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <geanyplugin.h> +#include "wb_globals.h" +#include "workbench.h" +#include "wb_monitor.h" +#include "utils.h" + +struct S_WB_MONITOR +{ + GHashTable *monitors; +}; + +typedef struct +{ + GFileMonitor *monitor; + WB_PROJECT *prj; + WB_PROJECT_DIR *dir; +}WB_MONITOR_ENTRY; + + +/** Create a new, empty WB_MONITOR. + * + * @return Address of the new WB_MONITOR + * + **/ +WB_MONITOR *wb_monitor_new(void) +{ + WB_MONITOR *monitor; + + monitor = g_new0(WB_MONITOR, 1); + + return monitor; +} + + +/* Create a new monitor entry */ +static WB_MONITOR_ENTRY *wb_monitor_entry_new (GFileMonitor *monitor, + WB_PROJECT *prj, WB_PROJECT_DIR *dir) +{ + WB_MONITOR_ENTRY *new; + + new = g_new0(WB_MONITOR_ENTRY, 1); + new->monitor = monitor; + new->prj = prj; + new->dir = dir; + + return new; +} + + +/* Free a monitor entry */ +static void wb_monitor_entry_free (gpointer data) +{ + WB_MONITOR_ENTRY *entry = data; + + if (data != NULL) + { + g_object_unref(entry->monitor); + g_free(entry); + } +} + + +/* Callback function for file monitoring. */ +static void wb_monitor_file_changed_cb(G_GNUC_UNUSED GFileMonitor *monitor, + G_GNUC_UNUSED GFile *file, + G_GNUC_UNUSED GFile *other_file, + GFileMonitorEvent event, + WB_MONITOR_ENTRY *entry) +{ + const gchar *event_string = NULL; + gchar *file_path, *other_file_path = NULL; + + g_return_if_fail(entry != NULL); + + g_message("%s: event: %d", G_STRFUNC, event); + + file_path = g_file_get_path (file); + if (other_file != NULL) + { + other_file_path = g_file_get_path (other_file); + } + switch (event) + { + case G_FILE_MONITOR_EVENT_CREATED: + event_string = "FILE_CREATED"; + workbench_process_add_file_event (wb_globals.opened_wb, + entry->prj, entry->dir, file_path); + break; + + case G_FILE_MONITOR_EVENT_DELETED: + event_string = "FILE_DELETED"; + workbench_process_remove_file_event (wb_globals.opened_wb, + entry->prj, entry->dir, file_path); + break; + + case G_FILE_MONITOR_EVENT_RENAMED: + event_string = "FILE_RENAMED"; + workbench_process_remove_file_event (wb_globals.opened_wb, + entry->prj, entry->dir, file_path); + workbench_process_add_file_event (wb_globals.opened_wb, + entry->prj, entry->dir, other_file_path); + break; + + case G_FILE_MONITOR_EVENT_MOVED_IN: + event_string = "FILE_MOVED_IN"; + workbench_process_add_file_event (wb_globals.opened_wb, + entry->prj, entry->dir, file_path); + break; + + case G_FILE_MONITOR_EVENT_MOVED_OUT: + event_string = "FILE_MOVED_OUT"; + workbench_process_remove_file_event (wb_globals.opened_wb, + entry->prj, entry->dir, file_path); + break; + + default: + break; + } + + if (event_string != NULL) + { + g_message("%s: Prj: \"%s\" Dir: \"%s\" %s: \"%s\"", G_STRFUNC, wb_project_get_name(entry->prj), + wb_project_dir_get_name(entry->dir), event_string, file_path); + } + + g_free(file_path); + g_free(other_file_path); +} + + +/** Add a new file monitor + * + * Add a new file monitor for dirpath. The monitor will only be created + * if the settings option "Enable live monitor" is set to on and if + * no file monitor exists for dirpath already. If monitor creation fails, + * that means g_file_monitor_directory returns NULL, then a message is + * output on the statusbar. + * + * @param monitor The global monitor management + * @param prj The project to which dirpath belongs + * @param dir The directory (WB_PROJECT_DIR) to which dirpath belongs + * @param dirpath The path of the directory + * + **/ +void wb_monitor_add_dir(WB_MONITOR *monitor, WB_PROJECT *prj, + WB_PROJECT_DIR *dir, const gchar *dirpath) +{ + GFileMonitor *newmon; + GFile *file; + GError *error = NULL; + WB_MONITOR_ENTRY *entry; + + g_return_if_fail(monitor != NULL); + g_return_if_fail(dir != NULL); + g_return_if_fail(dirpath != NULL); + + if (workbench_get_enable_live_update(wb_globals.opened_wb) == FALSE) + { + /* Return if the feature is disabled. */ + return; + } + + if (monitor->monitors == NULL) + { + monitor->monitors = g_hash_table_new_full + (g_str_hash, g_str_equal, g_free, wb_monitor_entry_free); + } + if (g_hash_table_contains(monitor->monitors, dirpath)) + { + /* A monitor for that path already exists, + do not create another one. */ + return; + } + + /* Setup file monitor for directory */ + file = g_file_new_for_path(dirpath); + newmon = g_file_monitor_directory + (file, G_FILE_MONITOR_WATCH_MOVES, NULL, &error); + if (newmon == NULL) + { + /* Create monitor failed. Report error. */ + ui_set_statusbar(TRUE, + _("Could not setup file monitoring for directory: \"%s\". Error: %s"), + dirpath, error->message); + g_error_free (error); + return; + } + else + { + /* Add file monitor to hash table. */ + entry = wb_monitor_entry_new(newmon, prj, dir); + g_hash_table_insert(monitor->monitors, (gpointer)g_strdup(dirpath), entry); + + g_signal_connect(newmon, "changed", + G_CALLBACK(wb_monitor_file_changed_cb), entry); + + /* ToDo: make rate limit configurable */ + g_file_monitor_set_rate_limit(newmon, 5 * 1000); + } + g_object_unref(file); +} + + +/** Remove a file monitor + * + * Remove the file monitor for dirpath. + * + * @param monitor The global monitor management + * @param dirpath The path of the directory + * + **/ +gboolean wb_monitor_remove_dir(WB_MONITOR *monitor, const gchar *dirpath) +{ + if (monitor == NULL || dirpath == NULL) + { + return FALSE; + } + + /* Free the entry. The hash table will call the destroy function + wb_monitor_entry_free which is doing the work for us. */ + return g_hash_table_remove(monitor->monitors, dirpath); +} + + +/** Free monitor management/all file monitors. + * + * @param monitor The global monitor management + * + **/ +void wb_monitor_free(WB_MONITOR *monitor) +{ + if (monitor != NULL) + { + if (monitor->monitors != NULL) + { + g_hash_table_unref(monitor->monitors); + monitor->monitors = NULL; + } + } +} Modified: workbench/src/wb_monitor.h 33 lines changed, 33 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,33 @@ +/* + * Copyright 2018 LarsGit223 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __WB_MONITOR_H__ +#define __WB_MONITOR_H__ + +#include <glib.h> +#include "wb_project.h" + +typedef struct S_WB_MONITOR WB_MONITOR; + +WB_MONITOR *wb_monitor_new(void); +void wb_monitor_add_dir(WB_MONITOR *monitor, WB_PROJECT *prj, + WB_PROJECT_DIR *dir, const gchar *dirpath); +gboolean wb_monitor_remove_dir(WB_MONITOR *monitor, const gchar *dirpath); +void wb_monitor_free(WB_MONITOR *monitor); + +#endif Modified: workbench/src/wb_project.c 508 lines changed, 406 insertions(+), 102 deletions(-) =================================================================== @@ -29,6 +29,7 @@ #include <../../utils/src/filelist.h> #include "wb_globals.h" #include "wb_project.h" +#include "sidebar.h" #include "utils.h" extern GeanyData *geany_data; @@ -40,6 +41,13 @@ typedef enum WB_PROJECT_TAG_PREFS_NO, }WB_PROJECT_TAG_PREFS; +typedef struct +{ + WB_PROJECT_IDLE_ACTION_ID id; + gpointer param_a; + gpointer param_b; +}WB_PROJECT_IDLE_ACTION; + typedef struct { GKeyFile *kf; @@ -64,13 +72,21 @@ struct S_WB_PROJECT gchar *filename; gchar *name; gboolean modified; - GSList *s_idle_add_funcs; - GSList *s_idle_remove_funcs; + //GSList *s_idle_add_funcs; + //GSList *s_idle_remove_funcs; GSList *directories; /* list of WB_PROJECT_DIR; */ WB_PROJECT_TAG_PREFS generate_tag_prefs; GPtrArray *bookmarks; }; +typedef struct +{ + guint len; + const gchar *string; +}WB_PROJECT_TEMP_DATA; + +static GSList *s_idle_actions = NULL; +static void wb_project_dir_update_tags(WB_PROJECT_DIR *root); /** Set the projects modified marker. * @@ -212,26 +228,26 @@ static gboolean match_basename(gconstpointer pft, gconstpointer user_data) /* Clear idle queue */ -static void wb_project_clear_idle_queue(GSList **queue) +static void wb_project_clear_idle_queue(void) { - if (queue == NULL || *queue == NULL) + if (s_idle_actions == NULL) { return; } - g_slist_free_full(*queue, g_free); - *queue = NULL; + g_slist_free_full(s_idle_actions, g_free); + s_idle_actions = NULL; } /* Create a new project dir with base path "utf8_base_dir" */ -static WB_PROJECT_DIR *wb_project_dir_new(const gchar *utf8_base_dir) +static WB_PROJECT_DIR *wb_project_dir_new(WB_PROJECT *prj, const gchar *utf8_base_dir) { guint offset; if (utf8_base_dir == NULL) { - return NULL; + return NULL; } WB_PROJECT_DIR *dir = g_new0(WB_PROJECT_DIR, 1); dir->base_dir = g_strdup(utf8_base_dir); @@ -250,6 +266,7 @@ static WB_PROJECT_DIR *wb_project_dir_new(const gchar *utf8_base_dir) } dir->name = g_strdup(&(dir->base_dir[offset])); dir->is_prj_base_dir = FALSE; + return dir; } @@ -551,6 +568,200 @@ static guint wb_project_dir_rescan_int(WB_PROJECT *prj, WB_PROJECT_DIR *root) } +/* Add a new file to the project directory and update the sidebar. */ +static void wb_project_dir_add_file_int(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) +{ + gboolean matches; + gchar **file_patterns = NULL; + SIDEBAR_CONTEXT context; + WB_MONITOR *monitor = NULL; + + if (root->file_patterns && root->file_patterns[0]) + { + file_patterns = root->file_patterns; + } + + matches = gp_filelist_filepath_matches_patterns(filepath, + file_patterns, root->ignored_dirs_patterns, root->ignored_file_patterns); + if (!matches) + { + /* Ignore it. */ + return; + } + + /* Update file table and counters. */ + g_hash_table_insert(root->file_table, g_strdup(filepath), NULL); + if (g_file_test(filepath, G_FILE_TEST_IS_DIR)) + { + root->subdir_count++; + monitor = workbench_get_monitor(wb_globals.opened_wb); + wb_monitor_add_dir(monitor, prj, root, filepath); + } + else if (g_file_test(filepath, G_FILE_TEST_IS_REGULAR)) + { + root->file_count++; + } + + /* Update sidebar. */ + memset(&context, 0, sizeof(context)); + context.project = prj; + context.directory = root; + context.file = (gchar *)filepath; + sidebar_update(SIDEBAR_CONTEXT_FILE_ADDED, &context); + + /* If the file is a directory we also have to manually add all files + contained in it. */ + if (monitor != NULL) + { + GSList *scanned, *elem = NULL; + + scanned = gp_filelist_scan_directory_full(&(root->file_count), &(root->subdir_count), + filepath, file_patterns, root->ignored_dirs_patterns, root->ignored_file_patterns, + FILELIST_FLAG_ADD_DIRS); + + foreach_slist(elem, scanned) + { + char *path = elem->data; + + if (path) + { + wb_project_dir_add_file(prj, root, path); + } + } + + g_slist_foreach(scanned, (GFunc) g_free, NULL); + g_slist_free(scanned); + } +} + +/** Add a new file to the project directory and update the sidebar. + * + * The file is only added if it matches the pattern settings. + * + * @param prj The project to add it to. + * @param root The directory to add it to. + * @param filepath The file to add. + * + **/ +void wb_project_dir_add_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) +{ + wb_project_dir_add_file_int(prj, root, filepath); + wb_project_add_idle_action(WB_PROJECT_IDLE_ACTION_ID_UPDATE_TAGS, + root, NULL); + +} + + +/* Check if the filepath is equal for the length of the directory path in px_temp */ +static gboolean wb_project_dir_remove_child (gpointer key, gpointer value, gpointer user_data) +{ + WB_PROJECT_TEMP_DATA *px_temp; + TMSourceFile *sf; + + px_temp = user_data; + if (strncmp(px_temp->string, key, px_temp->len) == 0) + { + /* We found a child of our removed directory. + Remove it from the hash table. This will also free + the tags. We do not need to update the sidebar as we + already deleted the parent directory/node. */ + sf = value; + if (sf != NULL) + { + tm_workspace_remove_source_file(sf); + } + return TRUE; + } + return FALSE; +} + + +/** Remove a file from the project directory and update the sidebar. + * + * If the file still exists, it is only removed if it matches the pattern settings. + * + * @param prj The project to remove it from. + * @param root The directory to remove it from. + * @param filepath The file to remove. + * + **/ +void wb_project_dir_remove_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath) +{ + gboolean matches, was_dir; + gchar **file_patterns = NULL; + WB_MONITOR *monitor; + + if (root->file_patterns && root->file_patterns[0]) + { + file_patterns = root->file_patterns; + } + + if (g_file_test(filepath, G_FILE_TEST_EXISTS)) + { + matches = gp_filelist_filepath_matches_patterns(filepath, + file_patterns, root->ignored_dirs_patterns, root->ignored_file_patterns); + } + else + { + /* If the file does not exist any more, then always try to remove it. */ + matches = TRUE; + } + + if (matches) + { + SIDEBAR_CONTEXT context; + TMSourceFile *sf; + + /* Update file table and counters. */ + sf = g_hash_table_lookup (root->file_table, filepath); + if (sf != NULL) + { + tm_workspace_remove_source_file(sf); + } + g_hash_table_remove(root->file_table, filepath); + + /* If the file already has been deleted, we cannot determine if it + was a file or directory at this point. But the monitors will + help us out, see code at end of function. */ + + /* Update sidebar. */ + memset(&context, 0, sizeof(context)); + context.project = prj; + context.directory = root; + context.file = (gchar *)filepath; + sidebar_update(SIDEBAR_CONTEXT_FILE_REMOVED, &context); + } + + /* Remove the file monitor for filepath. This will only return TRUE + if there is a file monitor for filepath and that means that file- + path was a directory. So we can determine if filepath was a dir + or not even if it has been deleted. */ + monitor = workbench_get_monitor(wb_globals.opened_wb); + was_dir = wb_monitor_remove_dir(monitor, filepath); + if (was_dir) + { + WB_PROJECT_TEMP_DATA x_temp; + + x_temp.len = strlen(filepath); + x_temp.string = filepath; + g_hash_table_foreach_remove(root->file_table, + wb_project_dir_remove_child, &x_temp); + + if (root->subdir_count > 0) + { + root->subdir_count--; + } + } + else + { + if (root->file_count > 0) + { + root->file_count--; + } + } +} + + /* Stolen and modified version from Geany. The only difference is that Geany * first looks at shebang inside the file and then, if it fails, checks the * file extension. Opening every file is too expensive so instead check just @@ -631,6 +842,37 @@ static void wb_project_dir_regenerate_tags(WB_PROJECT_DIR *root, G_GNUC_UNUSED g } +/* Update tags for new files */ +static void wb_project_dir_update_tags(WB_PROJECT_DIR *root) +{ + GHashTableIter iter; + gpointer key, value; + GPtrArray *source_files; + + source_files = g_ptr_array_new(); + g_hash_table_iter_init(&iter, root->file_table); + while (g_hash_table_iter_next(&iter, &key, &value)) + { + if (value == NULL) + { + TMSourceFile *sf; + gchar *utf8_path = key; + gchar *locale_path = utils_get_locale_from_utf8(utf8_path); + + sf = tm_source_file_new(locale_path, filetypes_detect(utf8_path)->name); + if (sf && !document_find_by_filename(utf8_path)) + g_ptr_array_add(source_files, sf); + + g_hash_table_insert(root->file_table, g_strdup(utf8_path), sf); + g_free(locale_path); + } + } + + tm_workspace_add_source_files(source_files); + g_ptr_array_free(source_files, TRUE); +} + + /** Rescan/update the file list of a project dir. * * @param project The project to which directory belongs @@ -661,14 +903,14 @@ void wb_project_rescan(WB_PROJECT *prj) { GSList *elem = NULL; guint filenum = 0; + GHashTableIter iter; if (!prj) { return; } - wb_project_clear_idle_queue(&prj->s_idle_add_funcs); - wb_project_clear_idle_queue(&prj->s_idle_remove_funcs); + wb_project_clear_idle_queue(); foreach_slist(elem, prj->directories) { @@ -679,6 +921,37 @@ void wb_project_rescan(WB_PROJECT *prj) { g_slist_foreach(prj->directories, (GFunc)wb_project_dir_regenerate_tags, NULL); } + + /* Create file monitors for directories. */ + if (workbench_get_enable_live_update(wb_globals.opened_wb) == TRUE) + { + WB_MONITOR *monitor; + + monitor = workbench_get_monitor(wb_globals.opened_wb); + foreach_slist(elem, prj->directories) + { + gpointer path, value; + GHashTable *filehash; + gchar *abs_path; + + /* First add monitor for base dir */ + abs_path = get_combined_path(wb_project_get_filename(prj), + wb_project_dir_get_base_dir(elem->data)); + wb_monitor_add_dir(monitor, prj, elem->data, abs_path); + g_free(abs_path); + + /* Now add all dirs in file table */ + filehash = ((WB_PROJECT_DIR *)elem->data)->file_table; + g_hash_table_iter_init(&iter, filehash); + while (g_hash_table_iter_next (&iter, &path, &value)) + { + if (path != NULL && g_file_test(path, G_FILE_TEST_IS_DIR)) + { + wb_monitor_add_dir(monitor, prj, elem->data, path); + } + } + } + } } @@ -732,141 +1005,144 @@ gboolean wb_project_file_is_included(WB_PROJECT *prj, const gchar *filename) } -static gboolean add_tm_idle(gpointer foo) +/* Add single tm file. Only to be called on-idle! */ +static void wb_project_add_single_tm_file(WB_PROJECT *prj, const gchar *filename) { - WB_PROJECT *prj; - GSList *elem2 = NULL; - - prj = (WB_PROJECT *)foo; - if (prj == NULL || prj->s_idle_add_funcs == NULL) - { - return FALSE; - } + GSList *elem = NULL; - foreach_slist (elem2, prj->s_idle_add_funcs) + foreach_slist (elem, prj->directories) { - GSList *elem = NULL; - gchar *utf8_fname = elem2->data; + WB_PROJECT_DIR *dir = elem->data; + TMSourceFile *sf = g_hash_table_lookup(dir->file_table, filename); - foreach_slist (elem, prj->directories) + if (sf != NULL && !document_find_by_filename(filename)) { - WB_PROJECT_DIR *dir = elem->data; - TMSourceFile *sf = g_hash_table_lookup(dir->file_table, utf8_fname); - - if (sf != NULL && !document_find_by_filename(utf8_fname)) - { - tm_workspace_add_source_file(sf); - break; /* single file representation in TM is enough */ - } + tm_workspace_add_source_file(sf); + break; /* single file representation in TM is enough */ } } - - wb_project_clear_idle_queue(&(prj->s_idle_add_funcs)); - - return FALSE; } -/* This function gets called when document is being closed by Geany and we need - * to add the TMSourceFile from the tag manager because Geany removes it on - * document close. +/* This function gets called when document is being opened by Geany and we need + * to remove the TMSourceFile from the tag manager because Geany inserts + * it for the newly open tab. Even though tag manager would handle two identical + * files, the file inserted by the plugin isn't updated automatically in TM + * so any changes wouldn't be reflected in the tags array (e.g. removed function + * from source file would still be found in TM) * - * Additional problem: The tag removal in Geany happens after this function is called. - * To be sure, perform on idle after this happens (even though from my knowledge of TM - * this shouldn't probably matter). */ -void wb_project_add_single_tm_file(WB_PROJECT *prj, const gchar *filename) + * Additional problem: The document being opened may be caused + * by going to tag definition/declaration - tag processing is in progress + * when this function is called and if we remove the TmSourceFile now, line + * number for the searched tag won't be found. For this reason delay the tag + * TmSourceFile removal until idle */ +static void wb_project_remove_single_tm_file(WB_PROJECT *prj, const gchar *filename) { - if (prj == NULL) - { - return; - } + GSList *elem = NULL; - if (prj->s_idle_add_funcs == NULL) + foreach_slist (elem, prj->directories) { - plugin_idle_add(wb_globals.geany_plugin, (GSourceFunc)add_tm_idle, prj); - } + WB_PROJECT_DIR *dir = elem->data; + TMSourceFile *sf = g_hash_table_lookup(dir->file_table, filename); - prj->s_idle_add_funcs = g_slist_prepend(prj->s_idle_add_funcs, g_strdup(filename)); + if (sf != NULL) + { + tm_workspace_remove_source_file(sf); + } + } } -static gboolean remove_tm_idle(gpointer foo) +/* On-idle callback function. */ +static gboolean wb_project_on_idle_callback(gpointer foo) { - WB_PROJECT *prj; - GSList *elem2 = NULL; - - prj = (WB_PROJECT *)foo; - if (prj == NULL || prj->s_idle_remove_funcs == NULL) - { - return FALSE; - } + GSList *elem = NULL; + WB_PROJECT_IDLE_ACTION *action; - foreach_slist (elem2, prj->s_idle_remove_funcs) + foreach_slist (elem, s_idle_actions) { - - GSList *elem = NULL; - gchar *utf8_fname = elem2->data; - - foreach_slist (elem, prj->directories) + action = elem->data; + switch (action->id) { - WB_PROJECT_DIR *dir = elem->data; - TMSourceFile *sf = g_hash_table_lookup(dir->file_table, utf8_fname); + case WB_PROJECT_IDLE_ACTION_ID_ADD_SINGLE_TM_FILE: + if (action->param_a != NULL && action->param_b != NULL) + { + wb_project_add_single_tm_file + (action->param_a, action->param_b); + g_free(action->param_b); + } + break; - if (sf != NULL) - { - tm_workspace_remove_source_file(sf); - } + case WB_PROJECT_IDLE_ACTION_ID_REMOVE_SINGLE_TM_FILE: + if (action->param_a != NULL && action->param_b != NULL) + { + wb_project_remove_single_tm_file + (action->param_a, action->param_b); + g_free(action->param_b); + } + break; + + case WB_PROJECT_IDLE_ACTION_ID_UPDATE_TAGS: + if (action->param_a != NULL) + { + wb_project_dir_update_tags(action->param_a); + } + break; } } - wb_project_clear_idle_queue(&(prj->s_idle_remove_funcs)); + wb_project_clear_idle_queue(); + return FALSE; } -/* This function gets called when document is being opened by Geany and we need - * to remove the TMSourceFile from the tag manager because Geany inserts - * it for the newly open tab. Even though tag manager would handle two identical - * files, the file inserted by the plugin isn't updated automatically in TM - * so any changes wouldn't be reflected in the tags array (e.g. removed function - * from source file would still be found in TM) +/** Add a new idle action to the list. * - * Additional problem: The document being opened may be caused - * by going to tag definition/declaration - tag processing is in progress - * when this function is called and if we remove the TmSourceFile now, line - * number for the searched tag won't be found. For this reason delay the tag - * TmSourceFile removal until idle */ -void wb_project_remove_single_tm_file(WB_PROJECT *prj, const gchar *utf8_filename) + * The function allocates a new WB_PROJECT_IDLE_ACTION structure and fills + * in the values passed. On-idle genay will then call wb_project_on_idle_callback + * and that function will call the function related to the action ID + * and pass the relevant parameters to it. + * + * @param id The action to execute on-idle + * @param param_a Parameter A + * @param param_a Parameter B + * + **/ +void wb_project_add_idle_action(WB_PROJECT_IDLE_ACTION_ID id, gpointer param_a, gpointer param_b) { - if (prj == NULL) - { - return; - } + WB_PROJECT_IDLE_ACTION *action; - if (prj->s_idle_remove_funcs == NULL) + action = g_new0(WB_PROJECT_IDLE_ACTION, 1); + action->id = id; + action->param_a = param_a; + action->param_b = param_b; + + if (s_idle_actions == NULL) { - plugin_idle_add(wb_globals.geany_plugin, (GSourceFunc)remove_tm_idle, prj); + plugin_idle_add(wb_globals.geany_plugin, (GSourceFunc)wb_project_on_idle_callback, NULL); } - prj->s_idle_remove_funcs = g_slist_prepend(prj->s_idle_remove_funcs, g_strdup(utf8_filename)); + + s_idle_actions = g_slist_prepend(s_idle_actions, action); } /* Add a directory to the project */ static WB_PROJECT_DIR *wb_project_add_directory_int(WB_PROJECT *prj, const gchar *dirname, gboolean rescan) { - if (prj != NULL) - { - WB_PROJECT_DIR *new_dir = wb_project_dir_new(dirname); + if (prj != NULL) + { + WB_PROJECT_DIR *new_dir = wb_project_dir_new(prj, dirname); - if (prj->directories != NULL) - { + if (prj->directories != NULL) + { GSList *lst = prj->directories->next; lst = g_slist_prepend(lst, new_dir); lst = g_slist_sort(lst, (GCompareFunc)wb_project_dir_comparator); prj->directories->next = lst; - } - else - { + } + else + { prj->directories = g_slist_append(prj->directories, new_dir); } @@ -875,8 +1151,8 @@ static WB_PROJECT_DIR *wb_project_add_directory_int(WB_PROJECT *prj, const gchar wb_project_rescan(prj); } return new_dir; - } - return NULL; + } + return NULL; } @@ -921,7 +1197,7 @@ gboolean wb_project_remove_directory (WB_PROJECT *prj, WB_PROJECT_DIR *dir) wb_project_rescan(prj); prj->modified = TRUE; } - return FALSE; + return FALSE; } @@ -1498,3 +1774,31 @@ void wb_project_free(WB_PROJECT *prj) g_free(prj->name); g_free(prj); } + + +/** Check if dir is a valid reference to a directory of prj. + * + * @param prj The project to search in + * @param dir The directory to search for + * @return TRUE dir is a directory in prj + * FALSE dir was not found in prj + **/ +gboolean wb_project_is_valid_dir_reference(WB_PROJECT *prj, WB_PROJECT_DIR *dir) +{ + GSList *elem = NULL; + + if (prj == NULL) + { + return FALSE; + } + + foreach_slist(elem, prj->directories) + { + if (elem->data == dir) + { + return TRUE; + } + } + + return FALSE; +} Modified: workbench/src/wb_project.h 14 lines changed, 12 insertions(+), 2 deletions(-) =================================================================== @@ -21,6 +21,13 @@ #include <glib.h> +typedef enum +{ + WB_PROJECT_IDLE_ACTION_ID_ADD_SINGLE_TM_FILE, + WB_PROJECT_IDLE_ACTION_ID_REMOVE_SINGLE_TM_FILE, + WB_PROJECT_IDLE_ACTION_ID_UPDATE_TAGS, +}WB_PROJECT_IDLE_ACTION_ID; + typedef struct S_WB_PROJECT WB_PROJECT; typedef struct S_WB_PROJECT_DIR WB_PROJECT_DIR; @@ -38,8 +45,7 @@ gboolean wb_project_add_directory(WB_PROJECT *prj, const gchar *dirname); gboolean wb_project_remove_directory (WB_PROJECT *prj, WB_PROJECT_DIR *dir); void wb_project_rescan(WB_PROJECT *prj); gboolean wb_project_file_is_included(WB_PROJECT *prj, const gchar *filename); -void wb_project_add_single_tm_file(WB_PROJECT *prj, const gchar *filename); -void wb_project_remove_single_tm_file(WB_PROJECT *prj, const gchar *filename); +gboolean wb_project_is_valid_dir_reference(WB_PROJECT *prj, WB_PROJECT_DIR *dir); void wb_project_dir_set_is_prj_base_dir (WB_PROJECT_DIR *directory, gboolean value); gboolean wb_project_dir_get_is_prj_base_dir (WB_PROJECT_DIR *directory); @@ -55,6 +61,8 @@ gboolean wb_project_dir_set_ignored_file_patterns (WB_PROJECT_DIR *directory, gc guint wb_project_dir_rescan(WB_PROJECT *prj, WB_PROJECT_DIR *root); gchar *wb_project_dir_get_info (WB_PROJECT_DIR *dir); gboolean wb_project_dir_file_is_included(WB_PROJECT_DIR *dir, const gchar *filename); +void wb_project_dir_add_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath); +void wb_project_dir_remove_file(WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar *filepath); gboolean wb_project_add_bookmark(WB_PROJECT *prj, const gchar *filename); gboolean wb_project_remove_bookmark(WB_PROJECT *prj, const gchar *filename); @@ -67,4 +75,6 @@ gboolean wb_project_load(WB_PROJECT *prj, gchar *filename, GError **error); gchar *wb_project_get_info (WB_PROJECT *prj); +void wb_project_add_idle_action(WB_PROJECT_IDLE_ACTION_ID id, gpointer param_a, gpointer param_b); + #endif Modified: workbench/src/workbench.c 224 lines changed, 223 insertions(+), 1 deletions(-) =================================================================== @@ -27,7 +27,9 @@ #include <glib/gstdio.h> #include <geanyplugin.h> #include "workbench.h" +#include "sidebar.h" #include "wb_project.h" +#include "wb_monitor.h" #include "utils.h" typedef struct @@ -45,8 +47,10 @@ struct S_WORKBENCH gchar *name; gboolean modified; gboolean rescan_projects_on_open; + gboolean enable_live_update; GPtrArray *projects; GPtrArray *bookmarks; + WB_MONITOR *monitor; }; /* Create a new, empty workbench project entry */ @@ -81,12 +85,14 @@ WORKBENCH *workbench_new(void) { WORKBENCH *new_wb; - new_wb = g_new(WORKBENCH, 1); + new_wb = g_new0(WORKBENCH, 1); memset(new_wb, 0, sizeof(*new_wb)); new_wb->modified = FALSE; new_wb->rescan_projects_on_open = TRUE; + new_wb->enable_live_update = TRUE; new_wb->projects = g_ptr_array_new(); new_wb->bookmarks = g_ptr_array_new(); + new_wb->monitor = wb_monitor_new(); return new_wb; } @@ -117,6 +123,7 @@ void workbench_free(WORKBENCH *wb) } } + wb_monitor_free(wb->monitor); g_ptr_array_free (wb->projects, TRUE); g_free(wb); } @@ -209,6 +216,42 @@ gboolean workbench_get_rescan_projects_on_open(WORKBENCH *wb) } +/** Set the "Enable live update" option. + * + * @param wb The workbench + * @param value The value to set + * + **/ +void workbench_set_enable_live_update(WORKBENCH *wb, gboolean value) +{ + if (wb != NULL) + { + if (wb->enable_live_update != value) + { + wb->enable_live_update = value; + wb->modified = TRUE; + } + } +} + + +/** Get the "Enable live update" option. + * + * @param wb The workbench + * @return TRUE = use file monitoring for live update of the file list, + * FALSE = don't + * + **/ +gboolean workbench_get_enable_live_update(WORKBENCH *wb) +{ + if (wb != NULL) + { + return wb->enable_live_update; + } + return FALSE; +} + + /** Set the filename. * * @param wb The workbench @@ -256,6 +299,22 @@ const gchar *workbench_get_filename(WORKBENCH *wb) } +/** Get the monitor. + * + * @param wb The workbench + * @return Reference to the WB_MONITOR (can be NULL). + * + **/ +WB_MONITOR *workbench_get_monitor(WORKBENCH *wb) +{ + if (wb != NULL) + { + return wb->monitor; + } + return NULL; +} + + /** Get the name. * * @param wb The workbench @@ -590,6 +649,7 @@ gboolean workbench_save(WORKBENCH *wb, GError **error) g_key_file_set_string(kf, "General", "filetype", "workbench"); g_key_file_set_string(kf, "General", "version", "1.0"); g_key_file_set_boolean(kf, "General", "RescanProjectsOnOpen", wb->rescan_projects_on_open); + g_key_file_set_boolean(kf, "General", "EnableLiveUpdate", wb->enable_live_update); /* Save Workbench bookmarks as string list */ boomarks_size = workbench_get_bookmarks_count(wb); @@ -713,6 +773,16 @@ gboolean workbench_load(WORKBENCH *wb, const gchar *filename, GError **error) } workbench_set_filename(wb, filename); wb->rescan_projects_on_open = g_key_file_get_boolean(kf, "General", "RescanProjectsOnOpen", error); + if (g_key_file_has_key (kf, "General", "EnableLiveUpdate", error)) + { + wb->enable_live_update = g_key_file_get_boolean(kf, "General", "EnableLiveUpdate", error); + } + else + { + /* Not found. Might happen if the workbench was created with an older version of the plugin. + Initialize with TRUE. */ + wb->enable_live_update = TRUE; + } /* Load Workbench bookmarks from string list */ bookmarks_strings = g_key_file_get_string_list (kf, "General", "Bookmarks", NULL, error); @@ -801,3 +871,155 @@ gboolean workbench_load(WORKBENCH *wb, const gchar *filename, GError **error) return success; } + + +/* Check if the given pointers are still valid references. */ +static gboolean workbench_references_are_valid(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT_DIR *dir) +{ + guint index; + WB_PROJECT_ENTRY *entry; + + if (wb == NULL) + { + return FALSE; + } + + /* Try to find the project. */ + for (index = 0 ; index < wb->projects->len ; index++) + { + entry = g_ptr_array_index(wb->projects, index); + if (((WB_PROJECT_ENTRY *)entry)->project == prj) + { + break; + } + } + if (index >= wb->projects->len) + { + return FALSE; + } + + /* Project exists in this workbench, let the project validate + the directory. */ + return wb_project_is_valid_dir_reference(prj, dir); +} + + +/** Process the add file event. + * + * The function processes the add file event. The pointers are checked for + * validity and on success the task is passed on to the project dir. file can + * be the path of a regular file or a directory. + * + * @param wb The workbench + * @param prj The project + * @param dir The directory + * @param file The new file to add to project/directory + * + **/ +void workbench_process_add_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *file) +{ + if (workbench_references_are_valid(wb, prj, dir) == FALSE) + { + /* Should not happen, log a message and return. */ + g_message("%s: invalid references: wb: %p, prj: %p, dir: %p", + G_STRFUNC, wb, prj, dir); + return; + } + + wb_project_dir_add_file(prj, dir, file); +} + + +/** Process the remove file event. + * + * The function processes the remove file event. The pointers are checked for + * validity and on success the task is passed on to the project dir. file can + * be the path of a regular file or a directory. + * + * @param wb The workbench + * @param prj The project + * @param dir The directory + * @param file The file to remove from project/directory + * + **/ +void workbench_process_remove_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *file) +{ + if (workbench_references_are_valid(wb, prj, dir) == FALSE) + { + /* Should not happen, log a message and return. */ + g_message("%s: invalid references: wb: %p, prj: %p, dir: %p", + G_STRFUNC, wb, prj, dir); + return; + } + + wb_project_dir_remove_file(prj, dir, file); +} + + +/* Foreach callback function for creating file monitors. */ +static void workbench_enable_live_update_foreach_cb(SIDEBAR_CONTEXT *context, + gpointer userdata) +{ + gchar *dirpath = NULL; + gchar *abs_path = NULL; + WB_MONITOR *monitor; + + if (context->project != NULL && context->directory != NULL) + { + if (context->subdir != NULL) + { + dirpath = context->subdir; + } + else + { + abs_path = get_combined_path(wb_project_get_filename(context->project), + wb_project_dir_get_base_dir(context->directory)); + dirpath = abs_path; + } + } + + if (dirpath != NULL) + { + monitor = userdata; + wb_monitor_add_dir(monitor, context->project, context->directory, dirpath); + } + + g_free(abs_path); +} + + +/** Enable live update. + * + * The function enables live update of the workbench by creating file + * monitors for all directories in the sidebars file tree. + * + * @param wb The workbench + * + **/ +void workbench_enable_live_update(WORKBENCH *wb) +{ + if (wb != NULL) + { + sidebar_call_foreach(DATA_ID_DIRECTORY, + workbench_enable_live_update_foreach_cb, wb->monitor); + sidebar_call_foreach(DATA_ID_SUB_DIRECTORY, + workbench_enable_live_update_foreach_cb, wb->monitor); + } +} + + +/** Disable live update. + * + * The function disables live update of the workbench by freeing all + * file monitors. + * + * @param wb The workbench + * + **/ +void workbench_disable_live_update(WORKBENCH *wb) +{ + if (wb != NULL) + { + wb_monitor_free(wb->monitor); + } +} Modified: workbench/src/workbench.h 11 lines changed, 11 insertions(+), 0 deletions(-) =================================================================== @@ -21,6 +21,7 @@ #include <glib.h> #include "wb_project.h" +#include "wb_monitor.h" typedef enum { @@ -37,8 +38,12 @@ void workbench_free(WORKBENCH *wb); gboolean workbench_is_empty(WORKBENCH *wb); guint workbench_get_project_count(WORKBENCH *wb); gboolean workbench_is_modified(WORKBENCH *wb); + void workbench_set_rescan_projects_on_open(WORKBENCH *wb, gboolean value); gboolean workbench_get_rescan_projects_on_open(WORKBENCH *wb); +void workbench_set_enable_live_update(WORKBENCH *wb, gboolean value); +gboolean workbench_get_enable_live_update(WORKBENCH *wb); + WB_PROJECT *workbench_get_project_at_index(WORKBENCH *wb, guint index); PROJECT_ENTRY_STATUS workbench_get_project_status_at_index(WORKBENCH *wb, guint index); PROJECT_ENTRY_STATUS workbench_get_project_status_by_address(WORKBENCH *wb, WB_PROJECT *address); @@ -49,6 +54,7 @@ WB_PROJECT *workbench_file_is_included (WORKBENCH *wb, const gchar *filename); void workbench_set_filename(WORKBENCH *wb, const gchar *filename); const gchar *workbench_get_filename(WORKBENCH *wb); gchar *workbench_get_name(WORKBENCH *wb); +WB_MONITOR *workbench_get_monitor(WORKBENCH *wb); gboolean workbench_save(WORKBENCH *wb, GError **error); gboolean workbench_load(WORKBENCH *wb, const gchar *filename, GError **error); @@ -58,4 +64,9 @@ gboolean workbench_remove_bookmark(WORKBENCH *wb, const gchar *filename); gchar *workbench_get_bookmark_at_index (WORKBENCH *wb, guint index); guint workbench_get_bookmarks_count(WORKBENCH *wb); +void workbench_process_add_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *file); +void workbench_process_remove_file_event(WORKBENCH *wb, WB_PROJECT *prj, WB_PROJECT_DIR *dir, const gchar *file); +void workbench_enable_live_update(WORKBENCH *wb); +void workbench_disable_live_update(WORKBENCH *wb); + #endif -------------- This E-Mail was brought to you by github_commit_mail.py (Source:
https://github.com/geany/infrastructure
).
1
0
0
0
[geany/geany-plugins] 18408e: Merge pull request #694 from LarsGit223/utils-ext
by Frank Lanitz
04 Mar '18
04 Mar '18
Branch: refs/heads/master Author: Frank Lanitz <frank(a)frank.uvena.de> Committer: GitHub <noreply(a)github.com> Date: Sun, 04 Mar 2018 06:24:14 UTC Commit: 18408ec176350c15fe7648700bb05e02c7a70260
https://github.com/geany/geany-plugins/commit/18408ec176350c15fe7648700bb05…
Log Message: ----------- Merge pull request #694 from LarsGit223/utils-ext utils: added new function "gp_filelist_filepath_matches_patterns()". Modified Paths: -------------- utils/src/filelist.c utils/src/filelist.h Modified: utils/src/filelist.c 70 lines changed, 70 insertions(+), 0 deletions(-) =================================================================== @@ -290,3 +290,73 @@ GSList *gp_filelist_scan_directory_full(guint *files, guint *folders, const gcha return params.filelist; } + + +/** Check if a filepath matches the given patterns. + * + * If the filepath belongs to a regular file, then TRUE will be returned if + * the filepath matches the patterns in file_patterns but does not match the + * patterns in ignored_file_patterns. + * + * If the filepath belongs to a directory, then TRUE will be returned if it + * does not match the patterns in ignored_dirs_patterns. + * + * @param filepath The file or dorectory path to check + * @param file_patterns + * File patterns for matching files (e.g. "*.c") or NULL + * for all files. + * @param ignored_dirs_patterns + * Patterns for ignored directories + * @param ignored_file_patterns + * Patterns for ignored files + * @return gboolean + * + **/ +gboolean gp_filelist_filepath_matches_patterns(const gchar *filepath, gchar **file_patterns, + gchar **ignored_dirs_patterns, gchar **ignored_file_patterns) +{ + gboolean match = FALSE; + GSList *file_patterns_list; + GSList *ignored_dirs_list; + GSList *ignored_file_list; + + if (!file_patterns || !file_patterns[0]) + { + const gchar *all_pattern[] = { "*", NULL }; + file_patterns_list = filelist_get_precompiled_patterns((gchar **)all_pattern); + } + else + { + file_patterns_list = filelist_get_precompiled_patterns(file_patterns); + } + + ignored_dirs_list = filelist_get_precompiled_patterns(ignored_dirs_patterns); + ignored_file_list = filelist_get_precompiled_patterns(ignored_file_patterns); + + if (g_file_test(filepath, G_FILE_TEST_IS_DIR)) + { + if (!filelist_patterns_match(ignored_dirs_list, filepath)) + { + match = TRUE; + } + } + else if (g_file_test(filepath, G_FILE_TEST_IS_REGULAR)) + { + if (filelist_patterns_match(file_patterns_list, filepath) && + !filelist_patterns_match(ignored_file_list, filepath)) + { + match = TRUE; + } + } + + g_slist_foreach(file_patterns_list, (GFunc) g_pattern_spec_free, NULL); + g_slist_free(file_patterns_list); + + g_slist_foreach(ignored_dirs_list, (GFunc) g_pattern_spec_free, NULL); + g_slist_free(ignored_dirs_list); + + g_slist_foreach(ignored_file_list, (GFunc) g_pattern_spec_free, NULL); + g_slist_free(ignored_file_list); + + return match; +} Modified: utils/src/filelist.h 2 lines changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -32,6 +32,8 @@ GSList *gp_filelist_scan_directory(guint *files, guint *folders, const gchar *se gchar **ignored_dirs_patterns, gchar **ignored_file_patterns); GSList *gp_filelist_scan_directory_full(guint *files, guint *folders, const gchar *searchdir, gchar **file_patterns, gchar **ignored_dirs_patterns, gchar **ignored_file_patterns, guint flags); +gboolean gp_filelist_filepath_matches_patterns(const gchar *filepath, gchar **file_patterns, + gchar **ignored_dirs_patterns, gchar **ignored_file_patterns); G_END_DECLS -------------- This E-Mail was brought to you by github_commit_mail.py (Source:
https://github.com/geany/infrastructure
).
1
0
0
0
← Newer
1
2
3
4
Older →
Jump to page:
1
2
3
4
Results per page:
10
25
50
100
200