[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-user: gschem: Replace recent-file-list by gtk-type



 Hello,

attached is a patch, witch will replace the implemented recent-file-list of gschem by a recent-file-list, which used gtk-default-functions.

Why do I think this patch is useful?
- This patch reduces the code-size of about 200 lines (smaller code, easier to read & debug).
- No external file to store the list
- There is more documentation and examples available for gtk-functions than for own functions

It has some differences to the actual version:
- No 'free recent list' option (is this function really needed?)
- Shows just filename (not full path) as menu-label
- Full file-path available as tooltip
- Shows filetype-icons

Potential drawbacks:
- This patch needs GTK 2.10 or newer. I am not sure, which is the actual minimum gtk-version of gschem

Perhaps, some of you can test this patch and give some feedback (did I introduce some new bugs?). Thank you :-)!

I am also working at a similar patch for pcb, but I have problems to migrate it to the menu in a smooth way. And another problem: As far as I know, pcb's minimum GTK-Version is 2.8. Can anybody tell me, if this is actually true?

Kind regards,
Felix
From a997981178276b3fd932dd2ade685fce5ccb4090 Mon Sep 17 00:00:00 2001
From: Felix Ruoff <Felix@xxxxxxxxxxxxxxxxxx>
Date: Sat, 9 Oct 2010 21:22:14 +0200
Subject: [PATCH] Replace recent-file-list by gtk_recent_manager

This patch replaces the implemented recent-file - list by the recent-manager provided by GTK since version 2.10.
Known differences to previous version:
* No 'free recent list' option
* Shows just filename (not full path) as menu-label
* Full file-path avaiable as tooltip
* Shows filetype-icons
---
 gschem/include/globals.h   |    3 +
 gschem/include/prototype.h |    3 -
 gschem/src/gschem.c        |    5 -
 gschem/src/x_menus.c       |  318 ++++++--------------------------------------
 gschem/src/x_window.c      |    6 +-
 5 files changed, 48 insertions(+), 287 deletions(-)

diff --git a/gschem/include/globals.h b/gschem/include/globals.h
index 8fbeb75..cb1fdb8 100644
--- a/gschem/include/globals.h
+++ b/gschem/include/globals.h
@@ -27,6 +27,9 @@ extern GSCHEM_TOPLEVEL *global_window_current;
 /* window list */
 extern GList *global_window_list;
 
+/* Manager for recently used files */
+GtkRecentManager *recent_manager;
+
 /* colors */
 extern GdkColor white;
 extern GdkColor black;
diff --git a/gschem/include/prototype.h b/gschem/include/prototype.h
index 5948c74..d0439a3 100644
--- a/gschem/include/prototype.h
+++ b/gschem/include/prototype.h
@@ -828,9 +828,6 @@ gint do_popup(GSCHEM_TOPLEVEL *w_current, GdkEventButton *event);
 void x_menus_sensitivity(GSCHEM_TOPLEVEL *w_current, const char *buf, int flag);
 void x_menus_popup_sensitivity(GSCHEM_TOPLEVEL *w_current, const char *buf, int flag);
 void x_menu_attach_recent_files_submenu(GSCHEM_TOPLEVEL *w_current);
-void recent_files_load();
-void recent_files_save(gpointer user_data);
-void recent_files_add(const char *filename);
 /* x_multiattrib.c */
 void x_multiattrib_open (GSCHEM_TOPLEVEL *w_current);
 void x_multiattrib_close (GSCHEM_TOPLEVEL *w_current);
diff --git a/gschem/src/gschem.c b/gschem/src/gschem.c
index b47d503..1b96a12 100644
--- a/gschem/src/gschem.c
+++ b/gschem/src/gschem.c
@@ -259,11 +259,6 @@ void main_prog(void *closure, int argc, char *argv[])
   free (input_str); /* M'allocated by scm_to_locale_string() */
   scm_remember_upto_here_1 (scm_tmp);
 
-  /* Load recent files list. This must be done
-   * before calling x_window_setup(). */
-  recent_files_load();
-  gschem_atexit(recent_files_save, NULL);
-
   /* Set default icon */
   x_window_set_default_icon();
 
diff --git a/gschem/src/x_menus.c b/gschem/src/x_menus.c
index 63fe5a6..8b729f5 100644
--- a/gschem/src/x_menus.c
+++ b/gschem/src/x_menus.c
@@ -26,8 +26,6 @@
 
 #include "gschem.h"
 
-#include <glib/gstdio.h>
-
 #ifdef HAVE_LIBDMALLOC
 #include <dmalloc.h>
 #endif
