[geany/geany-plugins] f03977: workbench: added new feature "Search projects"

LarsGit223 git-noreply at xxxxx
Thu Jul 11 17:42:55 UTC 2019


Branch:      refs/heads/master
Author:      LarsGit223 <lars_paulsen at web.de>
Committer:   LarsGit223 <lars_paulsen at web.de>
Date:        Wed, 12 Jun 2019 13:56:16 UTC
Commit:      f03977145f79269571a7480b664e4188cb5082ca
             https://github.com/geany/geany-plugins/commit/f03977145f79269571a7480b664e4188cb5082ca

Log Message:
-----------
workbench: added new feature "Search projects"

The feature lets the user search for projects to add them to the Workbench.
After selecting the menu item, the user can select a directory to search through.
The directory and it's sub-directories are scanned for project files (".geany").
All found files are listed and after scanning is done the user can select the
projects which shall be added to the Workbench.

The dialog is not modal - the user can do other work during the scanning of the
directory.


Modified Paths:
--------------
    po/POTFILES.in
    workbench/README
    workbench/src/Makefile.am
    workbench/src/menu.c
    workbench/src/menu.h
    workbench/src/plugin_main.c
    workbench/src/search_projects.c
    workbench/src/search_projects.h
    workbench/src/sidebar.c
    workbench/src/workbench.c

Modified: po/POTFILES.in
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -321,6 +321,7 @@ workbench/src/dialogs.c
 workbench/src/menu.c
 workbench/src/plugin_main.c
 workbench/src/popup_menu.c
+workbench/src/search_projects.c
 workbench/src/sidebar.c
 workbench/src/utils.c
 workbench/src/wb_globals.c


Modified: workbench/README
6 lines changed, 6 insertions(+), 0 deletions(-)
===================================================================
@@ -39,6 +39,12 @@ menu:
   Open the Workbench settings dialog. After the settings have been
   confirmed with "OK" they will be written back to the workbench file
   (if any value was changed).
+**Item "Search projects"**
+  Search for projects to add them to the Workbench. This lets the user
+  select a directory to search through. The directory and it's sub-directories
+  are scanned for project files (".geany"). All found files are listed and
+  after scanning is done the user can select the projects which shall be
+  added to the Workbench.
 **Item "Close"**
   Closes the opened Workbench.
 


Modified: workbench/src/Makefile.am
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -15,6 +15,8 @@ workbench_la_SOURCES = \
 	wb_monitor.c \
 	dialogs.h \
 	dialogs.c \
+	search_projects.h \
+	search_projects.c \
 	menu.h \
 	menu.c \
 	popup_menu.h \


Modified: workbench/src/menu.c
29 lines changed, 29 insertions(+), 0 deletions(-)
===================================================================
@@ -27,6 +27,7 @@
 #include "dialogs.h"
 #include "menu.h"
 #include "sidebar.h"
+#include "search_projects.h"
 
 extern GeanyPlugin *geany_plugin;
 
@@ -37,6 +38,7 @@ typedef struct
 	GtkWidget *item_new;
 	GtkWidget *item_open;
 	GtkWidget *item_settings;
+	GtkWidget *item_search_projects;
 	GtkWidget *item_close;
 }WB_MENU_DATA;
 static WB_MENU_DATA menu_data;
@@ -58,12 +60,21 @@ void menu_set_context(MENU_CONTEXT context)
 			gtk_widget_set_sensitive(menu_data.item_new, FALSE);
 			gtk_widget_set_sensitive(menu_data.item_open, FALSE);
 			gtk_widget_set_sensitive(menu_data.item_settings, TRUE);
+			gtk_widget_set_sensitive(menu_data.item_search_projects, TRUE);
 			gtk_widget_set_sensitive(menu_data.item_close, TRUE);
 		break;
