[Xfce4-commits] <mousepad:master> * TODO, mousepad/mousepad-window.c: Add option to the recent menu to clear the history. * mousepad/mousepad-window.c: The recent items are now in the Mousepad group so it's easier to filter them when removing. The list is also sorted by the most recently used item. * mousepad/mousepad-window.c: Fix problem in checking if the file was already openened. * mousepad/mousepad-window.c: You can now reorder tabs. * mousepad/mousepad-window.c: A tab is now inserted right from the current active tab. * mousepad/mousepad-screen.c: Untitled documents now have a number like "Untitled #". The number is increased as long as the application is running. * mousepad/mousepad-window.c: Added first parts of code for a statusbar.

Nick Schermer noreply at xfce.org
Sat May 5 21:30:05 CEST 2012


Updating branch refs/heads/master
         to f0dc6b97b9512e8121ad3b253562d13f5baca205 (commit)
       from ff28ae1045a381c7dc815906b9a0816b87451e2b (commit)

commit f0dc6b97b9512e8121ad3b253562d13f5baca205
Author: Nick Schermer <nick at xfce.org>
Date:   Wed Feb 28 18:14:25 2007 +0000

    	* TODO, mousepad/mousepad-window.c: Add option to the recent menu
    	  to clear the history.
    	* mousepad/mousepad-window.c: The recent items are now in the Mousepad
    	  group so it's easier to filter them when removing. The list is also
    	  sorted by the most recently used item.
    	* mousepad/mousepad-window.c: Fix problem in checking if the
    	  file was already openened.
    	* mousepad/mousepad-window.c: You can now reorder tabs.
    	* mousepad/mousepad-window.c: A tab is now inserted right from the
    	  current active tab.
    	* mousepad/mousepad-screen.c: Untitled documents now have a number like
    	  "Untitled #". The number is increased as long as the application is running.
    	* mousepad/mousepad-window.c: Added first parts of code for a statusbar.
    
    (Old svn revision: 25043)

 ChangeLog                       |   16 ++
 TODO                            |    3 -
 configure.in.in                 |    2 +-
 mousepad/main.c                 |    1 -
 mousepad/mousepad-preferences.c |    9 +
 mousepad/mousepad-screen.c      |    7 +-
 mousepad/mousepad-window-ui.xml |   11 +-
 mousepad/mousepad-window.c      |  493 ++++++++++++++++++++++++++++++++-------
 8 files changed, 447 insertions(+), 95 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 641b7e6..d9d84a6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2007-02-18	Nick Schermer <nick at xfce.org>
+
+	* TODO, mousepad/mousepad-window.c: Add option to the recent menu
+	  to clear the history.
+	* mousepad/mousepad-window.c: The recent items are now in the Mousepad
+	  group so it's easier to filter them when removing. The list is also
+	  sorted by the most recently used item.
+	* mousepad/mousepad-window.c: Fix problem in checking if the
+	  file was already openened.
+	* mousepad/mousepad-window.c: You can now reorder tabs.
+	* mousepad/mousepad-window.c: A tab is now inserted right from the
+	  current active tab.
+	* mousepad/mousepad-screen.c: Untitled documents now have a number like
+	  "Untitled #". The number is increased as long as the application is running.
+	* mousepad/mousepad-window.c: Added first parts of code for a statusbar.
+
 2007-02-17	Nick Schermer <nick at xfce.org>
 
 	* TODO: Remind myself to fix problems with UTF-8 filenames.
diff --git a/TODO b/TODO
index 1e0ed03..6cb57fe 100644
--- a/TODO
+++ b/TODO
@@ -1,10 +1,7 @@
 - Interface
   - Dialog when closing multiple (modified) tabs.
-  - Statusbar (not a priority).
   - Right-click menu for the tab label.
-  - Change tabs position.
   - Tab font color when the file is modified or readonly.
-  - Clear the recent history.
 
 - Text View
   - Search and Replace. Maybe also text highlighting.
diff --git a/configure.in.in b/configure.in.in
index 6cbd2a5..dbf3aba 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -24,7 +24,7 @@ dnl *** Initialize autoconf ***
 dnl ***************************
 AC_COPYRIGHT([Copyright (c) 2007
         The Xfce development team. All rights reserved.])