@@ -359,91 +357,31 @@ void x_menus_popup_sensitivity (GSCHEM_TOPLEVEL *w_current, const char *buf, int
   }
 }
 
-/* The list of recently loaded files. */
-static GList *recent_files = NULL;
 
-#define RECENT_FILES_STORE "gschem-recent-files"
 #define MAX_RECENT_FILES 10
-
-struct recent_file_menu_data {
-  GSCHEM_TOPLEVEL *w_current;
-  gchar *filename;
-};
-
-/*! \brief Make all toplevels reflect changes to the
- *         recent files list.
- */
-static void update_recent_files_menus()
-{
-   GSCHEM_TOPLEVEL *w_current;
-   GtkWidget *submenu, *recent_menu_item;
-   GList *iter;
-
-   for (iter = global_window_list;
-        iter != NULL;
-        iter = g_list_next (iter)) {
-      w_current = (GSCHEM_TOPLEVEL *)iter->data;
-
-      if (w_current->menubar == NULL)
-        continue;
-
-      recent_menu_item =
-        (GtkWidget *) gtk_object_get_data(GTK_OBJECT(w_current->menubar),
-                                          "_File/Open Recen_t");
-      if(recent_menu_item == NULL)
-         return;
-
-      submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(recent_menu_item));
-      gtk_widget_destroy(submenu);
-      x_menu_attach_recent_files_submenu(w_current);
-   }
-}
-
-/*! \brief Remove all entries from the recent files
- *         list and update all toplevels.
+/*! \brief Callback for recent-chooser.
+ * 
+ * Will be proceeded if element of recent-file-list is activated
  */
-static void clear_recent_file_list(gpointer data)
+void
+recent_chooser_item_activated (GtkRecentChooser *chooser, GSCHEM_TOPLEVEL *w_current)
 {
-   GList *p;
+  PAGE *page;
+  gchar *uri;
+  char *filename;
+  GtkRecentInfo *recentInfo;
 
-   p = recent_files;
-   while(p) {
-      g_free(p->data);
-      p = g_list_next(p);
-   }
-   g_list_free(recent_files);
-   recent_files = NULL;
+  uri = gtk_recent_chooser_get_current_uri (chooser);
+  filename = g_filename_from_uri(uri, NULL, NULL);
 
-   update_recent_files_menus();
-}
+  recentInfo = gtk_recent_chooser_get_current_item(chooser);
+  gtk_recent_manager_add_item(recent_manager, uri);
 
-static void
-recent_file_free_menu_data (gpointer data, GClosure *closure) {
-  g_free (data);
-}
+  page = x_window_open_page(w_current, (char *)filename);
+  x_window_set_current_page(w_current, page);
 