+		case MENU_CONTEXT_SEARCH_PROJECTS_SCANING:
+			gtk_widget_set_sensitive(menu_data.item_new, FALSE);
+			gtk_widget_set_sensitive(menu_data.item_open, FALSE);
+			gtk_widget_set_sensitive(menu_data.item_settings, TRUE);
+			gtk_widget_set_sensitive(menu_data.item_search_projects, FALSE);
+			gtk_widget_set_sensitive(menu_data.item_close, FALSE);
+		break;
 		case MENU_CONTEXT_WB_CLOSED:
 			gtk_widget_set_sensitive(menu_data.item_new, TRUE);
 			gtk_widget_set_sensitive(menu_data.item_open, TRUE);
 			gtk_widget_set_sensitive(menu_data.item_settings, FALSE);
+			gtk_widget_set_sensitive(menu_data.item_search_projects, FALSE);
 			gtk_widget_set_sensitive(menu_data.item_close, FALSE);
 		break;
 	}
@@ -164,6 +175,17 @@ static void item_workbench_settings_activate_cb(G_GNUC_UNUSED GtkMenuItem *menui
 }
 
 
+/* The function handles the menu item "Search projects" */
+static void item_workbench_search_projects_activate_cb(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer user_data)
+{
+	if (wb_globals.opened_wb != NULL)
+	{
+		search_projects(wb_globals.opened_wb);
+	}
+	sidebar_update(SIDEBAR_CONTEXT_PROJECT_ADDED, NULL);
+}
+
+
 /* The function handles the menu item "Close workbench" */
 static void item_close_workbench_activate_cb(G_GNUC_UNUSED GtkMenuItem *menuitem, G_GNUC_UNUSED gpointer user_data)
 {
@@ -206,6 +228,13 @@ gboolean menu_init(void)
 	g_signal_connect(menu_data.item_settings, "activate",
 					 G_CALLBACK(item_workbench_settings_activate_cb), NULL);
 
+	/* Create new menu item "Search Projects" */
+	menu_data.item_search_projects = gtk_menu_item_new_with_mnemonic(_("Search _projects"));
+	gtk_widget_show(menu_data.item_search_projects);
+	gtk_menu_shell_append(GTK_MENU_SHELL (menu_data.menu), menu_data.item_search_projects);
+	g_signal_connect(menu_data.item_search_projects, "activate",
+					 G_CALLBACK(item_workbench_search_projects_activate_cb), NULL);
+
 	/* Create new menu item "Close Workbench" */
 	menu_data.item_close = gtk_menu_item_new_with_mnemonic(_("_Close"));
 	gtk_widget_show(menu_data.item_close);


Modified: workbench/src/menu.h
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -24,6 +24,7 @@ typedef enum
 	MENU_CONTEXT_WB_CREATED,
 	MENU_CONTEXT_WB_OPENED,
 	MENU_CONTEXT_WB_CLOSED,
+	MENU_CONTEXT_SEARCH_PROJECTS_SCANING,
 }MENU_CONTEXT;
 
 void menu_set_context(MENU_CONTEXT context);


Modified: workbench/src/plugin_main.c
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -117,7 +117,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.07";
+	plugin->info->version = "1.08";
 	plugin->info->author = "LarsGit223";
 
 	/* Set functions */


