[Xfce4-commits] <mousepad:master> * mousepad/mousepad-dialogs.{c, h}: New file for the dialogs so the mousepad-window file becomes more readable. * mousepad/mousepad-window.c: Split some function and reorder them a bit. * mousepad/mousepad-window.c: The items in the go menu now have the filename as statusbar tooltip. * mousepad/mousepad-window.c: Check if the file is externally modified before writing. If it is, ask the user what to do. * mousepad/main.c, mousepad/mousepad-dbus.{c, h}, mousepad/mousepad-dbus-infos.xml: Support for terminating a running mousepad instance (that is connected to dbus), using mousepad -q. * mousepad/*: Add function destriptions for Erik (and others) :-).
Nick Schermer
noreply at xfce.org
Sat May 5 21:30:08 CEST 2012
Updating branch refs/heads/master
to b5178ab96dc4dd424f9ce884529a67e95731e145 (commit)
from 5263c479394dbb5a6bc0b892806f11a629bd81f4 (commit)
commit b5178ab96dc4dd424f9ce884529a67e95731e145
Author: Nick Schermer <nick at xfce.org>
Date: Sat Mar 3 12:07:46 2007 +0000
* mousepad/mousepad-dialogs.{c,h}: New file for the dialogs
so the mousepad-window file becomes more readable.
* mousepad/mousepad-window.c: Split some function and reorder
them a bit.
* mousepad/mousepad-window.c: The items in the go menu now have
the filename as statusbar tooltip.
* mousepad/mousepad-window.c: Check if the file is externally modified
before writing. If it is, ask the user what to do.
* mousepad/main.c, mousepad/mousepad-dbus.{c,h},
mousepad/mousepad-dbus-infos.xml: Support for terminating a running
mousepad instance (that is connected to dbus), using mousepad -q.
* mousepad/*: Add function destriptions for Erik (and others) :-).
(Old svn revision: 25069)
ChangeLog | 15 +
TODO | 2 +
configure.in.in | 1 +
mousepad/Makefile.am | 4 +
mousepad/main.c | 29 +-
mousepad/mousepad-application.c | 62 +++-
mousepad/mousepad-dbus-infos.xml | 44 ++
mousepad/mousepad-dbus.c | 192 ++++++--
mousepad/mousepad-dbus.h | 27 +-
mousepad/mousepad-dialogs.c | 333 +++++++++++++
mousepad/mousepad-dialogs.h | 48 ++
mousepad/mousepad-file.c | 69 +++-
mousepad/mousepad-file.h | 35 +-
mousepad/mousepad-preferences.c | 138 +++++-
mousepad/mousepad-screen.c | 16 +-
mousepad/mousepad-screen.h | 4 +-
mousepad/mousepad-view.c | 118 ++++-
mousepad/mousepad-window.c | 975 +++++++++++++++++---------------------
18 files changed, 1426 insertions(+), 686 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 65840c5..15b27bb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2007-02-19 Nick Schermer <nick at xfce.org>
+
+ * mousepad/mousepad-dialogs.{c,h}: New file for the dialogs
+ so the mousepad-window file becomes more readable.
+ * mousepad/mousepad-window.c: Split some function and reorder
+ them a bit.
+ * mousepad/mousepad-window.c: The items in the go menu now have
+ the filename as statusbar tooltip.
+ * mousepad/mousepad-window.c: Check if the file is externally modified
+ before writing. If it is, ask the user what to do.
+ * mousepad/main.c, mousepad/mousepad-dbus.{c,h},
+ mousepad/mousepad-dbus-infos.xml: Support for terminating a running
+ mousepad instance (that is connected to dbus), using mousepad -q.
+ * mousepad/*: Add function destriptions for Erik (and others) :-).
+
2007-02-18 Nick Schermer <nick at xfce.org>
* mousepad/mousepad-window.c: Improve the menu tooltips.
diff --git a/TODO b/TODO
index 6cb57fe..e64fc10 100644
--- a/TODO
+++ b/TODO
@@ -2,6 +2,8 @@
- Dialog when closing multiple (modified) tabs.
- Right-click menu for the tab label.
- Tab font color when the file is modified or readonly.
+ - Test the application with a screen reader and add Atk objects
+ where needed.
- Text View
- Search and Replace. Maybe also text highlighting.
diff --git a/configure.in.in b/configure.in.in
index dbf3aba..2e629ec 100644
--- a/configure.in.in
+++ b/configure.in.in
@@ -87,6 +87,7 @@ dnl ***********************************
dnl *** Check for required packages ***
dnl ***********************************
XDT_CHECK_PACKAGE([EXO], [exo-0.3], [0.3.2])
+XDT_CHECK_PACKAGE([PCRE], [libpcre], [6.0])
XDT_CHECK_PACKAGE([GLIB], [glib-2.0], [2.12.0])
XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.12.0])
XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.10.0])
diff --git a/mousepad/Makefile.am b/mousepad/Makefile.am
index 08a4384..5f31e7c 100644
--- a/mousepad/Makefile.am
+++ b/mousepad/Makefile.am
@@ -19,6 +19,8 @@ mousepad_SOURCES = \
main.c \
mousepad-application.c \
mousepad-application.h \
+ mousepad-dialogs.c \
+ mousepad-dialogs.h \
mousepad-file.c \
mousepad-file.h \
mousepad-preferences.c \
@@ -36,6 +38,7 @@ mousepad_SOURCES = \
mousepad_CFLAGS = \
$(EXO_CFLAGS) \
+ $(PCRE_CFLAGS) \
$(GTHREAD_CFLAGS) \
$(PLATFORM_CFLAGS)
@@ -46,6 +49,7 @@ mousepad_LDFLAGS = \
mousepad_LDADD = \
$(EXO_LIBS) \
+ $(PCRE_LIBS) \
$(GTHREAD_LIBS)
if HAVE_DBUS
diff --git a/mousepad/main.c b/mousepad/main.c
index d7102d8..b88bd15 100644
--- a/mousepad/main.c
+++ b/mousepad/main.c
@@ -41,6 +41,7 @@ static gchar **filenames = NULL;
static gboolean opt_version = FALSE;
#ifdef HAVE_DBUS
static gboolean opt_disable_server = FALSE;
+static gboolean opt_quit = FALSE;
#endif
@@ -49,9 +50,10 @@ static gboolean opt_disable_server = FALSE;
static GOptionEntry option_entries[] =
{
#ifdef HAVE_DBUS
- { "disable-server", '\0', 0, G_OPTION_ARG_NONE, &opt_disable_server, N_ ("Do not register with the D-BUS session message bus"), NULL, },
+ { "disable-server", '\0', 0, G_OPTION_ARG_NONE, &opt_disable_server, N_("Do not register with the D-BUS session message bus"), NULL, },
+ { "quit", 'q', 0, G_OPTION_ARG_NONE, &opt_quit, N_("Quit a running Mousepad instance"), NULL, },
#endif
- { "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, N_ ("Print version information and exit"), NULL, },
+ { "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, N_("Print version information and exit"), NULL, },
{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL, NULL },
{ NULL, },
};
@@ -62,11 +64,12 @@ gint
main (gint argc, gchar **argv)
{
MousepadApplication *application;
+ GError *error = NULL;
+ gchar *working_directory;
+
#ifdef HAVE_DBUS
MousepadDBusService *dbus_service;
#endif
- GError *error = NULL;
- gchar *working_directory;
/* translation domain */
xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
@@ -114,6 +117,22 @@ main (gint argc, gchar **argv)
return EXIT_SUCCESS;
}
+#ifdef HAVE_DBUS
+ /* check if we need to terminate a running Mousepad instance */
+ if (G_UNLIKELY (opt_quit))
+ {
+ /* try to terminate whatever is running */
+ if (!mousepad_dbus_client_terminate (&error))
+ {
+ g_error ("Failed to terminate a running instance: %s\n", error->message);
+ g_error_free (error);
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+ }
+#endif /* !HAVE_DBUS */
+
/* get the current working directory */
working_directory = g_get_current_dir ();
@@ -150,7 +169,7 @@ main (gint argc, gchar **argv)
/* create a new mousepad application */
application = mousepad_application_get ();
- /* open an empty window or the files */
+ /* open an empty window (with an empty document or the files) */
mousepad_application_open_window (application, NULL, working_directory, filenames);
/* cleanup */
diff --git a/mousepad/mousepad-application.c b/mousepad/mousepad-application.c
index 755348b..da88720 100644
--- a/mousepad/mousepad-application.c
+++ b/mousepad/mousepad-application.c
@@ -44,6 +44,7 @@ struct _MousepadApplication
{
GObject __parent__;
+ /* internal list of all the opened windows */
GList *windows;
};
@@ -53,6 +54,16 @@ static GObjectClass *mousepad_application_parent_class;
+/**
+ * mousepad_application_get:
+ *
+ * Returns the global shared #MousepadApplication instance.
+ * This method takes a reference on the global instance
+ * for the caller, so you must call g_object_unref()
+ * on it when done.
+ *
+ * Return value: the shared #MousepadApplication instance.
+ **/
MousepadApplication*
mousepad_application_get (void)
{
@@ -72,10 +83,6 @@ mousepad_application_get (void)
-static GObjectClass *mousepad_application_parent_class;
-
-
-
GType
mousepad_application_get_type (void)
{
@@ -116,7 +123,7 @@ mousepad_application_init (MousepadApplication *application)
gchar *path;
/* check if we have a saved accel map */
- path = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, "Mousepad/accels.scm");
+ path = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, PACKAGE_NAME "/accels.scm");
if (G_LIKELY (path != NULL))
{
/* load the accel map */
@@ -135,7 +142,7 @@ mousepad_application_finalize (GObject *object)
gchar *path;
/* save the current accel map */
- path = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "Mousepad/accels.scm", TRUE);
+ path = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, PACKAGE_NAME "/accels.scm", TRUE);
if (G_LIKELY (path != NULL))
{
/* save the accel map */
@@ -143,6 +150,7 @@ mousepad_application_finalize (GObject *object)
g_free (path);
}
+ /* destroy the windows if they are still opened */
for (li = application->windows; li != NULL; li = li->next)
{
g_signal_handlers_disconnect_by_func (G_OBJECT (li->data), G_CALLBACK (mousepad_application_window_destroyed), application);
@@ -156,6 +164,16 @@ mousepad_application_finalize (GObject *object)
+/**
+ * mousepad_application_get_windows:
+ * @application: A #MousepadApplication.
+ *
+ * Returns a list of #MousepadWindows currently registered by the
+ * #MousepadApplication. The returned list is owned by the caller and
+ * must be freed using g_list_free().
+ *
+ * Return value: the list of regular #MousepadWindows in @application.
+ **/
GList*
mousepad_application_get_windows (MousepadApplication *application)
{
@@ -173,6 +191,14 @@ mousepad_application_get_windows (MousepadApplication *application)
+/**
+ * mousepad_application_has_windows:
+ * @application : a #MousepadApplication.
+ *
+ * Returns %TRUE if @application controls atleast one window.
+ *
+ * Return value: %TRUE if @application controls atleast one window.
+ **/
gboolean
mousepad_application_has_windows (MousepadApplication *application)
{
@@ -183,6 +209,19 @@ mousepad_application_has_windows (MousepadApplication *application)
+/**
+ * mousepad_application_open_window:
+ * @application : A #MousepadApplication.
+ * @screen : The #GdkScreen on which to open the window or %NULL
+ * to open on the default screen.
+ * @working_directory : The default working directory for this window.
+ * @filenames : A list of filenames we try to open in tabs. The file names
+ * can either be absolute paths, supported URIs or relative file
+ * names to @working_directory or %NULL for an untitled document.
+ *
+ * Opens a new Mousepad window and tries to open all the file names in tabs. If
+ * @filename is %NULL an empty Untiled documenten will be opened in the window.
+ **/
void
mousepad_application_open_window (MousepadApplication *application,
GdkScreen *screen,
@@ -210,6 +249,8 @@ mousepad_application_open_window (MousepadApplication *application,
else
mousepad_window_open_tab (MOUSEPAD_WINDOW (window), NULL);
+ /* TODO: check if there are actually some tabs in the window, if not, open an empty tab */
+
/* connect to the "destroy" signal */
g_signal_connect (G_OBJECT (window), "destroy",
G_CALLBACK (mousepad_application_window_destroyed), application);
@@ -222,6 +263,15 @@ mousepad_application_open_window (MousepadApplication *application,
+/**
+ * mousepad_application_window_destroyed:
+ * @window : The window that has been destroyed.
+ * @application : A #MousepadApplication.
+ *
+ * This function removes @window from the registed windows in @application.
+ * When there are no more windows left in @application, the application is
+ * terminated.
+ **/
static void
mousepad_application_window_destroyed (GtkWidget *window,
MousepadApplication *application)
diff --git a/mousepad/mousepad-dbus-infos.xml b/mousepad/mousepad-dbus-infos.xml
index 27fa116..4787ba8 100644
--- a/mousepad/mousepad-dbus-infos.xml
+++ b/mousepad/mousepad-dbus-infos.xml
@@ -1,15 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ $Id$
+
+ Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+
+ 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., 59 Temple
+ Place, Suite 330, Boston, MA 02111-1307 USA
+-->
+
<node name="/org/xfce/Mousepad">
+ <!--
+ org.xfce.Thunar
+
+ The Mousepad specific interface, which provides Mousepad specific methods.
+
+ This inferface is internally used by Mousepad and should not be used externally.
+ -->
<interface name="org.xfce.Mousepad">
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="mousepad_dbus_service" />
+ <!--
+ LaunchFiles (working-directory : STRING, filenames : ARRAY OF STRING : VOID
+
+ working-directory : the directory, relative to which filenames should
+ be interpreted.
+ filenames : an array of file names to launch. The file names may
+ be either file:-URIs, absolute paths or paths relative
+ to the working-directory.
+ -->
<method name="LaunchFiles">
<arg direction="in" name="working-directory" type="s" />
<arg direction="in" name="filenames" type="as" />
</method>
+ <!--
+ Terminate () : VOID
+
+ Tells a running Mousepad instance to terminate immediately.
+ -->
+ <method name="Terminate">
+ </method>
+
</interface>
</node>
diff --git a/mousepad/mousepad-dbus.c b/mousepad/mousepad-dbus.c
index 9c6f6bd..1b7288a 100644
--- a/mousepad/mousepad-dbus.c
+++ b/mousepad/mousepad-dbus.c
@@ -38,13 +38,18 @@
-static void mousepad_dbus_service_class_init (MousepadDBusServiceClass *klass);
-static void mousepad_dbus_service_init (MousepadDBusService *dbus_service);
-static void mousepad_dbus_service_finalize (GObject *object);
-static gboolean mousepad_dbus_service_launch_files (MousepadDBusService *dbus_service,
- const gchar *working_directory,
- gchar **filenames,
- GError **error);
+#define MOUSEPAD_DBUS_PATH "/org/xfce/Mousepad"
+#define MOUSEPAD_DBUS_INTERFACE "org.xfce.Mousepad"
+
+
+
+static void mousepad_dbus_service_class_init (MousepadDBusServiceClass *klass);
+static void mousepad_dbus_service_init (MousepadDBusService *dbus_service);
+static void mousepad_dbus_service_finalize (GObject *object);
+static gboolean mousepad_dbus_service_launch_files (MousepadDBusService *dbus_service,
+ const gchar *working_directory,
+ gchar **filenames,
+ GError **error);
@@ -116,10 +121,11 @@ mousepad_dbus_service_init (MousepadDBusService *dbus_service)
if (G_LIKELY (dbus_service->connection != NULL))
{
/* register the /org/xfce/TextEditor object for Mousepad */
- dbus_g_connection_register_g_object (dbus_service->connection, "/org/xfce/Mousepad", G_OBJECT (dbus_service));
+ dbus_g_connection_register_g_object (dbus_service->connection, MOUSEPAD_DBUS_PATH, G_OBJECT (dbus_service));
/* request the org.xfce.Mousepad name for Mousepad */
- dbus_bus_request_name (dbus_g_connection_get_connection (dbus_service->connection), "org.xfce.Mousepad", DBUS_NAME_FLAG_REPLACE_EXISTING, NULL);
+ dbus_bus_request_name (dbus_g_connection_get_connection (dbus_service->connection),
+ MOUSEPAD_DBUS_INTERFACE, DBUS_NAME_FLAG_REPLACE_EXISTING, NULL);
}
else
{
@@ -152,6 +158,20 @@ mousepad_dbus_service_finalize (GObject *object)
+/**
+ * mousepad_dbus_service_launch_files:
+ * @dbus_service : A #MousepadDBusService.
+ * @working_directory : The default working directory for this window.
+ * @filenames : A list of filenames we try to open in tabs. The file names
+ * can either be absolute paths, supported URIs or relative file
+ * names to @working_directory or %NULL for an untitled document.
+ * @error : Return location for errors, not used atm.
+ *
+ * This function is activated by DBus (service) and opens a new window in this instance of
+ * Mousepad.
+ *
+ * Return value: %TRUE on success, %FALSE if @error is set.
+ **/
static gboolean
mousepad_dbus_service_launch_files (MousepadDBusService *dbus_service,
const gchar *working_directory,
@@ -164,8 +184,10 @@ mousepad_dbus_service_launch_files (MousepadDBusService *dbus_service,
_mousepad_return_val_if_fail (g_path_is_absolute (working_directory), FALSE);
_mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ /* get the default screen */
screen = gdk_screen_get_default ();
+ /* open a mousepad window */
application = mousepad_application_get ();
mousepad_application_open_window (application, screen, working_directory, filenames);
g_object_unref (G_OBJECT (application));
@@ -175,19 +197,46 @@ mousepad_dbus_service_launch_files (MousepadDBusService *dbus_service,
-gboolean
-mousepad_dbus_client_launch_files (gchar **filenames,
- const gchar *working_directory,
- GError **error)
+/**
+ * mousepad_dbus_service_terminate:
+ * @dbus_service : A #MousepadDBusService.
+ * @error : Return location for errors, not used atm.
+ *
+ * This function quits this instance of Mousepad.
+ *
+ * Return value: %TRUE on success.
+ **/
+static gboolean
+mousepad_dbus_service_terminate (MousepadDBusService *dbus_service,
+ GError **error)
+{
+ /* leave the Gtk main loop as soon as possible */
+ gtk_main_quit ();
+
+ /* we cannot fail */
+ return TRUE;
+}
+
+
+
+/**
+ * mousepad_dbus_client_send:
+ * @message : A #DBusMessage.
+ * @error : Return location for errors or %NULL.
+ *
+ * This function sends the DBus message and should avoid
+ * code duplication in the functions below.
+ *
+ * Return value: %TRUE on succeed or %FALSE if @error is set.
+ **/
+static gboolean
+mousepad_dbus_client_send (DBusMessage *message,
+ GError **error)
{
DBusConnection *connection;
- DBusMessage *message;
DBusMessage *result;
DBusError derror;
- _mousepad_return_val_if_fail (g_path_is_absolute (working_directory), FALSE);
- _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
dbus_error_init (&derror);
/* try to connect to the session bus */
@@ -199,34 +248,22 @@ mousepad_dbus_client_launch_files (gchar **filenames,
return FALSE;
}
- /* generate the message */
- message = dbus_message_new_method_call ("org.xfce.Mousepad", "/org/xfce/Mousepad",
- "org.xfce.Mousepad", "LaunchFiles");
- dbus_message_set_auto_start (message, FALSE);
- dbus_message_append_args (message,
- DBUS_TYPE_STRING, &working_directory,
- DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &filenames, filenames ? g_strv_length (filenames) : 0,
- DBUS_TYPE_INVALID);
-
/* send the message */
result = dbus_connection_send_with_reply_and_block (connection, message, -1, &derror);
- /* release ref */
- dbus_message_unref (message);
-
/* check if no reply was received */
if (result == NULL)
{
-#ifndef NDEBUG
- /* set the error when debug is enabled */
- dbus_set_g_error (error, &derror);
-#endif
+ /* check if there was just no instance running */
+ if (!dbus_error_has_name (&derror, DBUS_ERROR_NAME_HAS_NO_OWNER))
+ dbus_set_g_error (error, &derror);
+
dbus_error_free (&derror);
return FALSE;
}
/* but maybe we received an error */
- if (dbus_message_get_type (result) == DBUS_MESSAGE_TYPE_ERROR)
+ if (G_UNLIKELY (dbus_message_get_type (result) == DBUS_MESSAGE_TYPE_ERROR))
{
dbus_set_error_from_message (&derror, result);
dbus_set_g_error (error, &derror);
@@ -243,5 +280,90 @@ mousepad_dbus_client_launch_files (gchar **filenames,
-#include <mousepad/mousepad-dbus-infos.h>
+/**
+ * mousepad_dbus_client_terminate:
+ * @error : Return location for errors or %NULL.
+ *
+ * Function called from this instance of the application and tries to invoke
+ * with an already running instance and ties to quit it.
+ * The mousepad_dbus_service_terminate function is activated in the running instance.
+ *
+ * Return value: %TRUE on success.
+ **/
+gboolean
+mousepad_dbus_client_terminate (GError **error)
+{
+ DBusMessage *message;
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* generate the message */
+ message = dbus_message_new_method_call (MOUSEPAD_DBUS_INTERFACE, MOUSEPAD_DBUS_PATH,
+ MOUSEPAD_DBUS_INTERFACE, "Terminate");
+ dbus_message_set_auto_start (message, FALSE);
+
+
+ /* send the message */
+ mousepad_dbus_client_send (message, error);
+
+ /* unref the message */
+ dbus_message_unref (message);
+
+ /* we return false if an error was set */
+ return (error != NULL);
+}
+
+
+
+/**
+ * mousepad_dbus_client_launch_files:
+ * @filenames : A list of filenames we try to open in tabs. The file names
+ * can either be absolute paths, supported URIs or relative file
+ * names to @working_directory or %NULL for an untitled document.
+ * @working_directory : Working directory for the new Mousepad window.
+ * @error : Return location for errors or %NULL.
+ *
+ * This function is called within this instance and tries to connect a running instance
+ * of Mousepad via DBus. The function mousepad_dbus_service_launch_files is activated in the
+ * running instance.
+ *
+ * Return value: %TRUE on success.
+ **/
+gboolean
+mousepad_dbus_client_launch_files (gchar **filenames,
+ const gchar *working_directory,
+ GError **error)
+{
+ DBusMessage *message;
+ guint length = 0;
+ gboolean succeed;
+
+ _mousepad_return_val_if_fail (g_path_is_absolute (working_directory), FALSE);
+ _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* get the length of the filesname string */
+ if (filenames)
+ length = g_strv_length (filenames);
+
+ /* generate the message */
+ message = dbus_message_new_method_call (MOUSEPAD_DBUS_INTERFACE, MOUSEPAD_DBUS_PATH,
+ MOUSEPAD_DBUS_INTERFACE, "LaunchFiles");
+ dbus_message_set_auto_start (message, FALSE);
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &working_directory,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &filenames, length,
+ DBUS_TYPE_INVALID);
+
+ /* send the message */
+ succeed = mousepad_dbus_client_send (message, error);
+
+ /* unref the message */
+ dbus_message_unref (message);
+
+ return succeed;
+}
+
+
+
+/* include the dbus glue generated by dbus-binding-tool */
+#include <mousepad/mousepad-dbus-infos.h>
diff --git a/mousepad/mousepad-dbus.h b/mousepad/mousepad-dbus.h
index 50e5866..d02bef6 100644
--- a/mousepad/mousepad-dbus.h
+++ b/mousepad/mousepad-dbus.h
@@ -25,19 +25,20 @@ typedef struct _MousepadDBusService MousepadDBusService;
#include <mousepad/mousepad-application.h>
-#define MOUSEPAD_TYPE_DBUS_SERVICE (mousepad_dbus_service_get_type ())
-#define MOUSEPAD_DBUS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusService))
-#define MOUSEPAD_DBUS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusServiceClass))
-#define MOUSEPAD_IS_DBUS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_DBUS_SERVICE))
-#define MOUSEPAD_IS_DBUS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOUSEPAD_TYPE_DBUS_BRIGDE))
-#define MOUSEPAD_DBUS_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusServiceClass))
-
-GType mousepad_dbus_service_get_type (void) G_GNUC_CONST;
-
-gboolean
-mousepad_dbus_client_launch_files (gchar **filenames,
- const gchar *working_directory,
- GError **error);
+#define MOUSEPAD_TYPE_DBUS_SERVICE (mousepad_dbus_service_get_type ())
+#define MOUSEPAD_DBUS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusService))
+#define MOUSEPAD_DBUS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusServiceClass))
+#define MOUSEPAD_IS_DBUS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MOUSEPAD_TYPE_DBUS_SERVICE))
+#define MOUSEPAD_IS_DBUS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOUSEPAD_TYPE_DBUS_BRIGDE))
+#define MOUSEPAD_DBUS_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOUSEPAD_TYPE_DBUS_SERVICE, MousepadDBusServiceClass))
+
+GType mousepad_dbus_service_get_type (void) G_GNUC_CONST;
+
+gboolean mousepad_dbus_client_terminate (GError **error);
+
+gboolean mousepad_dbus_client_launch_files (gchar **filenames,
+ const gchar *working_directory,
+ GError **error);
G_END_DECLS
diff --git a/mousepad/mousepad-dialogs.c b/mousepad/mousepad-dialogs.c
new file mode 100644
index 0000000..dbd9f5c
--- /dev/null
+++ b/mousepad/mousepad-dialogs.c
@@ -0,0 +1,333 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * 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., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mousepad/mousepad-private.h>
+#include <mousepad/mousepad-file.h>
+
+
+
+static GtkWidget *
+mousepad_dialogs_image_button (const gchar *stock_id,
+ const gchar *label)
+{
+ GtkWidget *button, *image;
+
+ image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
+ gtk_widget_show (image);
+
+ button = gtk_button_new_with_mnemonic (label);
+ gtk_button_set_image (GTK_BUTTON (button), image);
+ gtk_widget_show (button);
+
+ return button;
+}
+
+
+
+void
+mousepad_dialogs_show_about (GtkWindow *parent)
+{
+ static const gchar *authors[] =
+ {
+ "Erik Harrison <erikharrison at xfce.org>",
+ "Nick Schermer <nick at xfce.org>",
+ "Benedikt Meurer <benny at xfce.org>",
+ NULL,
+ };
+
+ /* show the dialog */
+ gtk_about_dialog_set_email_hook (exo_url_about_dialog_hook, NULL, NULL);
+ gtk_about_dialog_set_url_hook (exo_url_about_dialog_hook, NULL, NULL);
+ gtk_show_about_dialog (parent,
+ "authors", authors,
+ "comments", _("Mousepad is a fast text editor for the Xfce Desktop Environment."),
+ "copyright", _("Copyright \302\251 2004-2007 Xfce Development Team"),
+ "destroy-with-parent", TRUE,
+ "license", XFCE_LICENSE_GPL,
+ "logo-icon-name", PACKAGE_NAME,
+ "name", PACKAGE_NAME,
+ "version", PACKAGE_VERSION,
+ "translator-credits", _("translator-credits"),
+ "website", "http://www.xfce.org/projects/mousepad",
+ NULL);
+}
+
+
+
+void
+mousepad_dialogs_show_error (GtkWindow *parent,
+ const GError *error,
+ const gchar *message)
+{
+ GtkWidget *dialog;
+
+ /* create the warning dialog */
+ dialog = gtk_message_dialog_new (parent,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_CLOSE,
+ "%s.", message);
+
+ /* set secondary text if an error is provided */
+ if (G_LIKELY (error != NULL))
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s.", error->message);
+
+ /* display the dialog */
+ gtk_dialog_run (GTK_DIALOG (dialog));
+
+ /* cleanup */
+ gtk_widget_destroy (dialog);
+}
+
+
+
+gint
+mousepad_dialogs_jump_to (GtkWindow *parent,
+ gint current_line,
+ gint last_line)
+{
+ GtkWidget *dialog;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ GtkWidget *button;
+ GtkAdjustment *adjustment;
+ gint line_number = 0;
+
+ /* build the dialog */
+ dialog = gtk_dialog_new_with_buttons (_("Jump To"),
+ parent,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_JUMP_TO, GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+
+ hbox = gtk_hbox_new (FALSE, 8);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
+ gtk_widget_show (hbox);
+
+ label = gtk_label_new_with_mnemonic (_("_Line number:"));
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show (label);
+
+ /* the spin button adjustment */
+ adjustment = (GtkAdjustment *) gtk_adjustment_new (current_line, 1, last_line, 1, 10, 0);
+
+ /* the spin button */
+ button = gtk_spin_button_new (adjustment, 1, 0);
+ gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (button), TRUE);
+ gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (button), TRUE);
+ gtk_entry_set_width_chars (GTK_ENTRY (button), 8);
+ gtk_entry_set_activates_default (GTK_ENTRY (button), TRUE);
+ gtk_label_set_mnemonic_widget (GTK_LABEL(label), button);
+ gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+ gtk_widget_show (button);
+
+ /* run the dialog */
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ line_number = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (button));
+
+ /* destroy the dialog */
+ gtk_widget_destroy (dialog);
+
+ return line_number;
+}
+
+
+
+gboolean
+mousepad_dialogs_clear_recent (GtkWindow *parent)
+{
+ GtkWidget *dialog;
+ gboolean succeed = FALSE;
+
+ dialog = gtk_message_dialog_new (parent,
+ 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);
+
+ /* popup the dialog */
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ succeed = TRUE;
+
+ /* destroy the dialog */
+ gtk_widget_destroy (dialog);
+
+ return succeed;
+}
+
+
+
+gboolean
+mousepad_dialogs_save_changes (GtkWindow *parent)
+{
+ GtkWidget *dialog;
+ gint response;
+
+ /* create the question dialog */
+ dialog = gtk_message_dialog_new (parent,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("Do you want to save changes to this\n"
+ "document before closing?"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("If you don't save, your changes will be lost."));
+
+ gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
+ mousepad_dialogs_image_button (GTK_STOCK_DELETE, _("_Don't Save")),
+ GTK_RESPONSE_REJECT);
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ /* run the dialog and wait for a response */
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ /* destroy the dialog */
+ gtk_widget_destroy (dialog);
+
+ return response;
+}
+
+
+
+static GtkFileChooserConfirmation
+mousepad_dialogs_save_as_callback (GtkFileChooser *dialog)
+{
+ gchar *filename;
+ GError *error = NULL;
+ GtkFileChooserConfirmation result;
+
+ /* get the filename */
+ filename = gtk_file_chooser_get_filename (dialog);
+
+ if (mousepad_file_is_writable (filename, &error))
+ {
+ /* show the normal confirmation dialog */
+ result = GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM;
+ }
+ else
+ {
+ /* tell the user he cannot write to this file */
+ mousepad_dialogs_show_error (GTK_WINDOW (dialog), error, _("Permission denied"));
+ g_error_free (error);
+
+ /* the user doesn't have permission to write to the file */
+ result = GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN;
+ }
+
+ /* cleanup */
+ g_free (filename);
+
+ return result;
+}
+
+
+
+gchar *
+mousepad_dialogs_save_as (GtkWindow *parent,
+ const gchar *filename)
+{
+ gchar *new_filename = NULL;
+ GtkWidget *dialog;
+
+ dialog = gtk_file_chooser_dialog_new (_("Save As"),
+ parent,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_OK,
+ NULL);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ /* we check if the user is allowed to write to the file */
+ g_signal_connect (G_OBJECT (dialog), "confirm-overwrite",
+ G_CALLBACK (mousepad_dialogs_save_as_callback), NULL);
+
+ /* set the current filename */
+ if (filename != NULL)
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), filename);
+
+ /* run the dialog */
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ new_filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+ /* destroy the dialog */
+ gtk_widget_destroy (dialog);
+
+ return new_filename;
+}
+
+
+
+gboolean
+mousepad_dialogs_ask_overwrite (GtkWindow *parent,
+ const gchar *filename)
+{
+ GtkWidget *dialog;
+ gboolean overwrite = FALSE;
+
+ dialog = gtk_message_dialog_new (parent,
+ GTK_DIALOG_MODAL
+ | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("The file has been externally modified. Are you sure "
+ "you want to save the file?"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ _("If you save the file, the external changes "
+ "to \"%s\" will be lost."), filename);
+
+ gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+ gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
+ mousepad_dialogs_image_button (GTK_STOCK_SAVE, _("_Overwrite")),
+ GTK_RESPONSE_OK);
+ gtk_dialog_add_action_widget (GTK_DIALOG (dialog),
+ mousepad_dialogs_image_button (GTK_STOCK_REFRESH, _("_Reload")),
+ GTK_RESPONSE_REJECT);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ overwrite = TRUE;
+
+ gtk_widget_destroy (dialog);
+
+ return overwrite;
+}
diff --git a/mousepad/mousepad-dialogs.h b/mousepad/mousepad-dialogs.h
new file mode 100644
index 0000000..b6f0310
--- /dev/null
+++ b/mousepad/mousepad-dialogs.h
@@ -0,0 +1,48 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2007 Nick Schermer <nick at xfce.org>
+ *
+ * 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., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __MOUSEPAD_DIALOGS_H__
+#define __MOUSEPAD_DIALOGS_H__
+
+G_BEGIN_DECLS
+
+void mousepad_dialogs_show_about (GtkWindow *parent);
+
+
+void mousepad_dialogs_show_error (GtkWindow *parent,
+ const GError *error,
+ const gchar *message);
+
+gint mousepad_dialogs_jump_to (GtkWindow *parent,
+ gint current_line,
+ gint last_line);
+
+gboolean mousepad_dialogs_clear_recent (GtkWindow *parent);
+
+gint mousepad_dialogs_save_changes (GtkWindow *parent);
+
+gchar *mousepad_dialogs_save_as (GtkWindow *parent,
+ const gchar *filename);
+
+gboolean mousepad_dialogs_ask_overwrite (GtkWindow *parent,
+ const gchar *filename);
+
+G_END_DECLS
+
+#endif /* !__MOUSEPAD_DIALOGS_H__ */
diff --git a/mousepad/mousepad-file.c b/mousepad/mousepad-file.c
index 6854fa6..389ee6e 100644
--- a/mousepad/mousepad-file.c
+++ b/mousepad/mousepad-file.c
@@ -54,25 +54,31 @@
#include <mousepad/mousepad-file.h>
-
+/**
+ * mousepad_file_get_externally_modified:
+ * @filename : The filename we're going to check.
+ * @mtime : The last modification time of the document.
+ *
+ * Returns whether a file has been modified after @mtime. If
+ * no file was found it returns %FALSE.
+ *
+ * Return value: %TRUE is the file exists and has been modified.
+ **/
gboolean
-mousepad_file_get_externally_modified (const gchar *filename,
- gint mtime,
- GError **error)
+mousepad_file_get_externally_modified (const gchar *filename,
+ gint mtime)
{
gint fd;
struct stat statb;
gboolean modified = FALSE;
- _mousepad_return_val_if_fail (filename != NULL, FALSE);
- _mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ _mousepad_return_val_if_fail (filename != NULL, TRUE);
/* open the file for reading */
fd = open (filename, O_RDONLY);
if (G_UNLIKELY (fd < 0))
{
- g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO,
- _("Failed to open \"%s\" for reading"), filename);
+ /* files probably doesn't exists, so we can safely write */
return FALSE;
}
@@ -88,6 +94,21 @@ mousepad_file_get_externally_modified (const gchar *filename,
+/**
+ * mousepad_file_save_data:
+ * @filename : The filename of the document.
+ * @data : The content of the editor. This string should
+ * already been converted to the correct encoding.
+ * @bytes : The length of @data.
+ * @new_mtime : Return location for the file's modification
+ * time after a succesfull write.
+ * @error : Return location for errors or %NULL.
+ *
+ * Try to save the @data to @filename. This function does not
+ * check if the document has been modified externally.
+ *
+ * Return value: %TRUE on success, %FALSE if @error is set.
+ **/
gboolean
mousepad_file_save_data (const gchar *filename,
const gchar *data,
@@ -188,6 +209,26 @@ failed:
+/**
+ * mousepad_file_read_to_buffer:
+ * @filename : The filename of the destination file.
+ * @buffer : A #GtkTextBuffer where we can insert the
+ * content of @filename.
+ * @new_mtime : Return location of the file's modification time
+ * after a succesfull read.
+ * @readonly : Return location if we're only allowed to write
+ * the file. %TRUE if the user is not allowed to write
+ * to the file.
+ * @error : Return location of errors or %NULL.
+ *
+ * This function reads the content of a file and inserts it directly
+ * in a #GtkTextBuffer. We don't return a string to avoid string duplication.
+ *
+ * If the user has support for MMAP and the size of the file is below 8MB, we
+ * use MMAP to speedup the file reading a bit.
+ *
+ * Return value: %TRUE on success, %FALSE if @error is set.
+ **/
gboolean
mousepad_file_read_to_buffer (const gchar *filename,
GtkTextBuffer *buffer,
@@ -280,6 +321,18 @@ failed:
+/**
+ * mousepad_file_is_writable:
+ * @filename : The filename to check.
+ * @error : Return location of errors or %NULL.
+ *
+ * Check if a user is allowed to write to a file. This function
+ * is used in the save as dialog to warn the user if he or she
+ * has permissions to write (before actually closing the
+ * dialog).
+ *
+ * Return value: %TRUE is the user is allowed to write the @filename.
+ **/
gboolean
mousepad_file_is_writable (const gchar *filename,
GError **error)
diff --git a/mousepad/mousepad-file.h b/mousepad/mousepad-file.h
index cabfda8..8ffcfd4 100644
--- a/mousepad/mousepad-file.h
+++ b/mousepad/mousepad-file.h
@@ -22,24 +22,23 @@
G_BEGIN_DECLS
-gboolean mousepad_file_get_externally_modified (const gchar *filename,
- gint mtime,
- GError **error);
-
-gboolean mousepad_file_save_data (const gchar *filename,
- const gchar *data,
- gsize bytes,
- gint *new_mtime,
- GError **error);
-
-gboolean mousepad_file_read_to_buffer (const gchar *filename,
- GtkTextBuffer *buffer,
- gint *new_mtime,
- gboolean *readonly,
- GError **error);
-
-gboolean mousepad_file_is_writable (const gchar *filename,
- GError **error);
+gboolean mousepad_file_get_externally_modified (const gchar *filename,
+ gint mtime);
+
+gboolean mousepad_file_save_data (const gchar *filename,
+ const gchar *data,
+ gsize bytes,
+ gint *new_mtime,
+ GError **error);
+
+gboolean mousepad_file_read_to_buffer (const gchar *filename,
+ GtkTextBuffer *buffer,
+ gint *new_mtime,
+ gboolean *readonly,
+ GError **error);
+
+gboolean mousepad_file_is_writable (const gchar *filename,
+ GError **error);
G_END_DECLS
diff --git a/mousepad/mousepad-preferences.c b/mousepad/mousepad-preferences.c
index c3707c6..c5ec45f 100644
--- a/mousepad/mousepad-preferences.c
+++ b/mousepad/mousepad-preferences.c
@@ -80,7 +80,7 @@ static void mousepad_preferences_set_property (GObject
const GValue *value,
GParamSpec *pspec);
static void mousepad_preferences_queue_store (MousepadPreferences *preferences);
-static gboolean mousepad_preferences_load_idle (gpointer user_data);
+static gboolean mousepad_preferences_load (MousepadPreferences *preferences);
static gboolean mousepad_preferences_store_idle (gpointer user_data);
static void mousepad_preferences_store_idle_destroy (gpointer user_data);
@@ -93,10 +93,10 @@ struct _MousepadPreferences
{
GObject __parent__;
+ /* all the properties stored in the Object */
GValue values[N_PROPERTIES];
- gboolean loading_in_progress;
-
+ /* idle save timer id */
gint store_idle_id;
};
@@ -105,7 +105,14 @@ struct _MousepadPreferences
static GObjectClass *mousepad_preferences_parent_class;
-
+/**
+ * transform_string_to_boolean:
+ * @const GValue : String #GValue.
+ * @GValue : Return location for a #GValue boolean.
+ *
+ * Converts a string into a boolean. This is used when
+ * converting the XfceRc values.
+ **/
static void
transform_string_to_boolean (const GValue *src,
GValue *dst)
@@ -115,6 +122,13 @@ transform_string_to_boolean (const GValue *src,
+/**
+ * transform_string_to_int:
+ * @const GValue : String #GValue.
+ * @GValue : Return location for a #GValue integer.
+ *
+ * Converts a string into a number.
+ **/
static void
transform_string_to_int (const GValue *src,
GValue *dst)
@@ -164,6 +178,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
if (!g_value_type_transformable (G_TYPE_STRING, G_TYPE_INT))
g_value_register_transform_func (G_TYPE_STRING, G_TYPE_INT, transform_string_to_int);
+ /**
+ * MousepadPreferences:auto-indent
+ *
+ * Whether line identation is enabled.
+ **/
g_object_class_install_property (gobject_class,
PROP_AUTO_INDENT,
g_param_spec_boolean ("auto-indent",
@@ -172,6 +191,12 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
FALSE,
EXO_PARAM_READWRITE));
+ /**
+ * MousepadPreferences:font-name
+ *
+ * The font name and size used in the text view. If this value is
+ * %NULL, the system font will be used.
+ **/
g_object_class_install_property (gobject_class,
PROP_FONT_NAME,
g_param_spec_string ("font-name",
@@ -180,6 +205,12 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
NULL,
EXO_PARAM_READWRITE));
+ /**
+ * MousepadPreferences:last-window-height
+ *
+ * The last known height of a #MousepadWindow, which will be used as
+ * default height for newly created windows.
+ **/
g_object_class_install_property (gobject_class,
PROP_LAST_WINDOW_HEIGHT,
g_param_spec_int ("last-window-height",
@@ -188,6 +219,12 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
1, G_MAXINT, 480,
EXO_PARAM_READWRITE));
+ /**
+ * MousepadPreferences:last-window-width
+ *
+ * The last known width of a #MousepadWindow, which will be used as
+ * default width for newly created windows.
+ **/
g_object_class_install_property (gobject_class,
PROP_LAST_WINDOW_WIDTH,
g_param_spec_int ("last-window-width",
@@ -196,6 +233,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
1, G_MAXINT, 640,
EXO_PARAM_READWRITE));
+ /**
+ * MousepadPreferences:line-numbers
+ *
+ * Whether line numbers are visible in the text view.
+ **/
g_object_class_install_property (gobject_class,
PROP_LINE_NUMBERS,
g_param_spec_boolean ("line-numbers",
@@ -204,6 +246,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
FALSE,
EXO_PARAM_READWRITE));
+ /**
+ * MousepadPreferences:statusbar
+ *
+ * Whether to display the statusbar in the Mousepad window.
+ **/
g_object_class_install_property (gobject_class,
PROP_STATUSBAR,
g_param_spec_boolean ("statusbar",
@@ -212,6 +259,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
TRUE,
EXO_PARAM_READWRITE));
+ /**
+ * MousepadPreferences:word-wrap
+ *
+ * Whether word wrapping is enabled.
+ **/
g_object_class_install_property (gobject_class,
PROP_WORD_WRAP,
g_param_spec_boolean ("word-wrap",
@@ -220,6 +272,12 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
FALSE,
EXO_PARAM_READWRITE));
+ /**
+ * MousepadPreferences:misc-always-show-tabs
+ *
+ * Whether tabs are always visible. By default the tabs are hidden
+ * when there is only 1 screen opened.
+ **/
g_object_class_install_property (gobject_class,
PROP_MISC_ALWAYS_SHOW_TABS,
g_param_spec_boolean ("misc-always-show-tabs",
@@ -228,6 +286,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
FALSE,
EXO_PARAM_READWRITE));
+ /**
+ * MousepadPreferences:misc-cycle-tabs
+ *
+ * Whether to cycle tabs with the back and forward buttons in the go menu.
+ **/
g_object_class_install_property (gobject_class,
PROP_MISC_CYCLE_TABS,
g_param_spec_boolean ("misc-cycle-tabs",
@@ -236,6 +299,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
FALSE,
EXO_PARAM_READWRITE));
+ /**
+ * MousepadPreferences:misc-show-full-path-in-title
+ *
+ * Whether to show the full file name path in the window title.
+ **/
g_object_class_install_property (gobject_class,
PROP_MISC_SHOW_FULL_PATH_IN_TITLE,
g_param_spec_boolean ("misc-show-full-path-in-title",
@@ -244,6 +312,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
FALSE,
EXO_PARAM_READWRITE));
+ /**
+ * MousepadPreferences:misc-recent-menu-limit
+ *
+ * The number of items in the recent menu,
+ **/
g_object_class_install_property (gobject_class,
PROP_MISC_RECENT_MENU_LIMIT,
g_param_spec_int ("misc-recent-menu-limit",
@@ -252,6 +325,15 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
1, G_MAXINT, 10,
EXO_PARAM_READWRITE));
+ /**
+ * MousepadPreferences:misc-remember-geometry
+ *
+ * Whether Mousepad should remember the size of windows and apply this
+ * to newly created windows. If %TRUE the width and height are
+ * saved to "last-window-width" and "last-window-height". If
+ * %FALSE the user may specify the start size in "last-window-with"
+ * and "last-window-height".
+ **/
g_object_class_install_property (gobject_class,
PROP_MISC_REMEMBER_GEOMETRY,
g_param_spec_boolean ("misc-remember-geometry",
@@ -260,6 +342,11 @@ mousepad_preferences_class_init (MousepadPreferencesClass *klass)
TRUE,
EXO_PARAM_READWRITE));
+ /**
+ * MousepadPreferences:misc-tab-close-buttons
+ *
+ * Whether the close buttons are visible in the tabs.
+ **/
g_object_class_install_property (gobject_class,
PROP_MISC_TAB_CLOSE_BUTTONS,
g_param_spec_boolean ("misc-tab-close-buttons",
@@ -275,7 +362,7 @@ static void
mousepad_preferences_init (MousepadPreferences *preferences)
{
/* load the settings */
- mousepad_preferences_load_idle (preferences);
+ mousepad_preferences_load (preferences);
}
@@ -345,7 +432,7 @@ mousepad_preferences_set_property (GObject *object,
static void
mousepad_preferences_queue_store (MousepadPreferences *preferences)
{
- if (preferences->store_idle_id == 0 && !preferences->loading_in_progress)
+ if (preferences->store_idle_id == 0)
{
preferences->store_idle_id = g_idle_add_full (G_PRIORITY_LOW, mousepad_preferences_store_idle,
preferences, mousepad_preferences_store_idle_destroy);
@@ -387,23 +474,22 @@ property_name_to_option_name (const gchar *property_name)
static gboolean
-mousepad_preferences_load_idle (gpointer user_data)
+mousepad_preferences_load (MousepadPreferences *preferences)
{
- MousepadPreferences *preferences = MOUSEPAD_PREFERENCES (user_data);
- const gchar *string;
- GParamSpec **specs;
- GParamSpec *spec;
- XfceRc *rc;
- GValue dst = { 0, };
- GValue src = { 0, };
- gchar *option;
- guint nspecs;
- guint n;
+ const gchar *string;
+ GParamSpec **specs;
+ GParamSpec *spec;
+ XfceRc *rc;
+ GValue dst = { 0, };
+ GValue src = { 0, };
+ gchar *option;
+ guint nspecs;
+ guint n;
rc = xfce_rc_config_open (XFCE_RESOURCE_CONFIG, "Mousepad/mousepadrc", TRUE);
if (G_UNLIKELY (rc == NULL))
{
- g_warning ("Failed to load mousepad preferences.");
+ g_warning ("Failed to load the preferences. Unable to open \"~/.config/Mousepad/mousepadrc\"");
return FALSE;
}
@@ -411,8 +497,6 @@ mousepad_preferences_load_idle (gpointer user_data)
xfce_rc_set_group (rc, "Configuration");
- preferences->loading_in_progress = TRUE;
-
specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (preferences), &nspecs);
for (n = 0; n < nspecs; ++n)
@@ -449,8 +533,6 @@ mousepad_preferences_load_idle (gpointer user_data)
}
g_free (specs);
- preferences->loading_in_progress = FALSE;
-
xfce_rc_close (rc);
g_object_thaw_notify (G_OBJECT (preferences));
@@ -477,7 +559,7 @@ mousepad_preferences_store_idle (gpointer user_data)
rc = xfce_rc_config_open (XFCE_RESOURCE_CONFIG, "Mousepad/mousepadrc", FALSE);
if (G_UNLIKELY (rc == NULL))
{
- g_warning ("Failed to store mousepad preferences.");
+ g_warning ("Failed to store the preferences. Unable to open \"~/.config/Mousepad/mousepadrc\"");
return FALSE;
}
@@ -533,6 +615,16 @@ mousepad_preferences_store_idle_destroy (gpointer user_data)
+/**
+ * mousepad_preferences_get:
+ *
+ * Queries the global #MousepadPreferences instance, which is shared
+ * by all modules. The function automatically takes a reference
+ * for the caller, so you'll need to call g_object_unref() when
+ * you're done with it.
+ *
+ * Return value: the global #MousepadPreferences instance.
+ **/
MousepadPreferences*
mousepad_preferences_get (void)
{
diff --git a/mousepad/mousepad-screen.c b/mousepad/mousepad-screen.c
index 4e281b7..1ac53a3 100644
--- a/mousepad/mousepad-screen.c
+++ b/mousepad/mousepad-screen.c
@@ -458,6 +458,7 @@ mousepad_screen_open_file (MousepadScreen *screen,
gboolean
mousepad_screen_save_file (MousepadScreen *screen,
+ const gchar *filename,
GError **error)
{
gchar *content;
@@ -470,7 +471,7 @@ mousepad_screen_save_file (MousepadScreen *screen,
_mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
_mousepad_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- _mousepad_return_val_if_fail (screen->filename != NULL, FALSE);
+ _mousepad_return_val_if_fail (filename != NULL, FALSE);
/* get the buffer */
buffer = mousepad_screen_get_text_buffer (screen);
@@ -495,7 +496,7 @@ mousepad_screen_save_file (MousepadScreen *screen,
if (G_LIKELY (converted != NULL))
{
- succeed = mousepad_file_save_data (screen->filename, converted, bytes,
+ succeed = mousepad_file_save_data (filename, converted, bytes,
&new_mtime, error);
/* cleanup */
@@ -553,18 +554,11 @@ mousepad_screen_get_filename (MousepadScreen *screen)
gboolean
-mousepad_screen_get_externally_modified (MousepadScreen *screen,
- GError **error)
+mousepad_screen_get_mtime (MousepadScreen *screen)
{
- gboolean modified;
-
_mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
- _mousepad_return_val_if_fail (screen->filename != NULL, FALSE);
-
- /* check if the file has been modified */
- modified = mousepad_file_get_externally_modified (screen->filename, screen->mtime, error);
- return modified;
+ return screen->mtime;
}
diff --git a/mousepad/mousepad-screen.h b/mousepad/mousepad-screen.h
index 9017424..c7274bc 100644
--- a/mousepad/mousepad-screen.h
+++ b/mousepad/mousepad-screen.h
@@ -46,6 +46,7 @@ gboolean mousepad_screen_open_file (MousepadScreen *scree
GError **error);
gboolean mousepad_screen_save_file (MousepadScreen *screen,
+ const gchar *filename,
GError **error);
const gchar *mousepad_screen_get_title (MousepadScreen *screen,
@@ -53,8 +54,7 @@ const gchar *mousepad_screen_get_title (MousepadScreen *scree
const gchar *mousepad_screen_get_filename (MousepadScreen *screen);
-gboolean mousepad_screen_get_externally_modified (MousepadScreen *screen,
- GError **error);
+gboolean mousepad_screen_get_mtime (MousepadScreen *screen);
GtkTextView *mousepad_screen_get_text_view (MousepadScreen *screen);
diff --git a/mousepad/mousepad-view.c b/mousepad/mousepad-view.c
index d4f3ce0..b0c181d 100644
--- a/mousepad/mousepad-view.c
+++ b/mousepad/mousepad-view.c
@@ -32,25 +32,25 @@
-static void mousepad_view_class_init (MousepadViewClass *klass);
-static void mousepad_view_init (MousepadView *view);
-static void mousepad_view_finalize (GObject *object);
-static gboolean mousepad_view_key_press_event (GtkWidget *widget,
- GdkEventKey *event);
-static void mousepad_view_indent_lines (MousepadView *view,
- GtkTextIter *start,
- GtkTextIter *end,
- gboolean indent);
-static gchar *mousepad_view_compute_indentation (MousepadView *view,
- GtkTextIter *iter);
-static gint mousepad_view_expose (GtkWidget *widget,
- GdkEventExpose *event);
-static void mousepad_view_get_lines (GtkTextView *text_view,
- gint first_y,
- gint last_y,
- GArray **pixels,
- GArray **numbers,
- gint *countp);
+static void mousepad_view_class_init (MousepadViewClass *klass);
+static void mousepad_view_init (MousepadView *view);
+static void mousepad_view_finalize (GObject *object);
+static gboolean mousepad_view_key_press_event (GtkWidget *widget,
+ GdkEventKey *event);
+static void mousepad_view_indent_lines (MousepadView *view,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ gboolean indent);
+static gchar *mousepad_view_compute_indentation (MousepadView *view,
+ GtkTextIter *iter);
+static gint mousepad_view_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static void mousepad_view_get_lines (GtkTextView *text_view,
+ gint first_y,
+ gint last_y,
+ GArray **pixels,
+ GArray **numbers,
+ gint *countp);
@@ -63,6 +63,7 @@ struct _MousepadView
{
GtkTextView __parent__;
+ /* settings */
gboolean auto_indent;
gboolean line_numbers;
};
@@ -128,6 +129,18 @@ mousepad_view_finalize (GObject *object)
+/**
+ * mousepad_view_key_press_event:
+ * @widget : A #GtkWidget.
+ * @event : A #GdkEventKey
+ *
+ * This function is triggered when the user pressed a key in the
+ * #MousepadView. It checks if we need to auto indent the new line
+ * or when multiple lines are selected we (un)indent all of them.
+ *
+ * Return value: %TRUE if we handled the event, else we trigger the
+ * parent class so Gtk can handle the event.
+ **/
static gboolean
mousepad_view_key_press_event (GtkWidget *widget,
GdkEventKey *event)
@@ -210,6 +223,18 @@ mousepad_view_key_press_event (GtkWidget *widget,
+/**
+ * mousepad_view_indent_lines:
+ * @view : A #MousepadView
+ * @start : The start #GtkTextIter of the selection.
+ * @end : The end #GtkTextIter of the selection
+ * @indent : Whether we need to indent or unindent the
+ * selected lines.
+ *
+ * This function (un)indents the selected lines. It simply walks
+ * from the start line number to the end line number and prepends
+ * or removed a tab (or the tab width in spaces).
+ **/
static void
mousepad_view_indent_lines (MousepadView *view,
GtkTextIter *start,
@@ -309,6 +334,19 @@ mousepad_view_indent_lines (MousepadView *view,
+/**
+ * mousepad_view_compute_indentation:
+ * @view : A #MousepadView.
+ * @iter : The #GtkTextIter of the previous line.
+ *
+ * This function is used to get the tabs and spaces we need to
+ * append when auto indentation is enabled. If scans the line of
+ * @iter and returns a slice of the tabs and spaces before the
+ * first character or line end.
+ *
+ * Return value: A string of tabs and spaces or %NULL when the
+ * previous line has no tabs or spaces before the text.
+ **/
static gchar *
mousepad_view_compute_indentation (MousepadView *view,
GtkTextIter *iter)
@@ -356,6 +394,21 @@ mousepad_view_compute_indentation (MousepadView *view,
+/**
+ * mousepad_view_get_lines:
+ * @text_view : A #GtkTextView
+ * @first_y : The first y location of the visible #GtkTextView window.
+ * @last_y : The last y location of the visible #GtkTextView window.
+ * @pixels : Return location for the #GArray with the y location
+ * in pixels we need to draw line numbers.
+ * @numbers : Return location for the #GArray with all the visible
+ * line numbers.
+ * @countp : Return location for the number of lines visible between
+ * @first_y and @last_y.
+ *
+ * This function returns two arrays with the lines number and there draw
+ * location of the visible text view window.
+ **/
static void
mousepad_view_get_lines (GtkTextView *text_view,
gint first_y,
@@ -428,6 +481,17 @@ mousepad_view_get_lines (GtkTextView *text_view,
+/**
+ * mousepad_view_expose:
+ * @widget : A textview widget.
+ * @event : A #GdkEventExpose event.
+ *
+ * This function draws the line numbers in the GTK_TEXT_WINDOW_LEFT window
+ * when it receives an expose event. At the end of the function we always
+ * return the expose_event of the parent class so Gtk can draw the text.
+ *
+ * Return value: The return value of the parent_class.
+ **/
static gboolean
mousepad_view_expose (GtkWidget *widget,
GdkEventExpose *event)
@@ -520,6 +584,14 @@ mousepad_view_expose (GtkWidget *widget,
+/**
+ * mousepad_view_set_show_line_numbers:
+ * @view : A #MousepadView
+ * @visible : Boolean whether we show or hide the line
+ * numbers.
+ *
+ * Whether line numbers are visible in the @view.
+ **/
void
mousepad_view_set_show_line_numbers (MousepadView *view,
gboolean visible)
@@ -543,6 +615,14 @@ mousepad_view_set_show_line_numbers (MousepadView *view,
+/**
+ * mousepad_view_set_auto_indent:
+ * @view : A #MousepadView
+ * @visible : Boolean whether we enable or disable
+ * auto indentation.
+ *
+ * Whether we enable auto indentation.
+ **/
void
mousepad_view_set_auto_indent (MousepadView *view,
gboolean enable)
diff --git a/mousepad/mousepad-window.c b/mousepad/mousepad-window.c
index 126fa88..b5bf592 100644
--- a/mousepad/mousepad-window.c
+++ b/mousepad/mousepad-window.c
@@ -25,11 +25,15 @@
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <mousepad/mousepad-application.h>
+#include <mousepad/mousepad-dialogs.h>
#include <mousepad/mousepad-preferences.h>
#include <mousepad/mousepad-private.h>
#include <mousepad/mousepad-file.h>
@@ -41,12 +45,15 @@
+/* class functions */
static void mousepad_window_class_init (MousepadWindowClass *klass);
static void mousepad_window_init (MousepadWindow *window);
static void mousepad_window_dispose (GObject *object);
static void mousepad_window_finalize (GObject *object);
static gboolean mousepad_window_configure_event (GtkWidget *widget,
GdkEventConfigure *event);
+
+/* statusbar tooltips */
static void mousepad_window_connect_proxy (GtkUIManager *manager,
GtkAction *action,
GtkWidget *proxy,
@@ -59,25 +66,24 @@ static void mousepad_window_menu_item_selected (GtkWidget
MousepadWindow *window);
static void mousepad_window_menu_item_deselected (GtkWidget *menu_item,
MousepadWindow *window);
+
+/* save windows geometry */
static gboolean mousepad_window_save_geometry_timer (gpointer user_data);
static void mousepad_window_save_geometry_timer_destroy (gpointer user_data);
+
+/* window functions */
static MousepadScreen *mousepad_window_get_active (MousepadWindow *window);
-static gboolean mousepad_window_save_as (MousepadWindow *window,
- MousepadScreen *screen);
+static gboolean mousepad_window_save (MousepadWindow *window,
+ MousepadScreen *screen,
+ gboolean force_save_as);
static void mousepad_window_add (MousepadWindow *window,
MousepadScreen *screen);
static gboolean mousepad_window_close_screen (MousepadWindow *window,
MousepadScreen *screen);
-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,
- GParamSpec *pspec,
- MousepadWindow *window);
+
+/* notebook signals */
static void mousepad_window_page_notified (GtkNotebook *notebook,
GParamSpec *pspec,
MousepadWindow *window);
@@ -88,14 +94,30 @@ static void mousepad_window_page_reordered (GtkNotebo
GtkNotebookPage *page,
guint page_num,
MousepadWindow *window);
-static void mousepad_window_error_dialog (GtkWindow *window,
- GError *error,
- const gchar *message);
-static void mousepad_window_update_actions (MousepadWindow *window);
-static void mousepad_window_go_menu (MousepadWindow *window);
+
+/* screen signals */
+static void mousepad_window_notify_title (MousepadScreen *screen,
+ GParamSpec *pspec,
+ MousepadWindow *window);
+static void mousepad_window_modified_changed (MousepadScreen *screen,
+ MousepadWindow *window);
static void mousepad_window_selection_changed (MousepadScreen *screen,
gboolean selected,
MousepadWindow *window);
+
+/* menu updaters */
+static void mousepad_window_update_actions (MousepadWindow *window);
+static void mousepad_window_update_gomenu (MousepadWindow *window);
+
+/* recent functions */
+static void mousepad_window_recent_add (MousepadWindow *window,
+ const gchar *filename);
+static gint mousepad_window_recent_sort (GtkRecentInfo *a,
+ GtkRecentInfo *b);
+static void mousepad_window_recent_menu (MousepadWindow *window);
+static void mousepad_window_recent_clear (MousepadWindow *window);
+
+/* actions */
static void mousepad_window_action_open_new_window (GtkAction *action,
MousepadWindow *window);
static void mousepad_window_action_open_file (GtkAction *action,
@@ -110,9 +132,6 @@ static void mousepad_window_action_save_file_as (GtkAction
MousepadWindow *window);
static void mousepad_window_action_close_tab (GtkAction *action,
MousepadWindow *window);
-static void mousepad_window_button_close_tab (MousepadScreen *screen);
-static gboolean mousepad_window_delete_event (MousepadWindow *window,
- GdkEvent *event);
static void mousepad_window_action_close (GtkAction *action,
MousepadWindow *window);
static void mousepad_window_action_close_all_windows (GtkAction *action,
@@ -137,9 +156,16 @@ static void mousepad_window_action_prev_tab (GtkAction
MousepadWindow *window);
static void mousepad_window_action_next_tab (GtkAction *action,
MousepadWindow *window);
+static void mousepad_window_action_goto (GtkRadioAction *action,
+ GtkNotebook *notebook);
static void mousepad_window_action_about (GtkAction *action,
MousepadWindow *window);
+/* miscellaneous actions */
+static void mousepad_window_button_close_tab (MousepadScreen *screen);
+static gboolean mousepad_window_delete_event (MousepadWindow *window,
+ GdkEvent *event);
+
@@ -346,7 +372,7 @@ mousepad_window_init (MousepadWindow *window)
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);
+ G_CALLBACK (mousepad_window_recent_menu), window);
/* create the recent menu */
mousepad_window_recent_menu (window);
@@ -488,6 +514,9 @@ mousepad_window_configure_event (GtkWidget *widget,
+/**
+ * Statusbar Tooltip Functions
+ **/
static void
mousepad_window_connect_proxy (GtkUIManager *manager,
GtkAction *action,
@@ -566,6 +595,9 @@ mousepad_window_menu_item_deselected (GtkWidget *menu_item,
+/**
+ * Save Geometry Functions
+ **/
static gboolean
mousepad_window_save_geometry_timer (gpointer user_data)
{
@@ -616,6 +648,9 @@ mousepad_window_save_geometry_timer_destroy (gpointer user_data)
+/**
+ * Mousepad Window Functions
+ **/
static MousepadScreen *
mousepad_window_get_active (MousepadWindow *window)
{
@@ -671,19 +706,22 @@ mousepad_window_open_tab (MousepadWindow *window,
/* new screen */
screen = mousepad_screen_new ();
- /* load a file, if there is any */
if (filename)
+ /* load the file content in the screen */
succeed = mousepad_screen_open_file (MOUSEPAD_SCREEN (screen), filename, &error);
if (G_LIKELY (succeed))
- mousepad_window_add (window, MOUSEPAD_SCREEN (screen));
+ {
+ /* add the screen to the notebook and connect some signals */
+ mousepad_window_add (window, MOUSEPAD_SCREEN (screen));
+ }
else
{
/* something went wrong, remove the screen */
gtk_widget_destroy (GTK_WIDGET (screen));
/* show the warning */
- mousepad_window_error_dialog (GTK_WINDOW (window), error, _("Failed to open file"));
+ mousepad_dialogs_show_error (GTK_WINDOW (window), error, _("Failed to open file"));
g_error_free (error);
}
@@ -712,7 +750,7 @@ mousepad_window_open_files (MousepadWindow *window,
for (n = 0; filenames[n] != NULL; ++n)
{
/* check if the filename looks like an uri */
- if (g_strstr_len (filenames[n], 5, "file:"))
+ if (strncmp (filenames[n], "file:", 5) == 0)
{
/* convert the uri to an absolute filename */
filename = g_filename_from_uri (filenames[n], NULL, NULL);
@@ -736,95 +774,76 @@ mousepad_window_open_files (MousepadWindow *window,
/* update the menus */
mousepad_window_recent_menu (window);
- mousepad_window_go_menu (window);
+ mousepad_window_update_gomenu (window);
}
-static GtkFileChooserConfirmation
-mousepad_window_save_as_callback (GtkFileChooser *dialog)
+static gboolean
+mousepad_window_save (MousepadWindow *window,
+ MousepadScreen *screen,
+ gboolean force_save_as)
{
- gchar *filename;
- GError *error = NULL;
- GtkFileChooserConfirmation result;
+ gchar *new_filename = NULL;
+ const gchar *filename;
+ gboolean succeed = FALSE;
+ GError *error = NULL;
+ const gchar *message;
+ gint mtime;
- /* get the filename */
- filename = gtk_file_chooser_get_filename (dialog);
+ /* get the current filename */
+ filename = mousepad_screen_get_filename (screen);
- if (mousepad_file_is_writable (filename, &error))
+ if (force_save_as || filename == NULL)
{
- /* show the normal confirmation dialog */
- result = GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM;
- }
- else
- {
- /* tell the user he cannot write to this file */
- mousepad_window_error_dialog (GTK_WINDOW (dialog), error, _("Permission denied"));
- g_error_free (error);
-
- /* the user doesn't have permission to write to the file */
- result = GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN;
- }
-
- /* cleanup */
- g_free (filename);
-
- return result;
-}
+ /* get the new filename */
+ new_filename = mousepad_dialogs_save_as (GTK_WINDOW (window), filename);
+ if (new_filename)
+ {
+ /* try the save the file */
+ succeed = mousepad_screen_save_file (screen, new_filename, &error);
+ /* the warnings message for save as */
+ message = _("Failed to save the document as another file");
-static gboolean
-mousepad_window_save_as (MousepadWindow *window,
- MousepadScreen *screen)
-{
- GtkWidget *dialog;
- gboolean succeed = FALSE;
- gchar *filename;
+ if (succeed)
+ {
+ /* set the filename */
+ mousepad_screen_set_filename (screen, new_filename);
- _mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
- _mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
+ /* add the item to the recent menu */
+ mousepad_window_recent_add (window, new_filename);
+ }
- dialog = gtk_file_chooser_dialog_new (_("Save As"),
- GTK_WINDOW (window),
- GTK_FILE_CHOOSER_ACTION_SAVE,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_OK,
- NULL);
- gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), TRUE);
- gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-
- /* we check if the user is allowed to write to the file */
- g_signal_connect (G_OBJECT (dialog), "confirm-overwrite",
- G_CALLBACK (mousepad_window_save_as_callback), NULL);
-
- /* set the current file, or the temp name */
- if (mousepad_screen_get_filename (screen) != NULL)
- gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), mousepad_screen_get_filename (screen));
+ /* cleanup */
+ g_free (new_filename);
+ }
+ }
else
- gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), mousepad_screen_get_title (screen, FALSE));
-
- if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
{
- /* get the filename the user has selected */
- filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ /* get the mtime */
+ mtime = mousepad_screen_get_mtime (screen);
- if (G_LIKELY (filename != NULL))
+ /* check if the file has been modified externally, if so ask the user if
+ * he or she wants to overwrite the file */
+ if (mousepad_file_get_externally_modified (filename, mtime) == FALSE ||
+ mousepad_dialogs_ask_overwrite (GTK_WINDOW (window), filename) == TRUE)
{
- /* set the filename */
- mousepad_screen_set_filename (screen, filename);
-
- /* cleanup */
- g_free (filename);
+ /* save the file */
+ succeed = mousepad_screen_save_file (screen, filename, &error);
- /* it worked */
- succeed = TRUE;
+ /* the warning message for save */
+ message = _("Failed to save the document");
}
}
- /* destroy the dialog */
- gtk_widget_destroy (dialog);
+ /* display the error */
+ if (G_UNLIKELY (error))
+ {
+ mousepad_dialogs_show_error (GTK_WINDOW (window), error, message);
+ g_error_free (error);
+ }
return succeed;
}
@@ -832,18 +851,6 @@ mousepad_window_save_as (MousepadWindow *window,
static void
-mousepad_window_modified_changed (MousepadScreen *screen,
- MousepadWindow *window)
-{
- _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
- _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
-
- mousepad_window_set_title (window, screen);
-}
-
-
-
-static void
mousepad_window_add (MousepadWindow *window,
MousepadScreen *screen)
{
@@ -895,7 +902,7 @@ mousepad_window_add (MousepadWindow *window,
GTK_WIDGET_UNSET_FLAGS (window->notebook, GTK_CAN_FOCUS);
/* rebuild the go menu */
- mousepad_window_go_menu (window);
+ mousepad_window_update_gomenu (window);
/* show the screen */
gtk_widget_show (GTK_WIDGET (screen));
@@ -921,10 +928,8 @@ static gboolean
mousepad_window_close_screen (MousepadWindow *window,
MousepadScreen *screen)
{
- GtkWidget *dialog;
gint response;
gboolean succeed = FALSE;
- GError *error = NULL;
_mousepad_return_val_if_fail (MOUSEPAD_IS_WINDOW (window), FALSE);
_mousepad_return_val_if_fail (MOUSEPAD_IS_SCREEN (screen), FALSE);
@@ -932,28 +937,12 @@ mousepad_window_close_screen (MousepadWindow *window,
/* check if the document needs to be saved */
if (mousepad_screen_get_modified (screen))
{
- /* create the question dialog */
- dialog = gtk_message_dialog_new (GTK_WINDOW (window),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_NONE,
- _("Do you want to save changes to this\ndocument before closing?"));
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
- _("If you don't save, your changes will be lost."));
- gtk_dialog_add_buttons (GTK_DIALOG (dialog),
- _("_Don't Save"), GTK_RESPONSE_HELP,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_SAVE, GTK_RESPONSE_OK,
- NULL);
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-
/* run the dialog */
- response = gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
+ response = mousepad_dialogs_save_changes (GTK_WINDOW (window));
switch (response)
{
- case GTK_RESPONSE_HELP:
+ case GTK_RESPONSE_REJECT:
/* don't save, only destroy the screen */
succeed = TRUE;
break;
@@ -961,17 +950,7 @@ mousepad_window_close_screen (MousepadWindow *window,
/* we do nothing */
break;
case GTK_RESPONSE_OK:
- /* save the screen */
- if (mousepad_screen_get_filename (screen) == NULL)
- {
- /* file has no name yet, save as */
- if (mousepad_window_save_as (window, screen))
- succeed = mousepad_screen_save_file (screen, &error);
- }
- else
- {
- succeed = mousepad_screen_save_file (screen, &error);
- }
+ succeed = mousepad_window_save (window, screen, FALSE);
break;
}
}
@@ -983,168 +962,11 @@ mousepad_window_close_screen (MousepadWindow *window,
/* destroy the screen */
if (succeed)
- {
- gtk_widget_destroy (GTK_WIDGET (screen));
- }
- else if (error != NULL)
- {
- /* something went wrong with saving the file */
- mousepad_window_error_dialog (GTK_WINDOW (window), error, _("Failed to save file"));
- g_error_free (error);
- }
+ gtk_widget_destroy (GTK_WIDGET (screen));
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_recent_menu (MousepadWindow *window)
-{
- 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;
-
- /* leave when we're updating multiple files */
- if (lock_menu_updates)
- return;
-
- /* unmerge the ui controls from the previous update */
- 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->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 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);
- }
-
- /* 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", &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);
-
- /* 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);
-
- /* add the action to the recent actions group */
- gtk_action_group_add_action (window->recent_actions, action);
-
- /* 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);
-
- /* make sure the ui is up2date to avoid flickering */
- gtk_ui_manager_ensure_update (window->ui_manager);
-}
-
-
-
-
-static void
-mousepad_window_add_recent (MousepadWindow *window,
- const gchar *filename)
-{
- GtkRecentData info;
- gchar *uri;
- static gchar *groups[2] = { PACKAGE_NAME, NULL };
-
- _mousepad_return_if_fail (filename != NULL);
-
- /* create the recent data */
- info.display_name = NULL;
- info.description = NULL;
- info.mime_type = "text/plain";
- info.app_name = PACKAGE_NAME;
- info.app_exec = PACKAGE " %u";
- info.groups = groups;
- info.is_private = FALSE;
-
- /* create an uri from the filename */
- uri = g_filename_to_uri (filename, NULL, NULL);
-
- /* add it */
- if (G_LIKELY (uri != NULL))
- {
- gtk_recent_manager_add_full (window->recent_manager, uri, &info);
- g_free (uri);
- }
-}
-
static void
@@ -1186,16 +1008,9 @@ mousepad_window_set_title (MousepadWindow *window,
-static void
-mousepad_window_notify_title (MousepadScreen *screen,
- GParamSpec *pspec,
- MousepadWindow *window)
-{
- mousepad_window_set_title (window, screen);
-}
-
-
-
+/**
+ * Notebook Signal Functions
+ **/
static void
mousepad_window_page_notified (GtkNotebook *notebook,
GParamSpec *pspec,
@@ -1241,7 +1056,7 @@ mousepad_window_tab_removed (GtkNotebook *notebook,
GTK_WIDGET_UNSET_FLAGS (window->notebook, GTK_CAN_FOCUS);
/* rebuild the go menu */
- mousepad_window_go_menu (window);
+ mousepad_window_update_gomenu (window);
/* update all screen sensitive actions */
mousepad_window_update_actions (window);
@@ -1257,38 +1072,34 @@ mousepad_window_page_reordered (GtkNotebook *notebook,
MousepadWindow *window)
{
/* update the go menu */
- mousepad_window_go_menu (window);
+ mousepad_window_update_gomenu (window);
}
+
+/**
+ * Screen Signals Functions
+ **/
static void
-mousepad_window_error_dialog (GtkWindow *window,
- GError *error,
- const gchar *message)
+mousepad_window_notify_title (MousepadScreen *screen,
+ GParamSpec *pspec,
+ MousepadWindow *window)
{
- GtkWidget *dialog;
-
- _mousepad_return_if_fail (GTK_IS_WINDOW (window));
-
- /* create the warning dialog */
- dialog = gtk_message_dialog_new (window,
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- message);
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
+ mousepad_window_set_title (window, screen);
+}
- /* set the message from GError */
- if (G_LIKELY (error && error->message))
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
- error->message);
- /* run the dialog */
- gtk_dialog_run (GTK_DIALOG (dialog));
- /* destroy it */
- gtk_widget_destroy (dialog);
+static void
+mousepad_window_modified_changed (MousepadScreen *screen,
+ MousepadWindow *window)
+{
+ _mousepad_return_if_fail (MOUSEPAD_IS_WINDOW (window));
+ _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+
+ /* TODO: set the tab label color */
+ mousepad_window_set_title (window, screen);
}
@@ -1312,19 +1123,21 @@ mousepad_window_selection_changed (MousepadScreen *screen,
+/**
+ * Menu Update Functions
+ **/
static void
mousepad_window_update_actions (MousepadWindow *window)
{
- GtkAction *action;
- GtkNotebook *notebook = GTK_NOTEBOOK (window->notebook);
- MousepadScreen *screen;
- GtkTextView *textview;
- GtkTextBuffer *buffer;
- GtkWidget *goitem;
- gboolean cycle_tabs;
- gint n_pages;
- gint page_num;
- gboolean selected;
+ GtkAction *action;
+ GtkNotebook *notebook = GTK_NOTEBOOK (window->notebook);
+ MousepadScreen *screen;
+ GtkTextView *textview;
+ GtkTextBuffer *buffer;
+ gboolean cycle_tabs;
+ gint n_pages;
+ gint page_num;
+ gboolean selected;
/* determine the number of pages */
n_pages = gtk_notebook_get_n_pages (notebook);
@@ -1339,9 +1152,11 @@ mousepad_window_update_actions (MousepadWindow *window)
{
page_num = gtk_notebook_page_num (notebook, GTK_WIDGET (screen));
+ /* get the textview and the buffer from the screen */
textview = mousepad_screen_get_text_view (screen);
buffer = mousepad_screen_get_text_buffer (screen);
+ /* whether we cycle tabs */
g_object_get (G_OBJECT (window->preferences), "misc-cycle-tabs", &cycle_tabs, NULL);
action = gtk_action_group_get_action (window->window_actions, "back");
@@ -1353,30 +1168,22 @@ mousepad_window_update_actions (MousepadWindow *window)
action = gtk_action_group_get_action (window->window_actions, "save-file");
gtk_action_set_sensitive (action, gtk_text_view_get_editable (textview));
+ /* set the sensitivity of the selection actions */
g_object_get (G_OBJECT (buffer), "has-selection", &selected, NULL);
mousepad_window_selection_changed (screen, selected, window);
- /* update the "Go" menu */
- goitem = g_object_get_data (G_OBJECT (screen), "go-menu-item");
- if (G_LIKELY (goitem != NULL))
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (goitem), TRUE);
+ /* active this tab in the go menu */
+ action = g_object_get_data (G_OBJECT (screen), I_("go-menu-action"));
+ if (G_LIKELY (action != NULL))
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
}
}
-static void
-mousepad_window_action_goto (GtkRadioAction *action,
- GtkNotebook *notebook)
-{
- gint page = gtk_radio_action_get_current_value (action);
-
- gtk_notebook_set_current_page (notebook, page);
-}
-
static void
-mousepad_window_go_menu (MousepadWindow *window)
+mousepad_window_update_gomenu (MousepadWindow *window)
{
GtkWidget *screen;
gint npages;
@@ -1418,13 +1225,14 @@ mousepad_window_go_menu (MousepadWindow *window)
/* create the radio action */
action = gtk_radio_action_new (name, NULL, NULL, NULL, n);
exo_binding_new (G_OBJECT (screen), "title", G_OBJECT (action), "label");
+ exo_binding_new (G_OBJECT (screen), "filename", G_OBJECT (action), "tooltip");
gtk_radio_action_set_group (action, group);
group = gtk_radio_action_get_group (action);
g_signal_connect (G_OBJECT (action), "activate",
G_CALLBACK (mousepad_window_action_goto), window->notebook);
/* connect the action to the screen to we can easily active it when the user toggled the tabs */
- g_object_set_data (G_OBJECT (screen), I_("go-menu-item"), action);
+ g_object_set_data (G_OBJECT (screen), I_("go-menu-action"), action);
if (G_LIKELY (n < 9))
{
@@ -1454,8 +1262,210 @@ mousepad_window_go_menu (MousepadWindow *window)
}
+
+/**
+ * Funtions for managing the recent files
+ **/
+static void
+mousepad_window_recent_add (MousepadWindow *window,
+ const gchar *filename)
+{
+ GtkRecentData info;
+ gchar *uri;
+ static gchar *groups[2] = { PACKAGE_NAME, NULL };
+
+ _mousepad_return_if_fail (filename != NULL);
+
+ /* create the recent data */
+ info.display_name = NULL;
+ info.description = NULL;
+ info.mime_type = "text/plain";
+ info.app_name = PACKAGE_NAME;
+ info.app_exec = PACKAGE " %u";
+ info.groups = groups;
+ info.is_private = FALSE;
+
+ /* create an uri from the filename */
+ uri = g_filename_to_uri (filename, NULL, NULL);
+
+ /* add it */
+ if (G_LIKELY (uri != NULL))
+ {
+ gtk_recent_manager_add_full (window->recent_manager, uri, &info);
+ g_free (uri);
+ }
+}
+
+
+
+static gint
+mousepad_window_recent_sort (GtkRecentInfo *a,
+ GtkRecentInfo *b)
+{
+ return (gtk_recent_info_get_modified (a) < gtk_recent_info_get_modified (b));
+}
+
+
+
+static void
+mousepad_window_recent_menu (MousepadWindow *window)
+{
+ 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;
+
+ /* leave when we're updating multiple files */
+ if (lock_menu_updates)
+ return;
+
+ /* unmerge the ui controls from the previous update */
+ 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->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 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 and pick the ones that or in the mousepad group */
+ 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);
+ }
+
+ /* sort the filtered items by modification date */
+ filtered = g_list_sort (filtered, (GCompareFunc) mousepad_window_recent_sort);
+
+ /* get the recent menu limit number */
+ 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);
+
+ /* 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);
+
+ /* add the action to the recent actions group */
+ gtk_action_group_add_action (window->recent_actions, action);
+
+ /* 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);
+ }
+
+ /* set the visibility of the 'No items found' 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);
+
+ /* make sure the ui is up2date to avoid flickering */
+ gtk_ui_manager_ensure_update (window->ui_manager);
+}
+
+
+static void
+mousepad_window_recent_clear (MousepadWindow *window)
+{
+ GList *items, *li;
+ const gchar *uri;
+ GError *error = NULL;
+ GtkRecentInfo *info;
+
+ /* 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))
+ continue;
+
+ /* 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))
+ break;
+ }
+
+ /* cleanup */
+ g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
+ g_list_free (items);
+
+ /* print a warning is there is one */
+ if (G_UNLIKELY (error != NULL))
+ {
+ mousepad_dialogs_show_error (GTK_WINDOW (window), error,
+ _("Failed to remove an item from the recent history"));
+ g_error_free (error);
+ }
+}
+
+
+
/**
* Menu Actions
+ *
+ * All those function should be sorted by the menu structure so it's
+ * easy to find a function. They should also use the other window
+ * functions as much as possible to avoid code duplication.
**/
static void
mousepad_window_action_open_new_window (GtkAction *action,
@@ -1519,7 +1529,7 @@ mousepad_window_action_open_file (GtkAction *action,
mousepad_window_open_tab (window, filename);
/* add to the recent files */
- mousepad_window_add_recent (window, filename);
+ mousepad_window_recent_add (window, filename);
/* cleanup */
g_free (filename);
@@ -1533,7 +1543,7 @@ mousepad_window_action_open_file (GtkAction *action,
/* update the menus */
mousepad_window_recent_menu (window);
- mousepad_window_go_menu (window);
+ mousepad_window_update_gomenu (window);
}
/* destroy dialog */
@@ -1588,60 +1598,14 @@ 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)
+ /* ask the user if he or she really want to clear the history */
+ if (mousepad_dialogs_clear_recent (GTK_WINDOW (window)))
{
/* avoid updating the menu */
lock_menu_updates = TRUE;
- /* 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_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
- g_list_free (items);
+ /* clear the recent history */
+ mousepad_window_recent_clear (window);
/* allow menu updates again */
lock_menu_updates = FALSE;
@@ -1649,9 +1613,6 @@ mousepad_window_action_clear_recent (GtkAction *action,
/* update the recent menu */
mousepad_window_recent_menu (window);
}
-
- /* destroy the dialog */
- gtk_widget_destroy (dialog);
}
@@ -1661,26 +1622,12 @@ mousepad_window_action_save_file (GtkAction *action,
MousepadWindow *window)
{
MousepadScreen *screen;
- GError *error = NULL;
screen = mousepad_window_get_active (window);
-
if (G_LIKELY (screen != NULL))
{
- if (mousepad_screen_get_filename (screen) != NULL)
- mousepad_screen_save_file (screen, &error);
- else
- {
- if (mousepad_window_save_as (window, screen))
- mousepad_screen_save_file (screen, &error);
- }
-
- /* check for errors */
- if (G_UNLIKELY (error != NULL))
- {
- mousepad_window_error_dialog (GTK_WINDOW (window), error, _("Failed to save file"));
- g_error_free (error);
- }
+ /* save the file */
+ mousepad_window_save (window, screen, FALSE);
}
}
@@ -1691,25 +1638,12 @@ mousepad_window_action_save_file_as (GtkAction *action,
MousepadWindow *window)
{
MousepadScreen *screen;
- GError *error = NULL;
screen = mousepad_window_get_active (window);
-
if (G_LIKELY (screen != NULL))
{
- /* popup the save as dialog, if that worked, save the file, if
- * 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 (window, mousepad_screen_get_filename (screen));
-
- /* check for errors */
- if (G_UNLIKELY (error != NULL))
- {
- mousepad_window_error_dialog (GTK_WINDOW (window), error, _("Failed to save file as"));
- g_error_free (error);
- }
- else
+ /* save the file */
+ if (mousepad_window_save (window, screen, TRUE))
{
/* make sure save-file is sensitive */
action = gtk_action_group_get_action (window->window_actions, "save-file");
@@ -1727,7 +1661,6 @@ mousepad_window_action_close_tab (GtkAction *action,
MousepadScreen *screen;
screen = mousepad_window_get_active (window);
-
if (G_LIKELY (screen != NULL))
mousepad_window_close_screen (window, screen);
}
@@ -1735,36 +1668,6 @@ mousepad_window_action_close_tab (GtkAction *action,
static void
-mousepad_window_button_close_tab (MousepadScreen *screen)
-{
- MousepadWindow *window;
-
- _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
-
- /* get the mousepad window of this screen */
- window = g_object_get_data (G_OBJECT (screen), I_("mousepad-window"));
-
- /* close the screen */
- if (G_LIKELY (window != NULL))
- mousepad_window_close_screen (window, screen);
-}
-
-
-
-static gboolean
-mousepad_window_delete_event (MousepadWindow *window,
- GdkEvent *event)
-{
- /* try to close the windows */
- mousepad_window_action_close (NULL, window);
-
- /* we will close the window when it's time */
- return TRUE;
-}
-
-
-
-static void
mousepad_window_action_close (GtkAction *action,
MousepadWindow *window)
{
@@ -1795,7 +1698,7 @@ mousepad_window_action_close (GtkAction *action,
lock_menu_updates = FALSE;
/* update the go menu */
- mousepad_window_go_menu (window);
+ mousepad_window_update_gomenu (window);
break;
}
@@ -1837,7 +1740,6 @@ mousepad_window_action_cut (GtkAction *action,
/* get the active screen */
screen = mousepad_window_get_active (window);
-
if (G_LIKELY (screen != NULL))
{
/* get the clipboard, textview and the buffer */
@@ -1868,10 +1770,9 @@ mousepad_window_action_copy (GtkAction *action,
GtkClipboard *clipboard;
screen = mousepad_window_get_active (window);
-
if (G_LIKELY (screen != NULL))
{
- /* get the buffer, textview and the clipboard */
+ /* get the buffer and clipboard */
buffer = mousepad_screen_get_text_buffer (screen);
clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), GDK_SELECTION_CLIPBOARD);
@@ -1892,7 +1793,6 @@ mousepad_window_action_paste (GtkAction *action,
GtkTextView *textview;
screen = mousepad_window_get_active (window);
-
if (G_LIKELY (screen != NULL))
{
/* get the buffer and the clipboard */
@@ -1923,7 +1823,6 @@ mousepad_window_action_delete (GtkAction *action,
GtkTextView *textview;
screen = mousepad_window_get_active (window);
-
if (G_LIKELY (screen != NULL))
{
/* get the buffer */
@@ -1954,7 +1853,6 @@ mousepad_window_action_select_all (GtkAction *action,
GtkTextIter start, end;
screen = mousepad_window_get_active (window);
-
if (G_LIKELY (screen != NULL))
{
/* get the buffer */
@@ -1974,68 +1872,32 @@ static void
mousepad_window_action_jump_to (GtkAction *action,
MousepadWindow *window)
{
- GtkWidget *dialog;
- GtkWidget *hbox, *label, *button;
GtkTextBuffer *buffer;
MousepadScreen *screen;
- gint num, num_max;
+ gint current_line, last_line, line;
GtkTextIter iter;
- GtkAdjustment *adjustment;
-
+ /* get the active screen */
screen = mousepad_window_get_active (window);
-
if (G_LIKELY (screen != NULL))
{
buffer = mousepad_screen_get_text_buffer (screen);
/* get the current line number */
gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
- num = gtk_text_iter_get_line (&iter) + 1;
+ current_line = gtk_text_iter_get_line (&iter) + 1;
/* get the last line number */
gtk_text_buffer_get_end_iter (buffer, &iter);
- num_max = gtk_text_iter_get_line (&iter) + 1;
-
- /* build the dialog */
- dialog = gtk_dialog_new_with_buttons (_("Jump To"),
- GTK_WINDOW (window),
- GTK_DIALOG_MODAL
- | GTK_DIALOG_DESTROY_WITH_PARENT
- | GTK_DIALOG_NO_SEPARATOR,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_JUMP_TO, GTK_RESPONSE_OK,
- NULL);
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
- gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
-
- hbox = gtk_hbox_new (FALSE, 8);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
- gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
- gtk_widget_show (hbox);
-
- label = gtk_label_new_with_mnemonic (_("_Line number:"));
- gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
- gtk_widget_show (label);
-
- /* the spin button adjustment */
- adjustment = (GtkAdjustment *) gtk_adjustment_new (num, 1, num_max, 1, 10, 0);
+ last_line = gtk_text_iter_get_line (&iter) + 1;
- /* the spin button */
- button = gtk_spin_button_new (adjustment, 1, 0);
- gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (button), TRUE);
- gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON (button), TRUE);
- gtk_entry_set_width_chars (GTK_ENTRY (button), 8);
- gtk_entry_set_activates_default (GTK_ENTRY (button), TRUE);
- gtk_label_set_mnemonic_widget (GTK_LABEL(label), button);
- gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
- gtk_widget_show (button);
+ /* run the jump to dialog and wait for the response */
+ line = mousepad_dialogs_jump_to (GTK_WINDOW (window), current_line, last_line);
- if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
+ if (G_LIKELY (line > 0))
{
/* jump to the line */
- num = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (button)) - 1;
- gtk_text_buffer_get_iter_at_line (buffer, &iter, num);
+ gtk_text_buffer_get_iter_at_line (buffer, &iter, line-1);
gtk_text_buffer_place_cursor (buffer, &iter);
/* scroll to visible area */
@@ -2044,9 +1906,6 @@ mousepad_window_action_jump_to (GtkAction *action,
MOUSEPAD_SCROLL_MARGIN,
FALSE, 0.0, 0.0);
}
-
- /* destroy the dialog */
- gtk_widget_destroy (dialog);
}
}
@@ -2123,31 +1982,55 @@ mousepad_window_action_next_tab (GtkAction *action,
static void
+mousepad_window_action_goto (GtkRadioAction *action,
+ GtkNotebook *notebook)
+{
+ /* get the page number from the action value */
+ gint page = gtk_radio_action_get_current_value (action);
+
+ /* set the page */
+ gtk_notebook_set_current_page (notebook, page);
+}
+
+
+
+static void
mousepad_window_action_about (GtkAction *action,
MousepadWindow *window)
{
- static const gchar *authors[] =
- {
- "Erik Harrison <erikharrison at xfce.org>",
- "Nick Schermer <nick at xfce.org>",
- "Benedikt Meurer <benny at xfce.org>",
- NULL,
- };
-
- /* show the dialog */
- gtk_about_dialog_set_email_hook (exo_url_about_dialog_hook, NULL, NULL);
- gtk_about_dialog_set_url_hook (exo_url_about_dialog_hook, NULL, NULL);
- gtk_show_about_dialog (GTK_WINDOW (window),
- "authors", authors,
- "comments", _("Mousepad is a fast text editor for the Xfce Desktop Environment."),
- "copyright", _("Copyright \302\251 2004-2007 Xfce Development Team"),
- "destroy-with-parent", TRUE,
- "license", XFCE_LICENSE_GPL,
- "logo-icon-name", PACKAGE_NAME,
- "name", PACKAGE_NAME,
- "version", PACKAGE_VERSION,
- "translator-credits", _("translator-credits"),
- "website", "http://www.xfce.org/projects/mousepad",
- NULL);
+ mousepad_dialogs_show_about (GTK_WINDOW (window));
}
+
+/**
+ * Miscellaneous Actions
+ **/
+static void
+mousepad_window_button_close_tab (MousepadScreen *screen)
+{
+ MousepadWindow *window;
+
+ _mousepad_return_if_fail (MOUSEPAD_IS_SCREEN (screen));
+
+ /* get the mousepad window of this screen */
+ window = g_object_get_data (G_OBJECT (screen), I_("mousepad-window"));
+
+ /* close the screen */
+ if (G_LIKELY (window != NULL))
+ mousepad_window_close_screen (window, screen);
+}
+
+
+
+static gboolean
+mousepad_window_delete_event (MousepadWindow *window,
+ GdkEvent *event)
+{
+ /* try to close the windows */
+ mousepad_window_action_close (NULL, window);
+
+ /* we will close the window when all the tabs are closed */
+ return TRUE;
+}
+
+
More information about the Xfce4-commits
mailing list