-static void recent_file_clicked(GtkMenuItem *menuitem, gpointer user_data)
-{
-   FILE *fp;
-   PAGE *page;
-   struct recent_file_menu_data *data =
-     (struct recent_file_menu_data *) user_data;
-   GSCHEM_TOPLEVEL *w_current = data->w_current;
-   gchar *filename = data->filename;
-
-   /* Check if the file exists */
-   fp = fopen((char *) filename, "r");
-   if(fp == NULL) {
-      /* Remove this entry from all menus */
-      s_log_message(_("Couldn't open file %s\n"), (char *) filename);
-      recent_files = g_list_remove(recent_files, filename);
-      update_recent_files_menus();
-      return;
-   }
-   fclose(fp);
-
-   page = x_window_open_page(w_current, (char *)filename);
-   x_window_set_current_page(w_current, page);
+  gtk_recent_info_unref(recentInfo);
+  g_free(uri);
 }
 
 /*! \brief Attach a submenu with filenames to the 'Open Recent'
@@ -453,203 +391,31 @@ static void recent_file_clicked(GtkMenuItem *menuitem, gpointer user_data)
  */
 void x_menu_attach_recent_files_submenu(GSCHEM_TOPLEVEL *w_current)
 {
-   gulong id;
-   GtkWidget *tmp;
-   GtkWidget *recent_menu_item, *recent_submenu;
-
-   recent_menu_item = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(
-            w_current->menubar), "_File/Open Recen_t");
-   if(recent_menu_item == NULL)
-      return;
-
-   /* disconnect all unblocked signals */
-   while(1) {
-      id = g_signal_handler_find(recent_menu_item, G_SIGNAL_MATCH_UNBLOCKED,
-            0, 0, NULL, NULL, NULL);
-      if(id == 0)
-         break;
-      gtk_signal_disconnect(recent_menu_item, id);
-   }
-
-   recent_submenu = gtk_menu_new();
-   GList *p = recent_files;
-   while(p) {
-     struct recent_file_menu_data *menu_data = g_new0 (struct recent_file_menu_data, 1);
-     menu_data->filename = p->data;
-     menu_data->w_current = w_current;
-     tmp = gtk_menu_item_new_with_label((gchar *)p->data);
-     g_signal_connect_data (GTK_OBJECT(tmp), "activate",
-                            (GCallback) recent_file_clicked,
-                            menu_data,
-                            (GClosureNotify) recent_file_free_menu_data,
-                            0);
-     gtk_menu_append(GTK_MENU(recent_submenu), tmp);
-     p = g_list_next(p);
-   }
-
-   if(recent_files != NULL) {
-      /* Append the 'Clear' menu item to the submenu */
-      GtkWidget *alignment = gtk_alignment_new(0.5, 0, 0, 0);
-
-      tmp = gtk_menu_item_new();
-      gtk_container_add(GTK_CONTAINER(alignment), gtk_label_new(_("Clear")));
-      gtk_container_add(GTK_CONTAINER(tmp), alignment);
-
-      gtk_signal_connect_object(GTK_OBJECT(tmp), "activate",
-            GTK_SIGNAL_FUNC (clear_recent_file_list), NULL);
-
-      gtk_menu_append(GTK_MENU(recent_submenu), gtk_separator_menu_item_new());
-      gtk_menu_append(GTK_MENU(recent_submenu), tmp);
-   }
-
-   gtk_widget_show_all(recent_submenu);
-   gtk_menu_item_set_submenu(GTK_MENU_ITEM(recent_menu_item), recent_submenu);
-}
-
-/*! \brief Add a filename to the list of recent files.
- *
- *  If filename is already in the list, moves it to the head of the
- *  list.
- */
-void recent_files_add(const char *filename)
-{
-   gchar *basename;
-   gchar *save_fn;
-   GError *err = NULL;
-   GList *p = recent_files;
-
-   basename = g_path_get_basename(filename);
-   if(strstr(basename, "untitled_") == basename) {
-      g_free(basename);
-      return;
-   }
-
-   g_free(basename);
-
-   /* Normalize the filename. */
-   save_fn = f_normalize_filename (filename, &err);
-   if (err != NULL) {
-     save_fn = g_strdup (filename);
-     g_error_free (err);
-   }
-
-   /* Check if the file is already in the list.  */
-   while (p != NULL) {
-     if (strcmp (save_fn, (gchar *) p->data) == 0) {
-       break;
-     }
-     p = g_list_next (p);
-   }
-
-   if (p != NULL) {
-     /* Since we found the filename already in the list, move it to
-      * the head of the list. */
-     g_free (save_fn);
-     save_fn = (gchar *) p->data;
-     recent_files = g_list_delete_link (recent_files, p);
-     recent_files = g_list_prepend (recent_files, save_fn);
-   } else {
-     /* Otherwise, just add the new filename to the front of the
-      * list. */
-     recent_files = g_list_prepend (recent_files, save_fn);
-   }
-
-   update_recent_files_menus();
-}
+  GtkWidget* menuitem_to_append_to = NULL;
+  GtkRecentFilter *recent_filter;
+  GtkWidget *menuitem_file_recent_items;
 