Modified: workbench/src/search_projects.c
537 lines changed, 537 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,537 @@
+/*
+ * Copyright 2017 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.
+ */
+
+/*
+ * This file contains all the code for handling the "Search projects"
+ * menu item/action.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "wb_globals.h"
+#include "dialogs.h"
+#include "sidebar.h"
+#include "menu.h"
+
+
+typedef enum
+{
+	SCAN_DIR_STATE_ENTER,
+	SCAN_DIR_STATE_CONTINUE,
+}SCAN_DIR_STATE;
+
+
+enum
+{
+	SEARCH_PROJECTS_COLUMN_IMPORT,
+	SEARCH_PROJECTS_COLUMN_PATH,
+	SEARCH_PROJECTS_N_COLUMNS,
+};
+
+
+typedef struct
+{
+	gchar *path;
+	gchar *locale_path;
+	gchar *real_path;
+	GDir *dir;
+}SCAN_DIR_STATE_DATA;
+
+
+typedef struct
+{
+	SCAN_DIR_STATE state;
+	gchar *searchdir;
+	glong prj_count;
+	GHashTable *visited_paths;
+	GPtrArray *data;
+}SCAN_DIR_PARAMS;
+
+
+typedef struct S_SEARCH_PROJECTS_DIALOG
+{
+	gboolean stopped;
+	GtkWidget *dialog;
+	GtkWidget *vbox;
+	GtkWidget *label;
+	GtkWidget *label_dir;
+	GtkWidget *list_vbox;
+	GtkWidget *list_view;
+	GtkListStore *list_store;
+	SCAN_DIR_PARAMS *params;
+}SEARCH_PROJECTS_DIALOG;
+
+
+/** Shows the dialog "Select search directory".
+ *
+ * The dialog lets the user choose an existing folder.
+ *
+ * @return The filename
+ *
+ **/
+static gchar *dialogs_select_search_directory(void)
+{
+	gchar *filename = NULL;
+	GtkWidget *dialog;
+
+	dialog = gtk_file_chooser_dialog_new(_("Select search directory"),
+		GTK_WINDOW(wb_globals.geany_plugin->geany_data->main_widgets->window), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+		_("_Cancel"), GTK_RESPONSE_CANCEL,
+		_("_Add"), GTK_RESPONSE_ACCEPT, NULL);
+
+	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
+	{
+		filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+	}
+
+	gtk_widget_destroy(dialog);
+
+	return filename;
+}
+
+
+/* Free data used during searching.
+   Freeing the widgets is done by gtk through calling 'destroy()'. */
+static void search_projects_free_data(SEARCH_PROJECTS_DIALOG *data)
+{
+	if (data->params != NULL)
+	{
+		g_free(data->params->searchdir);
+		g_hash_table_destroy(data->params->visited_paths);
+		g_ptr_array_free(data->params->data, FALSE);
+		g_free(data->params);
+		data->params = NULL;
+	}
+
+	g_free(data);
+}
+
+
+/* Callback function for clicking on a list item */
+static void list_view_on_row_activated (GtkTreeView *treeview,
+	GtkTreePath *path, G_GNUC_UNUSED GtkTreeViewColumn *col, G_GNUC_UNUSED gpointer userdata)
+{
+	gboolean value;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	SEARCH_PROJECTS_DIALOG *data = userdata;
+
+	model = gtk_tree_view_get_model(treeview);
+
+	if (gtk_tree_model_get_iter(model, &iter, path))
+	{
+		gtk_tree_model_get(model, &iter, SEARCH_PROJECTS_COLUMN_IMPORT, &value, -1);
+		gtk_list_store_set(data->list_store, &iter,
+			SEARCH_PROJECTS_COLUMN_IMPORT, !value,
+			-1);
+	}
+}
+
+static void search_projects_shutdown(SEARCH_PROJECTS_DIALOG *data)
+{
+	/* Close and free dialog. */
+	gtk_widget_destroy(GTK_WIDGET(data->dialog));
+
+	menu_set_context(MENU_CONTEXT_WB_OPENED);
+
+	/* Free data. */
+	search_projects_free_data(data);
+}
+
+
+/* Handle "OK" and "Cancel" button. */
+static void dialog_on_button_pressed(GtkDialog *dialog, gint response_id,
+									 gpointer user_data)
+{
+	gboolean value;
+	gchar *filename;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	GError *error = NULL;
+	SEARCH_PROJECTS_DIALOG *data = user_data;
+
+	if (response_id == GTK_RESPONSE_ACCEPT)
+	{
+		model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->list_view));
+		if (gtk_tree_model_get_iter_first(model, &iter))
+		{
+			do
+			{
+				gtk_tree_model_get(model, &iter, SEARCH_PROJECTS_COLUMN_IMPORT, &value, -1);
+				if (value == TRUE)
+				{
+					gtk_tree_model_get(model, &iter, SEARCH_PROJECTS_COLUMN_PATH, &filename, -1);
+					workbench_add_project(wb_globals.opened_wb, filename);
+				}
+			}while (gtk_tree_model_iter_next(model, &iter));
+		}
+
+		/* Save the workbench file (.geanywb). */
+		if (!workbench_save(wb_globals.opened_wb, &error))
+		{
+			dialogs_show_msgbox(GTK_MESSAGE_INFO, _("Could not save workbench file: %s"), error->message);
+		}
+		sidebar_update(SIDEBAR_CONTEXT_PROJECT_ADDED, NULL);
+	}
+
+
+	if (response_id == GTK_RESPONSE_ACCEPT ||
+		response_id == GTK_RESPONSE_CANCEL ||
+		data->stopped == TRUE)
+	{
+		search_projects_shutdown(data);
+	}
+	else
+	{
+		/* Set stop marker (scanning might still be in progress). */
+		data->stopped = TRUE;
+	}
+}
+
+
+/* Push scan data on the stack. */
+static void scan_dir_data_push(SCAN_DIR_PARAMS *params, gchar *path, 
+	gchar *locale_path, gchar *real_path, GDir *dir)
+{
+	SCAN_DIR_STATE_DATA *state_data;
+
+	state_data = g_new0(SCAN_DIR_STATE_DATA, 1);
+	state_data->path = path;
+	state_data->locale_path = locale_path;
+	state_data->real_path = real_path;
+	state_data->dir = dir;
+
+	g_ptr_array_add(params->data, state_data);
+}
+
+
+/* Pop scan data from the stack. */
+static void scan_dir_data_pop(SCAN_DIR_PARAMS *params)
+{
+	SCAN_DIR_STATE_DATA *state_data;
+
+	if (params->data->len > 0)
+	{
+		state_data = params->data->pdata[params->data->len - 1];
+		g_free(state_data->path);
+		g_free(state_data->locale_path);
+		g_free(state_data->real_path);
+
+		g_ptr_array_remove_index(params->data, params->data->len - 1);
+	}
+}
+
+
+/* The function needs to be called if scanning comes to an end (scanning
+   done or an error occurred. */
+static void search_projects_scan_directory_end (SEARCH_PROJECTS_DIALOG *data)
+{
+	gchar *text;
+
+	if (data->stopped == FALSE)
+	{
+		text = g_strdup_printf(_("Found %lu project files in directory \"%s\".\nPlease select the projects to add to the workbench."),
+			data->params->prj_count, data->params->searchdir);
+		gtk_label_set_text((GtkLabel *)data->label, text);
+		g_free(text);
+
+		gtk_widget_destroy(data->label_dir);
+		gtk_widget_set_sensitive(data->dialog, TRUE);
+
+		data->stopped = TRUE;
+	}
+	else
+	{
+		/* Dialog has been deleted as timer was running. */
+		search_projects_shutdown(data);
+	}
+}
+
+
+/* Start/continue scanning of the directory. This is a timer callback
+   function to enable working with geany during long scans instead of
+   blocking everything. */
+static gboolean search_projects_scan_directory_do_work (gpointer user_data)
+{
+	SEARCH_PROJECTS_DIALOG *data = user_data;
+	SCAN_DIR_STATE_DATA *state_data;
+	gchar *text;
+	guint repeats = 0;
+
+	if (data->stopped == TRUE ||
+		data->params->data->len == 0)
+	{
+		/* Abort. */
+		search_projects_scan_directory_end(data);
+		return FALSE;
+	}
+
+	while (repeats < 50)
+	{
+		const gchar *locale_name;
+		gchar *locale_filename, *utf8_filename, *utf8_name;
+		GtkTreeIter iter;
+
+		if (data->stopped == TRUE)
+		{
+			/* Abort. */
+			search_projects_scan_directory_end(data);
+			return FALSE;
+		}
+
+		repeats++;
+		state_data = data->params->data->pdata[data->params->data->len - 1];
+
+		if (data->params->state == SCAN_DIR_STATE_ENTER)
+		{
+			/* Data must already be on the stack. */
+
+			/* Add missing state data. */
+			state_data->locale_path = utils_get_locale_from_utf8(state_data->path);
+			state_data->real_path = utils_get_real_path(state_data->locale_path);
+
+			if (state_data->real_path &&
+				g_hash_table_lookup(data->params->visited_paths, state_data->real_path))
+			{
+				/* Seen this already. Leave dir. */
+				scan_dir_data_pop(data->params);
+				data->params->state = SCAN_DIR_STATE_CONTINUE;
+				return TRUE;
+			}
+
+			state_data->dir = g_dir_open(state_data->locale_path, 0, NULL);
+			if (!state_data->dir || !state_data->real_path)
+			{
+				if (state_data->dir != NULL)
+				{
+					g_dir_close(state_data->dir);
+				}
+
+				/* Abort on error. */
+				search_projects_scan_directory_end(data);
+				return FALSE;
+			}
+
+			g_hash_table_insert(data->params->visited_paths, g_strdup(state_data->real_path), GINT_TO_POINTER(1));
+
+			text = g_strdup_printf("%s", state_data->locale_path);
+			gtk_label_set_text((GtkLabel *)data->label_dir, text);
+			g_free(text);
+		}
+
+
+		if (data->params->data->len == 0)
+		{
+			/* Internal error. Abort. */
+			search_projects_scan_directory_end(data);
+			return FALSE;
+		}
+		data->params->state = SCAN_DIR_STATE_CONTINUE;
+		state_data = data->params->data->pdata[data->params->data->len - 1];
+
+		/* Get next directory entry. */
+		locale_name = g_dir_read_name(state_data->dir);
+		if (!locale_name)
+		{
+			g_dir_close(state_data->dir);
+			scan_dir_data_pop(data->params);
+			break;
+		}
+
+		utf8_name = utils_get_utf8_from_locale(locale_name);
+		locale_filename = g_build_filename(state_data->locale_path, locale_name, NULL);
+		utf8_filename = utils_get_utf8_from_locale(locale_filename);
+
+		if (g_file_test(locale_filename, G_FILE_TEST_IS_DIR))
+		{
+			scan_dir_data_push(data->params, g_strdup(locale_filename), NULL, NULL, NULL);
+			data->params->state = SCAN_DIR_STATE_ENTER;
+		}
+		else if (g_file_test(locale_filename, G_FILE_TEST_IS_REGULAR))
+		{
+			if (g_str_has_suffix(utf8_name, ".geany"))
+			{
+				data->params->prj_count++;
+				gtk_list_store_append (data->list_store, &iter);
+				gtk_list_store_set (data->list_store, &iter,
+					SEARCH_PROJECTS_COLUMN_PATH, locale_filename,
+					SEARCH_PROJECTS_COLUMN_IMPORT, FALSE,
+					-1);
+			}
+		}
+
+		g_free(utf8_filename);
+		g_free(locale_filename);
+		g_free(utf8_name);
+	}
+
+	if (data->params->data->len == 0)
+	{
+		/* Finished. */
+		search_projects_scan_directory_end(data);
+		return FALSE;
+	}
+
+	/* Continue. */
+	return TRUE;
+}
+
+
+/* The function prepares the required data for scaning and starts a timer
+   for calling 'search_projects_scan_directory_do_work()' periodically
+   until work is done. */
+static void search_projects_scan_directory_start (const gchar *searchdir, SEARCH_PROJECTS_DIALOG *data)
+{
+	SCAN_DIR_PARAMS *params;
+
+	params = g_new0(SCAN_DIR_PARAMS, 1);
+
+	params->state = SCAN_DIR_STATE_ENTER;
+	params->searchdir = g_strdup(searchdir);
+	params->prj_count = 0;
+	params->visited_paths = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+	params->data = g_ptr_array_new();
+
+	scan_dir_data_push(params, g_strdup(searchdir), NULL, NULL, NULL);
+	data->params = params;
+
+	menu_set_context(MENU_CONTEXT_SEARCH_PROJECTS_SCANING);
+	plugin_timeout_add(wb_globals.geany_plugin, 1, search_projects_scan_directory_do_work, data);
+}
+
+
+/** Search for projects.
+ * 
+ * Search for projects to be added to the workbench. First the function
+ * 'dialogs_select_search_directory()' is called to open the dialog
+ * "Select search directory". Scanning then started by calling
+ * 'search_projects_scan_directory_start()'. The dialog shows a list
+ * of found project files ("*.geany") and is held insenstive until search
+ * has finished. Then the user can check the projects we likes to add.
+ * Clicking "OK" then makes the projects being added to the workbench.
+ * Clicking "Cancel" or closing the dialog aborts everything and the
+ * workbench is un-changed.
+ *
+ * @param wb The workbench to add the found/selected projects to.
+ *
+ **/
+void search_projects(WORKBENCH *wb)
+{
+	gchar *directory;
+	GtkWidget *content_area;
+	GtkDialogFlags flags;
+	GtkWidget *scrollwin;
+	GtkCellRenderer *renderer;
+	GtkTreeViewColumn *column;
+	GtkTreeSelection *sel;
+	GList *focus_chain = NULL;
+	SEARCH_PROJECTS_DIALOG *search_projects;
+
+	/* First, the user needs to select a directory to scan. */
+	directory = dialogs_select_search_directory();
+	if (directory == NULL)
+	{
+		return;
+	}
+
+	search_projects = g_new0(SEARCH_PROJECTS_DIALOG, 1);
+
+	/* Create the widgets */
+	flags = GTK_DIALOG_DESTROY_WITH_PARENT;
+	search_projects->dialog = gtk_dialog_new_with_buttons(_("Search projects"),
+		GTK_WINDOW(wb_globals.geany_plugin->geany_data->main_widgets->window),
+		flags,
+		_("_Cancel"), GTK_RESPONSE_CANCEL,
+		_("_OK"), GTK_RESPONSE_ACCEPT,
+		NULL);
+	g_signal_connect(search_projects->dialog, "response", G_CALLBACK(dialog_on_button_pressed), search_projects);
+	content_area = gtk_dialog_get_content_area(GTK_DIALOG (search_projects->dialog));
+	gtk_widget_set_sensitive(search_projects->dialog, FALSE);
+
+	/* VBox for the list view */
+	search_projects->vbox = gtk_vbox_new(FALSE, 0);
+	gtk_container_set_border_width(GTK_CONTAINER(search_projects->vbox), 12);
+
+
+	/* List view */
+	search_projects->list_view = gtk_tree_view_new();
+	g_signal_connect(search_projects->list_view, "row-activated", (GCallback)list_view_on_row_activated, search_projects);
+
+	search_projects->list_store = gtk_list_store_new(SEARCH_PROJECTS_N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING);
+	gtk_tree_view_set_model(GTK_TREE_VIEW(search_projects->list_view), GTK_TREE_MODEL(search_projects->list_store));
+
+	column = gtk_tree_view_column_new();
+	gtk_tree_view_column_set_spacing(column, 10);
+	gtk_tree_view_column_set_resizable(column, FALSE);
+	gtk_tree_view_column_set_title(column, _("Add to workbench?"));
+	renderer = gtk_cell_renderer_toggle_new();
+	gtk_tree_view_column_pack_start(column, renderer, FALSE);
+	gtk_tree_view_column_add_attribute(column, renderer, "active", SEARCH_PROJECTS_COLUMN_IMPORT);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(search_projects->list_view), column);
+
+	column = gtk_tree_view_column_new();
+	gtk_tree_view_column_set_spacing(column, 10);
+	gtk_tree_view_column_set_resizable (column, TRUE);
+	gtk_tree_view_column_set_title(column, _("Project path"));
+	renderer = gtk_cell_renderer_text_new();
+	gtk_tree_view_column_pack_start(column, renderer, TRUE);
+	gtk_tree_view_column_add_attribute(column, renderer, "text", SEARCH_PROJECTS_COLUMN_PATH);
+	gtk_tree_view_append_column(GTK_TREE_VIEW(search_projects->list_view), column);
+
+	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(search_projects->list_view), TRUE);
+	gtk_tree_view_set_enable_search(GTK_TREE_VIEW(search_projects->list_view), FALSE);
+
+	ui_widget_modify_font_from_string(search_projects->list_view,
+		wb_globals.geany_plugin->geany_data->interface_prefs->tagbar_font);
+
+	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(search_projects->list_view));
+	gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
+
+	/*Add label to vbox */
+	search_projects->label = gtk_label_new (_("Scanning directory:"));
+	gtk_box_pack_start(GTK_BOX(search_projects->vbox), search_projects->label, FALSE, FALSE, 6);
+
+	/*Add label for current directory to vbox */
+	search_projects->label_dir = gtk_label_new (NULL);
+	gtk_box_pack_start(GTK_BOX(search_projects->vbox), search_projects->label_dir, FALSE, FALSE, 6);
+
+	/*Add list view to vbox */
+	focus_chain = g_list_prepend(focus_chain, search_projects->list_view);
+	gtk_container_set_focus_chain(GTK_CONTAINER(search_projects->vbox), focus_chain);
+	g_list_free(focus_chain);
+	scrollwin = gtk_scrolled_window_new(NULL, NULL);
+	gtk_widget_set_size_request(scrollwin, 400, 200);
+#if GTK_CHECK_VERSION(3, 0, 0)
+	gtk_widget_set_vexpand(scrollwin, TRUE);
+#endif
+	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
+		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_container_add(GTK_CONTAINER(scrollwin), search_projects->list_view);
+	gtk_box_pack_start(GTK_BOX(search_projects->vbox), scrollwin, TRUE, TRUE, 0);
+
+	gtk_widget_show_all(search_projects->vbox);
+
+	gtk_container_add(GTK_CONTAINER (content_area), search_projects->vbox);
+	gtk_widget_show_all(search_projects->dialog);
+
+	search_projects_scan_directory_start(directory, search_projects);
+	g_free(directory);
+
+	return;
+}