-AC_INIT([Mousepad], [mousepad_version()], [http://bugzilla.xfce.org/], [Mousepad])
+AC_INIT([Mousepad], [mousepad_version()], [http://bugzilla.xfce.org/], [mousepad])
 AC_PREREQ([2.50])
 AC_CANONICAL_TARGET()
 AC_REVISION([$Id$])
diff --git a/mousepad/main.c b/mousepad/main.c
index 88045b7..d7102d8 100644
--- a/mousepad/main.c
+++ b/mousepad/main.c
@@ -108,7 +108,6 @@ main (gint argc, gchar **argv)
       g_print ("%s %s (Xfce %s)\n\n", PACKAGE_NAME, PACKAGE_VERSION, xfce_version_string ());
       g_print ("%s\n", "Copyright (c) 2007");
       g_print ("\t%s\n\n", _("The Xfce development team. All rights reserved."));
-      g_print ("%s\n\n", _("Written by Nick Schermer <nick at xfce.org>."));
       g_print (_("Please report bugs to <%s>."), PACKAGE_BUGREPORT);
       g_print ("\n");
 
diff --git a/mousepad/mousepad-preferences.c b/mousepad/mousepad-preferences.c
index 4a3f1d1..c3707c6 100644
--- a/mousepad/mousepad-preferences.c
+++ b/mousepad/mousepad-preferences.c
@@ -53,6 +53,7 @@ enum
   PROP_LAST_WINDOW_HEIGHT,
   PROP_LAST_WINDOW_WIDTH,
   PROP_LINE_NUMBERS,
+  PROP_STATUSBAR,
   PROP_WORD_WRAP,
   PROP_MISC_ALWAYS_SHOW_TABS,
   PROP_MISC_CYCLE_TABS,
@@ -204,6 +205,14 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
                                                          EXO_PARAM_READWRITE));
 
   g_object_class_install_property (gobject_class,
+                                   PROP_STATUSBAR,
+                                   g_param_spec_boolean ("statusbar",
+                                                         "statusbar",
+                                                         "statusbar",
+                                                         TRUE,
+                                                         EXO_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
                                    PROP_WORD_WRAP,
                                    g_param_spec_boolean ("word-wrap",
                                                          "word-wrap",
diff --git a/mousepad/mousepad-screen.c b/mousepad/mousepad-screen.c
index c643e39..4e281b7 100644
--- a/mousepad/mousepad-screen.c
+++ b/mousepad/mousepad-screen.c
@@ -104,6 +104,7 @@ struct _MousepadScreen
 
 static guint         screen_signals[LAST_SIGNAL];
 static GObjectClass *mousepad_screen_parent_class;
+static guint         untitled_counter = 0;
 
 
 
@@ -222,7 +223,7 @@ mousepad_screen_init (MousepadScreen *screen)
 
   /* initialize the variables */
   screen->filename     = NULL;
-  screen->display_name = NULL;
+  screen->display_name = g_strdup_printf ("%s %d", _("Untitled"), ++untitled_counter);
   screen->mtime        = 0;
 
   /* setup the scolled window */
@@ -533,10 +534,8 @@ mousepad_screen_get_title (MousepadScreen *screen,
 
   if (G_UNLIKELY (show_full_path && screen->filename))
     title = screen->filename;
-  else if (screen->display_name)
-    title = screen->display_name;
   else
-    title = _("Untitled");
+    title = screen->display_name;
 
   return title;
 }
diff --git a/mousepad/mousepad-window-ui.xml b/mousepad/mousepad-window-ui.xml
index b1e94b7..77b6c72 100644
--- a/mousepad/mousepad-window-ui.xml
+++ b/mousepad/mousepad-window-ui.xml
@@ -11,7 +11,14 @@
       <menuitem action="new-window" />
       <separator />
       <menuitem action="open-file" />
-      <menuitem action="recent-menu" />
+
+      <menu action="recent-menu">
+        <menuitem action="no-recent-items" />
+        <placeholder name="placeholder-recent-items" />
+        <separator />
+        <menuitem action="clear-recent" />
+      </menu>
+
       <separator />
       <menuitem action="save-file" />
       <menuitem action="save-file-as" />
@@ -45,6 +52,8 @@
     <menu action="view-menu">
       <menuitem action="font" />
       <separator />
+      <menuitem action="statusbar" />
+      <separator />
       <menuitem action="word-wrap" />
       <menuitem action="line-numbers" />
       <separator />
diff --git a/mousepad/mousepad-window.c b/mousepad/mousepad-window.c
index a0da54c..81d9a66 100644
--- a/mousepad/mousepad-window.c
+++ b/mousepad/mousepad-window.c
@@ -47,6 +47,18 @@ static void              mousepad_window_dispose                      (GObject
 static void              mousepad_window_finalize                     (GObject                *object);
 static gboolean          mousepad_window_configure_event              (GtkWidget              *widget,
                                                                        GdkEventConfigure      *event);
+static void              mousepad_window_connect_proxy                (GtkUIManager           *manager,
+                                                                       GtkAction              *action,
+                                                                       GtkWidget              *proxy,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_disconnect_proxy             (GtkUIManager           *manager,
+                                                                       GtkAction              *action,
+                                                                       GtkWidget              *proxy,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_menu_item_selected           (GtkWidget              *menu_item,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_menu_item_deselected         (GtkWidget              *menu_item,
+                                                                       MousepadWindow         *window);
 static gboolean          mousepad_window_save_geometry_timer          (gpointer                user_data);
 static void              mousepad_window_save_geometry_timer_destroy  (gpointer                user_data);
 static MousepadScreen   *mousepad_window_get_active                   (MousepadWindow         *window);
@@ -56,8 +68,11 @@ static void              mousepad_window_add                          (MousepadW
                                                                        MousepadScreen         *screen);
 static gboolean          mousepad_window_close_screen                 (MousepadWindow         *window,
                                                                        MousepadScreen         *screen);
-static void              mousepad_window_create_recent_menu           (MousepadWindow         *window);
-static void              mousepad_window_add_recent                   (const gchar            *filename);
+static gint              mousepad_window_sort_recent_items            (GtkRecentInfo          *a,
+                                                                       GtkRecentInfo          *b);
+static void              mousepad_window_recent_menu                  (MousepadWindow         *window);
+static void              mousepad_window_add_recent                   (MousepadWindow         *window,
+                                                                       const gchar            *filename);
 static void              mousepad_window_set_title                    (MousepadWindow         *window,
                                                                        MousepadScreen         *screen);
 static void              mousepad_window_notify_title                 (MousepadScreen         *screen,
@@ -69,6 +84,10 @@ static void              mousepad_window_page_notified                (GtkNotebo
 static void              mousepad_window_tab_removed                  (GtkNotebook            *notebook,
                                                                        MousepadScreen         *screen,
                                                                        MousepadWindow         *window);
+static void              mousepad_window_page_reordered               (GtkNotebook            *notebook,
+                                                                       GtkNotebookPage        *page,
+                                                                       guint                   page_num,
+                                                                       MousepadWindow         *window);
 static void              mousepad_window_error_dialog                 (GtkWindow              *window,
                                                                        GError                 *error,
                                                                        const gchar            *message);
@@ -81,7 +100,9 @@ static void              mousepad_window_action_open_new_window       (GtkAction
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_open_file             (GtkAction              *action,
                                                                        MousepadWindow         *window);
-static void              mousepad_window_action_open_recent           (GtkRecentChooser       *chooser,
+static void              mousepad_window_action_open_recent           (GtkAction              *action,
+                                                                       MousepadWindow         *window);
+static void              mousepad_window_action_clear_recent          (GtkAction              *action,
                                                                        MousepadWindow         *window);
 static void              mousepad_window_action_save_file             (GtkAction              *action,
                                                                        MousepadWindow         *window);
@@ -133,10 +154,24 @@ struct _MousepadWindow
 
   MousepadPreferences *preferences;
 
-  GtkActionGroup      *action_group;
+  /* closures for the menu callbacks */
+  GClosure            *menu_item_selected_closure;
+  GClosure            *menu_item_deselected_closure;
+
+  /* action groups */
+  GtkActionGroup      *window_actions;
+  GtkActionGroup      *gomenu_actions;
+  GtkActionGroup      *recent_actions;
+
+  /* UI manager */
   GtkUIManager        *ui_manager;
 
+  /* recent items manager */
+  GtkRecentManager    *recent_manager;
+
+  /* main window widgets */
   GtkWidget           *notebook;
+  GtkWidget           *statusbar;
 
   /* support to remember window geometry */
   gint                 save_geometry_timer_id;
@@ -151,6 +186,8 @@ static const GtkActionEntry action_entries[] =
   { "new-window", "window-new", N_ ("_New Window"), "<control>N", N_ ("Open a new Mousepad window"), G_CALLBACK (mousepad_window_action_open_new_window), },
   { "open-file", GTK_STOCK_OPEN, N_ ("_Open File"), NULL, N_ ("Open a new document"), G_CALLBACK (mousepad_window_action_open_file), },
   { "recent-menu", NULL, N_ ("Open _Recent"), NULL, NULL, NULL, },
+  { "no-recent-items", NULL, N_ ("No items found"), NULL, NULL, NULL, },
+  { "clear-recent", GTK_STOCK_CLEAR, N_ ("C_lear Recent History"), NULL, NULL, G_CALLBACK (mousepad_window_action_clear_recent), },
   { "save-file", GTK_STOCK_SAVE, N_ ("_Save"), NULL, N_ ("Save current document"), G_CALLBACK (mousepad_window_action_save_file), },
   { "save-file-as", GTK_STOCK_SAVE_AS, N_ ("Save _As"), NULL, N_ ("Save current document as another file"), G_CALLBACK (mousepad_window_action_save_file_as), },
   { "close-tab", GTK_STOCK_CLOSE, N_ ("C_lose Tab"), "<control>W", N_ ("Close the current Mousepad tab"), G_CALLBACK (mousepad_window_action_close_tab), },
@@ -186,6 +223,7 @@ static const GtkActionEntry action_entries[] =
 
 static const GtkToggleActionEntry toggle_action_entries[] =
 {
+  { "statusbar", NULL, N_ ("_Statusbar"), NULL, NULL, NULL, FALSE, },
   { "word-wrap", NULL, N_ ("_Word Wrap"), NULL, NULL, NULL, FALSE, },
   { "line-numbers", NULL, N_ ("_Line Numbers"), NULL, NULL, NULL, FALSE, },
   { "auto-indent", NULL, N_ ("_Auto Indent"), NULL, NULL, NULL, FALSE, },
@@ -257,6 +295,16 @@ mousepad_window_init (MousepadWindow *window)
 
   window->preferences = mousepad_preferences_get ();
 
+  /* allocate a closure for the menu_item_selected() callback */
+  window->menu_item_selected_closure = g_cclosure_new_object (G_CALLBACK (mousepad_window_menu_item_selected), G_OBJECT (window));
+  g_closure_ref (window->menu_item_selected_closure);
+  g_closure_sink (window->menu_item_selected_closure);
+
+  /* allocate a closure for the menu_item_deselected() callback */
+  window->menu_item_deselected_closure = g_cclosure_new_object (G_CALLBACK (mousepad_window_menu_item_deselected), G_OBJECT (window));
+  g_closure_ref (window->menu_item_deselected_closure);
+  g_closure_sink (window->menu_item_deselected_closure);
+
   /* signal for monitoring */
   g_signal_connect (G_OBJECT (window), "delete-event",
                     G_CALLBACK (mousepad_window_delete_event), NULL);
@@ -271,26 +319,42 @@ mousepad_window_init (MousepadWindow *window)
   gtk_window_set_default_size (GTK_WINDOW (window), width, height);
 
   /* the action group for this window */
-  window->action_group = gtk_action_group_new ("MousepadActionGroup");
-  gtk_action_group_set_translation_domain (window->action_group, GETTEXT_PACKAGE);
-  gtk_action_group_add_actions (window->action_group, action_entries, G_N_ELEMENTS (action_entries), GTK_WIDGET (window));
-  gtk_action_group_add_toggle_actions (window->action_group, toggle_action_entries, G_N_ELEMENTS (toggle_action_entries), GTK_WIDGET (window));
+  window->window_actions = gtk_action_group_new ("WindowActions");
+  gtk_action_group_set_translation_domain (window->window_actions, GETTEXT_PACKAGE);
+  gtk_action_group_add_actions (window->window_actions, action_entries, G_N_ELEMENTS (action_entries), GTK_WIDGET (window));
+  gtk_action_group_add_toggle_actions (window->window_actions, toggle_action_entries, G_N_ELEMENTS (toggle_action_entries), GTK_WIDGET (window));
 
   /* create mutual bindings for the toggle buttons */
-  action = gtk_action_group_get_action (window->action_group, "line-numbers");
+  action = gtk_action_group_get_action (window->window_actions, "line-numbers");
   exo_mutual_binding_new (G_OBJECT (window->preferences), "line-numbers", G_OBJECT (action), "active");
-  action = gtk_action_group_get_action (window->action_group, "auto-indent");
+  action = gtk_action_group_get_action (window->window_actions, "auto-indent");
   exo_mutual_binding_new (G_OBJECT (window->preferences), "auto-indent", G_OBJECT (action), "active");
-  action = gtk_action_group_get_action (window->action_group, "word-wrap");
+  action = gtk_action_group_get_action (window->window_actions, "statusbar");
+  exo_mutual_binding_new (G_OBJECT (window->preferences), "statusbar", G_OBJECT (action), "active");
+  action = gtk_action_group_get_action (window->window_actions, "word-wrap");
   exo_mutual_binding_new (G_OBJECT (window->preferences), "word-wrap", G_OBJECT (action), "active");
 
   window->ui_manager = gtk_ui_manager_new ();
-  gtk_ui_manager_insert_action_group (window->ui_manager, window->action_group, 0);
+  g_signal_connect (G_OBJECT (window->ui_manager), "connect-proxy", G_CALLBACK (mousepad_window_connect_proxy), window);
+  g_signal_connect (G_OBJECT (window->ui_manager), "disconnect-proxy", G_CALLBACK (mousepad_window_disconnect_proxy), window);
+  gtk_ui_manager_insert_action_group (window->ui_manager, window->window_actions, 0);
   gtk_ui_manager_add_ui_from_string (window->ui_manager, mousepad_window_ui, mousepad_window_ui_length, NULL);
 
-  /* append the recent-menu items */
-  mousepad_window_create_recent_menu (window);
+  /* create the recent manager */
+  window->recent_manager = gtk_recent_manager_get_default ();
+  window->recent_actions = gtk_action_group_new ("RecentActions");
+  gtk_ui_manager_insert_action_group (window->ui_manager, window->recent_actions, -1);
+  g_signal_connect_swapped (G_OBJECT (window->recent_manager), "changed",
+		            G_CALLBACK (mousepad_window_recent_menu), window);
+
+  /* create the recent menu */
+  mousepad_window_recent_menu (window);
 
+  /* create action group for the go menu */
+  window->gomenu_actions = gtk_action_group_new ("GoMenuActions");
+  gtk_ui_manager_insert_action_group (window->ui_manager, window->gomenu_actions, -1);
+
+  /* set accel group for the window */
   accel_group = gtk_ui_manager_get_accel_group (window->ui_manager);
   gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
 
@@ -327,6 +391,7 @@ mousepad_window_init (MousepadWindow *window)
       gtk_widget_show (separator);
     }
 
+  /* create the notebook */
   window->notebook = g_object_new (GTK_TYPE_NOTEBOOK,
                                    "homogeneous", FALSE,
                                    "scrollable", TRUE,
@@ -340,9 +405,16 @@ mousepad_window_init (MousepadWindow *window)
                     G_CALLBACK (mousepad_window_page_notified), window);
   g_signal_connect (G_OBJECT (window->notebook), "remove",
                     G_CALLBACK (mousepad_window_tab_removed), window);
+  g_signal_connect (G_OBJECT (window->notebook), "page-reordered",
+                    G_CALLBACK (mousepad_window_page_reordered), window);
 
   gtk_box_pack_start (GTK_BOX (vbox), window->notebook, TRUE, TRUE, 0);
   gtk_widget_show (window->notebook);
+
+  /* create the statusbar */
+  window->statusbar = g_object_new (GTK_TYPE_STATUSBAR, NULL);
+  gtk_box_pack_start (GTK_BOX (vbox), window->statusbar, FALSE, FALSE, 0);
+  exo_binding_new (G_OBJECT (window->preferences), "statusbar", G_OBJECT (window->statusbar), "visible");
 }
 
 
@@ -366,8 +438,17 @@ mousepad_window_finalize (GObject *object)
 {
   MousepadWindow *window = MOUSEPAD_WINDOW (object);
 
+  /* drop our references on the menu_item_selected()/menu_item_deselected() closures */
+  g_closure_unref (window->menu_item_deselected_closure);
+  g_closure_unref (window->menu_item_selected_closure);
+
+  /* release the ui manager */
   g_object_unref (G_OBJECT (window->ui_manager));
-  g_object_unref (G_OBJECT (window->action_group));
+
+  /* release the action groups */
+  g_object_unref (G_OBJECT (window->window_actions));
+  g_object_unref (G_OBJECT (window->gomenu_actions));
+  g_object_unref (G_OBJECT (window->recent_actions));
 
   /* release the preferences reference */
   g_object_unref (G_OBJECT (window->preferences));
@@ -405,6 +486,84 @@ mousepad_window_configure_event (GtkWidget         *widget,
 
 
 
+static void
+mousepad_window_connect_proxy (GtkUIManager   *manager,
+                               GtkAction      *action,
+                               GtkWidget      *proxy,
+                               MousepadWindow *window)
+{
+  /* we want to get informed when the user hovers a menu item */
+  if (GTK_IS_MENU_ITEM (proxy))
+    {
+      g_signal_connect_closure (G_OBJECT (proxy), "select", window->menu_item_selected_closure, FALSE);
+      g_signal_connect_closure (G_OBJECT (proxy), "deselect", window->menu_item_deselected_closure, FALSE);
+    }
+}
+
+
+
+static void
+mousepad_window_disconnect_proxy (GtkUIManager   *manager,
+                                  GtkAction      *action,
+                                  GtkWidget      *proxy,
+                                  MousepadWindow *window)
+{
+  /* undo what we did in connect_proxy() */
+  if (GTK_IS_MENU_ITEM (proxy))
+    {
+      g_signal_handlers_disconnect_matched (G_OBJECT (proxy), G_SIGNAL_MATCH_CLOSURE, 0, 0, window->menu_item_selected_closure, NULL, NULL);
+      g_signal_handlers_disconnect_matched (G_OBJECT (proxy), G_SIGNAL_MATCH_CLOSURE, 0, 0, window->menu_item_deselected_closure, NULL, NULL);
+    }
+}
+
+
+
+static void
+mousepad_window_menu_item_selected (GtkWidget      *menu_item,
+                                    MousepadWindow *window)
+{
+  GtkAction *action;
+  gchar     *tooltip;
+  gint       id;
+
+  /* we can only display tooltips if we have a statusbar */
+  if (G_LIKELY (window->statusbar != NULL))
+    {
+      /* determine the action for the menu item */
+      action = g_object_get_data (G_OBJECT (menu_item), I_("gtk-action"));
+      if (G_UNLIKELY (action == NULL))
+        return;
+
+      /* determine the tooltip from the action */
+      g_object_get (G_OBJECT (action), "tooltip", &tooltip, NULL);
+      if (G_LIKELY (tooltip != NULL))
+        {
+          id = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->statusbar), "Menu tooltip");
+          gtk_statusbar_push (GTK_STATUSBAR (window->statusbar), id, tooltip);
+          g_free (tooltip);
+        }
+    }
+}
+
+
+
+static void
+mousepad_window_menu_item_deselected (GtkWidget      *menu_item,
+                                      MousepadWindow *window)
+{
+  gint id;
+
+  /* we can only undisplay tooltips if we have a statusbar */
+  if (G_LIKELY (window->statusbar != NULL))
+    {
+      /* drop the last tooltip from the statusbar */
+      id = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->statusbar), "Menu tooltip");
+      gtk_statusbar_pop (GTK_STATUSBAR (window->statusbar), id);
+    }
+}
+
+
+
 static gboolean
 mousepad_window_save_geometry_timer (gpointer user_data)
 {
@@ -483,7 +642,7 @@ mousepad_window_open_tab (MousepadWindow *window,
 
   /* get the number of page in the notebook */
   if (filename)
-    npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) - 1;
+    npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
 
   /* walk though the tabs */
   for (i = 0; i < npages; i++)
@@ -705,9 +864,13 @@ mousepad_window_add (MousepadWindow *window,
   g_signal_connect (G_OBJECT (screen), "selection-changed", G_CALLBACK (mousepad_window_selection_changed), window);
   g_signal_connect (G_OBJECT (screen), "modified-changed", G_CALLBACK (mousepad_window_modified_changed), window);
 
-  /* append the page to the window */
-  page = gtk_notebook_append_page (GTK_NOTEBOOK (window->notebook),
-                                   GTK_WIDGET (screen), label);
+  /* insert the page */
+  page = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
+  page = gtk_notebook_insert_page (GTK_NOTEBOOK (window->notebook),
+                                   GTK_WIDGET (screen), label, page + 1);
+
+  /* allow tab reordering */
+  gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (window->notebook), GTK_WIDGET (screen), TRUE);
 
   /* check if we should always display tabs */
   g_object_get (G_OBJECT (window->preferences), "misc-always-show-tabs", &always_show_tabs, NULL);
@@ -821,52 +984,125 @@ mousepad_window_close_screen (MousepadWindow *window,
   return succeed;
 }
 
-
+static gint
+mousepad_window_sort_recent_items (GtkRecentInfo *a,
+                                   GtkRecentInfo *b)
+{
+  return (gtk_recent_info_get_modified (a) < gtk_recent_info_get_modified (b));
+}
 
 static void
-mousepad_window_create_recent_menu (MousepadWindow *window)
+mousepad_window_recent_menu (MousepadWindow *window)
 {
-  GtkRecentFilter *filter;
-  GtkWidget       *menu;
-  GtkWidget       *item;
-  gint             recent_menu_limit;
+  static guint   merge_id = 0;
+  GList         *items, *li, *actions;
+  GList         *filtered = NULL;
+  GtkRecentInfo *info;
+  const gchar   *display_name;
+  gchar         *uri_display;
+  gchar         *tooltip, *name, *label;
+  GtkAction     *action;
+  gint           n;
 
-  _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+  /* unmerge the ui controls from the previous update */
+  if (merge_id != 0)
+    gtk_ui_manager_remove_ui (window->ui_manager, merge_id);
 
-  /* get the recent menu item */
-  item = gtk_ui_manager_get_widget (window->ui_manager, "/main-menu/file-menu/recent-menu");
+  /* drop all the previous actions from the action group */
+  actions = gtk_action_group_list_actions (window->recent_actions);
+  for (li = actions; li != NULL; li = li->next)
+    gtk_action_group_remove_action (window->recent_actions, li->data);
+  g_list_free (actions);
 
-  /* create a new recent chooser */
-  menu = gtk_recent_chooser_menu_new ();
+  /* create a new merge id */
+  merge_id = gtk_ui_manager_new_merge_id (window->ui_manager);
+
+  /* get all the items in the manager */
+  items = gtk_recent_manager_get_items (window->recent_manager);
+
+  /* walk through the items in the manager */
+  for (li = items; li != NULL; li = li->next)
+    {
+      /* check if the item is in the Mousepad group */
+      if (!gtk_recent_info_has_group (li->data, PACKAGE_NAME))
+        continue;
+
+      /* append the item */
+      filtered = g_list_prepend (filtered, li->data);
+    }
 
-  /* show only Mousepad items */
-  filter = gtk_recent_filter_new ();
-  gtk_recent_filter_add_application (filter, "Mousepad Text Editor");
-  gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu), filter);
+  /* sort the filtered items */
+  filtered = g_list_sort (filtered, (GCompareFunc) mousepad_window_sort_recent_items);
 
   /* get the recent menu limit number */
-  g_object_get (G_OBJECT (window->preferences), "misc-recent-menu-limit", &recent_menu_limit, NULL);
+  g_object_get (G_OBJECT (window->preferences), "misc-recent-menu-limit", &n, NULL);
+
+  /* append the items to the menu */
+  for (li = filtered; n > 0 && li != NULL; li = li->next, --n)
+    {
+      info = li->data;
+
+      /* create the action name */
+      name = g_strdup_printf ("recent-info-%d", n);
+
+      /* get the name of the item and escape the underscores */
+      display_name = gtk_recent_info_get_display_name (info);
+      label = exo_str_replace (display_name, "_", "__");
+
+      /* create the tooltip with an utf-8 valid version of the filename */
+      uri_display = gtk_recent_info_get_uri_display (info);
+      tooltip = g_strdup_printf (_("Open '%s'"), uri_display);
+      g_free (uri_display);
 
-  /* set recent menu properties */
-  gtk_recent_chooser_set_local_only (GTK_RECENT_CHOOSER (menu), TRUE);
-  gtk_recent_chooser_set_limit (GTK_RECENT_CHOOSER (menu), recent_menu_limit);
-  gtk_recent_chooser_set_show_tips (GTK_RECENT_CHOOSER (menu), TRUE);
+      /* create the action */
+      action = gtk_action_new (name, label, tooltip, NULL);
+
+      /* cleanup */
+      g_free (tooltip);
+      g_free (label);
+
+      /* add the info data and connect a menu signal */
+      g_object_set_data_full (G_OBJECT (action), I_("gtk-recent-info"), gtk_recent_info_ref (info), (GDestroyNotify) gtk_recent_info_unref);
+      g_signal_connect (G_OBJECT (action), "activate",
+			G_CALLBACK (mousepad_window_action_open_recent), window);
 
-  g_signal_connect (G_OBJECT (menu), "item-activated",
-                    G_CALLBACK(mousepad_window_action_open_recent), window);
+      /* add the action to the recent actions group */
+      gtk_action_group_add_action (window->recent_actions, action);
 
-  /* append the recent menu */
-  gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
+      /* add the action to the menu */
+      gtk_ui_manager_add_ui (window->ui_manager, merge_id,
+                             "/main-menu/file-menu/recent-menu/placeholder-recent-items",
+                             name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
+
+      /* cleanup */
+      g_free (name);
+    }
+
+  /* show or hide the not 'available' action */
+  action = gtk_action_group_get_action (window->window_actions, "no-recent-items");
+  gtk_action_set_visible (action, (filtered == NULL));
+  gtk_action_set_sensitive (action, FALSE);
+
+  /* set the sensitivity of the clear button */
+  action = gtk_action_group_get_action (window->window_actions, "clear-recent");
+  gtk_action_set_sensitive (action, (filtered != NULL));
+
+  /* cleanup */
+  g_list_free (filtered);
+  g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
+  g_list_free (items);
 }
 
 
 
+
 static void
-mousepad_window_add_recent (const gchar *filename)
+mousepad_window_add_recent (MousepadWindow *window,
+                            const gchar    *filename)
 {
-  GtkRecentData     info;
-  gchar            *uri;
-  GtkRecentManager *manager = gtk_recent_manager_get_default ();
+  GtkRecentData       info;
+  gchar              *uri;
+  static gchar       *groups[2] = { PACKAGE_NAME, NULL };
 
   _mousepad_return_if_fail (filename != NULL);
 
@@ -874,9 +1110,9 @@ mousepad_window_add_recent (const gchar *filename)
   info.display_name = NULL;
   info.description  = NULL;
   info.mime_type    = "text/plain";
-  info.app_name     = "Mousepad Text Editor";
-  info.app_exec     = "Mousepad %F";
-  info.groups       = NULL;
+  info.app_name     = PACKAGE_NAME;
+  info.app_exec     = PACKAGE " %u";
+  info.groups       = groups;
   info.is_private   = FALSE;
 
   /* create an uri from the filename */
@@ -885,7 +1121,7 @@ mousepad_window_add_recent (const gchar *filename)
   /* add it */
   if (G_LIKELY (uri != NULL))
     {
-      gtk_recent_manager_add_full (manager, uri, &info);
+      gtk_recent_manager_add_full (window->recent_manager, uri, &info);
       g_free (uri);
     }
 }
@@ -971,6 +1207,7 @@ mousepad_window_tab_removed (GtkNotebook    *notebook,
 
   if (G_UNLIKELY (npages == 0))
     {
+      /* destroy the window when there are no tabs */
       gtk_widget_destroy (GTK_WIDGET (window));
     }
   else
@@ -995,6 +1232,24 @@ mousepad_window_tab_removed (GtkNotebook    *notebook,
 
 
 static void
+mousepad_window_page_reordered (GtkNotebook     *notebook,
+                                GtkNotebookPage *page,
+                                guint            page_num,
+                                MousepadWindow  *window)
+{
+  GtkWidget *item;
+
+  /* update the go menu */
+  mousepad_window_rebuild_gomenu (window);
+
+  /* select the item in the menu */
+  item = g_object_get_data (G_OBJECT (page), "go-menu-item");
+  if (G_LIKELY (item != NULL))
+    gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (item), TRUE);
+}
+
+
+static void
 mousepad_window_error_dialog (GtkWindow   *window,
                               GError      *error,
                               const gchar *message)
@@ -1033,13 +1288,13 @@ mousepad_window_selection_changed (MousepadScreen *screen,
 {
   GtkAction *action;
 
-  action = gtk_action_group_get_action (window->action_group, "cut");
+  action = gtk_action_group_get_action (window->window_actions, "cut");
   gtk_action_set_sensitive (action, selected);
 
-  action = gtk_action_group_get_action (window->action_group, "copy");
+  action = gtk_action_group_get_action (window->window_actions, "copy");
   gtk_action_set_sensitive (action, selected);
 
-  action = gtk_action_group_get_action (window->action_group, "delete");
+  action = gtk_action_group_get_action (window->window_actions, "delete");
   gtk_action_set_sensitive (action, selected);
 }
 
@@ -1063,7 +1318,7 @@ mousepad_window_update_actions (MousepadWindow *window)
   n_pages = gtk_notebook_get_n_pages (notebook);
 
   /* set sensitivity for the "Close Tab" action */
-  action = gtk_action_group_get_action (window->action_group, "close-tab");
+  action = gtk_action_group_get_action (window->window_actions, "close-tab");
   gtk_action_set_sensitive (action, (n_pages > 1));
 
   /* update the actions for the current terminal screen */
@@ -1077,13 +1332,13 @@ mousepad_window_update_actions (MousepadWindow *window)
 
       g_object_get (G_OBJECT (window->preferences), "misc-cycle-tabs", &cycle_tabs, NULL);
 
-      action = gtk_action_group_get_action (window->action_group, "back");
+      action = gtk_action_group_get_action (window->window_actions, "back");
       gtk_action_set_sensitive (action, (cycle_tabs && n_pages > 1) || (page_num > 0));
 
-      action = gtk_action_group_get_action (window->action_group, "forward");
+      action = gtk_action_group_get_action (window->window_actions, "forward");
       gtk_action_set_sensitive (action, (cycle_tabs && n_pages > 1 ) || (page_num < n_pages - 1));
 
-      action = gtk_action_group_get_action (window->action_group, "save-file");
+      action = gtk_action_group_get_action (window->window_actions, "save-file");
       gtk_action_set_sensitive (action, gtk_text_view_get_editable (textview));
 
       g_object_get (G_OBJECT (buffer), "has-selection", &selected, NULL);
@@ -1118,19 +1373,22 @@ mousepad_window_rebuild_gomenu (MousepadWindow *window)
   gchar           accelerator[7];
   GtkRadioAction *action;
   GSList         *group = NULL;
-  const gchar    *go_menu_path;
+  GList          *actions, *li;
   static guint    merge_id = 0;
 
   /* remove the old merge */
-  if (merge_id > 1)
+  if (merge_id != 0)
     gtk_ui_manager_remove_ui (window->ui_manager, merge_id);
 
+  /* drop all the previous actions from the action group */
+  actions = gtk_action_group_list_actions (window->gomenu_actions);
+  for (li = actions; li != NULL; li = li->next)
+    gtk_action_group_remove_action (window->gomenu_actions, GTK_ACTION (li->data));
+  g_list_free (actions);
+
   /* create a new merge id */
   merge_id = gtk_ui_manager_new_merge_id (window->ui_manager);
 
-  /* the path in the ui where the items will be added */
-  go_menu_path = "/main-menu/go-menu/placeholder-go-items";
-
   /* walk through the notebook pages */
   npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
   for (n = 0; n < npages; ++n)
@@ -1155,19 +1413,19 @@ mousepad_window_rebuild_gomenu (MousepadWindow *window)
         {
           /* create an accelerator and add it to the menu */
           g_snprintf (accelerator, sizeof (accelerator), "<Alt>%d", n+1);
-          gtk_action_group_add_action_with_accel (window->action_group, GTK_ACTION (action), accelerator);
+          gtk_action_group_add_action_with_accel (window->gomenu_actions, GTK_ACTION (action), accelerator);
         }
       else
         /* add a menu item without accelerator */
-        gtk_action_group_add_action (window->action_group, GTK_ACTION (action));
+        gtk_action_group_add_action (window->gomenu_actions, GTK_ACTION (action));
 
       /* release the action */
       g_object_unref (G_OBJECT (action));
 
       /* add the action to the go menu */
       gtk_ui_manager_add_ui (window->ui_manager, merge_id,
-                             go_menu_path, name, name,
-                             GTK_UI_MANAGER_MENUITEM, FALSE);
+                             "/main-menu/go-menu/placeholder-go-items",
+                             name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
     }
 
   /* make sure the ui is up2date to avoid flickering */
@@ -1237,7 +1495,7 @@ mousepad_window_action_open_file (GtkAction      *action,
           mousepad_window_open_tab (window, filename);
 
           /* add to the recent files */
-          mousepad_window_add_recent (filename);
+          mousepad_window_add_recent (window, filename);
 
           /* cleanup */
           g_free (filename);
@@ -1254,19 +1512,22 @@ mousepad_window_action_open_file (GtkAction      *action,
 
 
 static void
-mousepad_window_action_open_recent (GtkRecentChooser *chooser,
+mousepad_window_action_open_recent (GtkAction        *action,
                                     MousepadWindow   *window)
 {
-  gchar            *uri;
-  gchar            *filename;
-  gboolean          succeed;
-  GtkRecentManager *manager;
+  const gchar   *uri;
+  gchar         *filename;
+  gboolean       succeed = FALSE;
+  GtkRecentInfo *info;
 
-  /* get the file uri */
-  uri = gtk_recent_chooser_get_current_uri (chooser);
+  /* get the info */
+  info = g_object_get_data (G_OBJECT (action), I_("gtk-recent-info"));
 
-  if (G_LIKELY(uri != NULL))
+  if (G_LIKELY (info != NULL))
     {
+      /* get the file uri */
+      uri = gtk_recent_info_get_uri (info);
+
       /* get the filename from the uri */
       filename = g_filename_from_uri (uri, NULL, NULL);
 
@@ -1275,20 +1536,82 @@ mousepad_window_action_open_recent (GtkRecentChooser *chooser,
           /* open a new tab */
           succeed = mousepad_window_open_tab (window, filename);
 
-          /* remove the file from the recent menu if Mousepad failed to open it */
-          if (G_UNLIKELY (succeed == FALSE))
-            {
-              manager = gtk_recent_manager_get_default ();
-              gtk_recent_manager_remove_item (manager, uri, NULL);
-            }
+          /* update the recent history */
+          if (G_LIKELY (succeed))
+            /* update the recent manager count and time */
+            gtk_recent_manager_add_item (window->recent_manager, uri);
+          else
+            /* remove the item from the history */
+            gtk_recent_manager_remove_item (window->recent_manager, uri, NULL);
 
           /* cleanup */
           g_free (filename);
         }
+    }
+}
+
+
+
+
+static void
+mousepad_window_action_clear_recent (GtkAction      *action,
+                                     MousepadWindow *window)
+{
+  GtkWidget         *dialog;
+  GtkRecentInfo     *info;
+  GList             *items, *li;
+  const gchar       *uri;
+  GError            *error = NULL;
+
+  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                   GTK_MESSAGE_QUESTION,
+                                   GTK_BUTTONS_NONE,
+                                   _("Are you sure you want to clear\nthe Recent History?"));
+  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                            _("This will only remove the items from the history owned by Mousepad."));
+  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                          GTK_STOCK_CLEAR, GTK_RESPONSE_OK,
+                          NULL);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+    {
+      /* get all the items in the manager */
+      items = gtk_recent_manager_get_items (window->recent_manager);
+
+      /* walk through the items */
+      for (li = items; li != NULL; li = li->next)
+        {
+          info = li->data;
+
+          /* check if the item is in the Mousepad group */
+          if (gtk_recent_info_has_group (info, PACKAGE_NAME))
+            {
+              /* get the uri of the recent item */
+              uri = gtk_recent_info_get_uri (info);
+
+              /* try to remove it, if it fails, break the loop */
+              if (G_UNLIKELY (gtk_recent_manager_remove_item (window->recent_manager, uri, &error) == FALSE))
+                {
+                  mousepad_window_error_dialog (GTK_WINDOW (window), error,
+                                                _("Failed to remove an item from the recent history"));
+                  g_error_free (error);
+
+                  /* stop removing to prevent multiple warnings */
+                  break;
+                }
+            }
+        }
 
       /* cleanup */
-      g_free (uri);
+      g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
+      g_list_free (items);
     }
+
+  /* destroy the dialog */
+  gtk_widget_destroy (dialog);
 }
 
 
@@ -1338,7 +1661,7 @@ mousepad_window_action_save_file_as (GtkAction      *action,
        * that worked too, add the (new) file to the recent menu */
       if (mousepad_window_save_as (window, screen))
         if (mousepad_screen_save_file (screen, &error))
-          mousepad_window_add_recent (mousepad_screen_get_filename (screen));
+          mousepad_window_add_recent (window, mousepad_screen_get_filename (screen));
 
       /* check for errors */
       if (G_UNLIKELY (error != NULL))
@@ -1349,7 +1672,7 @@ mousepad_window_action_save_file_as (GtkAction      *action,
       else
         {
           /* make sure save-file is sensitive */
-          action = gtk_action_group_get_action (window->action_group, "save-file");
+          action = gtk_action_group_get_action (window->window_actions, "save-file");
           gtk_action_set_sensitive (action, TRUE);
         }
     }


More information about the Xfce4-commits mailing list