-/*! \brief Make RECENT_FILES_STORE contain an empty file list.
- */
-static void recent_files_create_empty()
-{
-   gchar *c;
-   const gchar * const tmp[] = { NULL };
-   GKeyFile *kf = g_key_file_new();
-   gchar *file = g_build_filename(s_path_user_config (), RECENT_FILES_STORE, NULL);
-
-   g_key_file_set_string_list(kf, "Recent files", "Files", tmp, 0);
-   c = g_key_file_to_data(kf, NULL, NULL);
-   g_key_file_free(kf);
-
-   g_file_set_contents(file, c, -1, NULL);
-   g_free(c);
-   g_free(file);
-}
-
-/*! \brief Save the list of recent files to RECENT_FILES_STORE.
- *
- *  \param [in] user_data unused
- */
-void recent_files_save(gpointer user_data)
-{
-   gchar *files[MAX_RECENT_FILES];
-   int num = 0;
-   gchar *c;
-   gchar *file = g_build_filename(s_path_user_config (), RECENT_FILES_STORE, NULL);
-
-   GList *p = recent_files;
-   if(p == NULL) {
-      recent_files_create_empty();
-      return;
-   }
-
-   while((p != NULL) && (num < MAX_RECENT_FILES)) {
-     files[num++] = (gchar *)p->data;
-     p = g_list_next(p);
-   }
-
-   GKeyFile *kf = g_key_file_new();
-
-   g_key_file_set_string_list(kf, "Recent files", "Files", 
-         (const gchar **)files, num);
-   c = g_key_file_to_data(kf, NULL, NULL);
-   g_file_set_contents(file, c, -1, NULL);
-
-   g_free(c);
-   g_free(file);
-   g_key_file_free(kf);
-}
+  recent_manager = gtk_recent_manager_get_default();
+  
+  recent_filter = gtk_recent_filter_new();
+  gtk_recent_filter_add_mime_type(recent_filter, "application/x-geda-schematic");
+  gtk_recent_filter_add_mime_type(recent_filter, "application/x-geda-symbol");
+  
+  menuitem_file_recent_items = gtk_recent_chooser_menu_new_for_manager(recent_manager);
+ 
+  gtk_recent_chooser_add_filter(GTK_RECENT_CHOOSER(menuitem_file_recent_items), recent_filter);
+  gtk_recent_chooser_set_show_tips(GTK_RECENT_CHOOSER(menuitem_file_recent_items), TRUE);
+  gtk_recent_chooser_set_sort_type(GTK_RECENT_CHOOSER(menuitem_file_recent_items),
+                                    GTK_RECENT_SORT_MRU);
+  gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER(menuitem_file_recent_items), MAX_RECENT_FILES);
+  gtk_recent_chooser_set_local_only(GTK_RECENT_CHOOSER(menuitem_file_recent_items), FALSE);
+  gtk_recent_chooser_menu_set_show_numbers(GTK_RECENT_CHOOSER_MENU(menuitem_file_recent_items), TRUE);
+  g_signal_connect(GTK_OBJECT(menuitem_file_recent_items), "item-activated",
+                  G_CALLBACK(recent_chooser_item_activated), w_current); 
+
+  menuitem_to_append_to = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(w_current->menubar), "_File/Open Recen_t");
+  if(menuitem_to_append_to == NULL)
+    return;
 
-/*! \brief Load the recent file list using data from
- *         RECENT_FILES_STORE. 
- *
- *  Must be called before any other recent-files-related
- *  functions.
- */
-void recent_files_load()
-{
-   GKeyFile *kf = g_key_file_new();
-   gchar *file = g_build_filename(s_path_user_config (), RECENT_FILES_STORE, NULL);
-
-   if(!g_file_test(file, G_FILE_TEST_EXISTS)) {
-     g_mkdir(s_path_user_config (), S_IRWXU | S_IRWXG);
-
-      recent_files_create_empty();
-   }
-
-   if(!g_key_file_load_from_file(kf, file, G_KEY_FILE_NONE, NULL)) {
-      /* error opening key file, create an empty one and try again */
-      recent_files_create_empty();
-      if(!g_key_file_load_from_file(kf, file, G_KEY_FILE_NONE, NULL))
-         return;
-   }
-
-   gsize len;
-   gchar **list = g_key_file_get_string_list(kf, "Recent files",
-         "Files", &len, NULL);
-
-   if(list == NULL) {
-      /* error reading key file, don't bother to correct;
-       * just overwrite it with an empty one */
-      recent_files_create_empty();
-      return;
-   }
-
-   while(len > 0) {
-      len--;
-      recent_files = g_list_prepend(recent_files, list[len]);
-   }
-
-   g_free(list);
-   g_free(file);
-   g_key_file_free(kf);
+  gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem_to_append_to), menuitem_file_recent_items);
 }
diff --git a/gschem/src/x_window.c b/gschem/src/x_window.c
index 07beb6e..8e358e7 100644
--- a/gschem/src/x_window.c
+++ b/gschem/src/x_window.c
@@ -743,7 +743,7 @@ x_window_open_page (GSCHEM_TOPLEVEL *w_current, const gchar *filename)
       gtk_widget_destroy (dialog);
       g_error_free (err);
     } else {
-      recent_files_add (fn);
+      gtk_recent_manager_add_item (recent_manager, g_filename_to_uri(fn, NULL, NULL));
     }
   } else {
     if (!quiet_mode)
@@ -873,8 +873,8 @@ x_window_save_page (GSCHEM_TOPLEVEL *w_current, PAGE *page, const gchar *filenam
     /* reset page CHANGED flag */
     page->CHANGED = 0;
 
-    /* update recent file list */
-    recent_files_add(filename);
+    /* add to recent file list */
+    gtk_recent_manager_add_item (recent_manager, g_filename_to_uri(filename, NULL, NULL));
   }
 
   /* log status of operation */
-- 
1.7.1


_______________________________________________
geda-user mailing list
geda-user@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-user