Modified: workbench/src/search_projects.h
24 lines changed, 24 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2019 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_SEARCH_PROJECTS_H__
+#define __WB_SEARCH_PROJECTS_H__
+
+void search_projects(WORKBENCH *wb);
+
+#endif


Modified: workbench/src/sidebar.c
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -883,7 +883,8 @@ static void sidebar_update_workbench(GtkTreeIter *iter, gint *position)
 		if (count == 0)
 		{
 			gtk_tree_store_clear(sidebar.file_store);
-			sidebar_show_intro_message(_("Add a project\nusing the context menu."), TRUE);
+			sidebar_show_intro_message(_("Add a project using the context menu\n"
+				"or select \"Search projects\" from the menu."), TRUE);
 		}
 		else
 		{


Modified: workbench/src/workbench.c
6 lines changed, 6 insertions(+), 0 deletions(-)
===================================================================
@@ -534,6 +534,12 @@ gboolean workbench_add_project(WORKBENCH *wb, const gchar *filename)
 		/* Load project to import base path. */
 		wb_project_load(project, filename, NULL);
 
+		/* Start immediate scan if enabled. */
+		if (wb->rescan_projects_on_open == TRUE)
+		{
+			wb_project_rescan(project);
+		}
+
 		wb->modified = TRUE;
 		return TRUE;
 	}



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


More information about the Plugins-Commits mailing list