Rename Pluma to Xedit

This commit is contained in:
Clement Lefebvre
2016-01-25 14:13:49 +00:00
parent 3a62ddff64
commit 4304f9ffc1
563 changed files with 112901 additions and 112901 deletions

209
xedit/Makefile.am Normal file
View File

@@ -0,0 +1,209 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = dialogs smclient
bin_PROGRAMS = xedit
noinst_LTLIBRARIES = libxedit.la
AM_CPPFLAGS = \
-I$(top_srcdir) \
-I$(srcdir) \
-I$(srcdir)/smclient \
$(XEDIT_CFLAGS) \
$(MATE_DESKTOP_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED_CFLAGS) \
-DDATADIR=\""$(datadir)"\" \
-DLIBDIR=\""$(libdir)"\"
xedit_SOURCES = \
xedit.c
xedit_LDADD = libxedit.la $(XEDIT_LIBS) $(EGG_SMCLIENT_LIBS)
xedit_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
libxedit_la_LDFLAGS = -export-dynamic -no-undefined -export-symbols-regex "^[[^_]].*"
libxedit_la_LIBADD = \
dialogs/libdialogs.la \
smclient/libeggsmclient.la \
$(MATE_DESKTOP_LIBS)
# XEDIT_LIBS must be the last to ensure correct order on some platforms
libxedit_la_LIBADD += $(XEDIT_LIBS) -lICE
BUILT_SOURCES = \
xedit-enum-types.c \
xedit-enum-types.h \
xedit-marshal.c \
xedit-marshal.h
NOINST_H_FILES = \
xedit-close-button.h \
xedit-dirs.h \
xedit-document-input-stream.h \
xedit-document-loader.h \
xedit-document-output-stream.h \
xedit-document-saver.h \
xedit-documents-panel.h \
xedit-gio-document-loader.h \
xedit-gio-document-saver.h \
xedit-history-entry.h \
xedit-io-error-message-area.h \
xedit-language-manager.h \
xedit-object-module.h \
xedit-plugin-info.h \
xedit-plugin-info-priv.h \
xedit-plugin-loader.h \
xedit-plugin-manager.h \
xedit-plugins-engine.h \
xedit-prefs-manager-private.h \
xedit-print-job.h \
xedit-print-preview.h \
xedit-session.h \
xedit-smart-charset-converter.h \
xedit-style-scheme-manager.h \
xedit-tab-label.h \
xedittextregion.h \
xedit-ui.h \
xedit-window-private.h
INST_H_FILES = \
xedit-app.h \
xedit-commands.h \
xedit-debug.h \
xedit-document.h \
xedit-encodings.h \
xedit-encodings-combo-box.h \
xedit-file-chooser-dialog.h \
xedit-help.h \
xedit-message-bus.h \
xedit-message-type.h \
xedit-message.h \
xedit-notebook.h \
xedit-panel.h \
xedit-plugin.h \
xedit-prefs-manager-app.h \
xedit-prefs-manager.h \
xedit-progress-message-area.h \
xedit-statusbar.h \
xedit-status-combo-box.h \
xedit-tab.h \
xedit-utils.h \
xedit-view.h \
xedit-window.h
if !ENABLE_GVFS_METADATA
INST_H_FILES += xedit-metadata-manager.h
endif
headerdir = $(prefix)/include/xedit
header_DATA = \
$(INST_H_FILES)
libxedit_la_SOURCES = \
$(BUILT_SOURCES) \
$(BACON_FILES) \
$(POSIXIO_FILES) \
xedit-app.c \
xedit-close-button.c \
xedit-commands-documents.c \
xedit-commands-edit.c \
xedit-commands-file.c \
xedit-commands-file-print.c \
xedit-commands-help.c \
xedit-commands-search.c \
xedit-commands-view.c \
xedit-debug.c \
xedit-dirs.c \
xedit-document.c \
xedit-document-input-stream.c \
xedit-document-loader.c \
xedit-document-output-stream.c \
xedit-gio-document-loader.c \
xedit-document-saver.c \
xedit-gio-document-saver.c \
xedit-documents-panel.c \
xedit-encodings.c \
xedit-encodings-combo-box.c \
xedit-file-chooser-dialog.c \
xedit-help.c \
xedit-history-entry.c \
xedit-io-error-message-area.c \
xedit-language-manager.c \
xedit-message-bus.c \
xedit-message-type.c \
xedit-message.c \
xedit-object-module.c \
xedit-notebook.c \
xedit-panel.c \
xedit-plugin-info.c \
xedit-plugin.c \
xedit-plugin-loader.c \
xedit-plugin-manager.c \
xedit-plugins-engine.c \
xedit-prefs-manager-app.c \
xedit-prefs-manager.c \
xedit-prefs-manager-private.h \
xedit-print-job.c \
xedit-print-preview.c \
xedit-progress-message-area.c \
xedit-session.c \
xedit-smart-charset-converter.c \
xedit-statusbar.c \
xedit-status-combo-box.c \
xedit-style-scheme-manager.c \
xedit-tab.c \
xedit-tab-label.c \
xedit-utils.c \
xedit-view.c \
xedit-window.c \
xedittextregion.c \
$(NOINST_H_FILES) \
$(INST_H_FILES)
if !ENABLE_GVFS_METADATA
libxedit_la_SOURCES += xedit-metadata-manager.c
endif
xedit-enum-types.h: xedit-enum-types.h.template $(INST_H_FILES) $(GLIB_MKENUMS)
$(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template xedit-enum-types.h.template $(INST_H_FILES)) > $@
xedit-enum-types.c: xedit-enum-types.c.template $(INST_H_FILES) $(GLIB_MKENUMS)
$(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template xedit-enum-types.c.template $(INST_H_FILES)) > $@
xedit-marshal.h: xedit-marshal.list $(GLIB_GENMARSHAL)
$(AM_V_GEN) $(GLIB_GENMARSHAL) $< --header --prefix=xedit_marshal > $@
xedit-marshal.c: xedit-marshal.list $(GLIB_GENMARSHAL)
$(AM_V_GEN) echo "#include \"xedit-marshal.h\"" > $@ && \
$(GLIB_GENMARSHAL) $< --body --prefix=xedit_marshal >> $@
uidir = $(datadir)/xedit/ui/
ui_DATA = \
xedit-ui.xml \
xedit-print-preferences.ui
EXTRA_DIST = \
$(ui_DATA) \
xedit-enum-types.h.template \
xedit-enum-types.c.template \
xedit-marshal.list \
xedit.rc
CLEANFILES = $(BUILT_SOURCES)
dist-hook:
cd $(distdir); rm -f $(BUILT_SOURCES)
BACON_DIR=$(srcdir)/../../libbacon/src/
BACON_FILES=bacon-message-connection.h bacon-message-connection.c
regenerate-built-sources:
BACONFILES="$(BACON_FILES)" BACONDIR="$(BACON_DIR)" $(top_srcdir)/xedit/update-from-bacon.sh
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,396 @@
/*
* Copyright (C) 2003 Bastien Nocera <hadess@hadess.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include "bacon-message-connection.h"
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 108
#endif
struct BaconMessageConnection {
/* A server accepts connections */
gboolean is_server;
/* The socket path itself */
char *path;
/* File descriptor of the socket */
int fd;
/* Channel to watch */
GIOChannel *chan;
/* Event id returned by g_io_add_watch() */
int conn_id;
/* Connections accepted by this connection */
GSList *accepted_connections;
/* callback */
void (*func) (const char *message, gpointer user_data);
gpointer data;
};
static gboolean
test_is_socket (const char *path)
{
struct stat s;
if (stat (path, &s) == -1)
return FALSE;
if (S_ISSOCK (s.st_mode))
return TRUE;
return FALSE;
}
static gboolean
is_owned_by_user_and_socket (const char *path)
{
struct stat s;
if (stat (path, &s) == -1)
return FALSE;
if (s.st_uid != geteuid ())
return FALSE;
if ((s.st_mode & S_IFSOCK) != S_IFSOCK)
return FALSE;
return TRUE;
}
static gboolean server_cb (GIOChannel *source,
GIOCondition condition, gpointer data);
static gboolean
setup_connection (BaconMessageConnection *conn)
{
g_return_val_if_fail (conn->chan == NULL, FALSE);
conn->chan = g_io_channel_unix_new (conn->fd);
if (!conn->chan) {
return FALSE;
}
g_io_channel_set_line_term (conn->chan, "\n", 1);
conn->conn_id = g_io_add_watch (conn->chan, G_IO_IN, server_cb, conn);
return TRUE;
}
static void
accept_new_connection (BaconMessageConnection *server_conn)
{
BaconMessageConnection *conn;
int alen;
g_return_if_fail (server_conn->is_server);
conn = g_new0 (BaconMessageConnection, 1);
conn->is_server = FALSE;
conn->func = server_conn->func;
conn->data = server_conn->data;
conn->fd = accept (server_conn->fd, NULL, (guint *)&alen);
server_conn->accepted_connections =
g_slist_prepend (server_conn->accepted_connections, conn);
setup_connection (conn);
}
static gboolean
server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
{
BaconMessageConnection *conn = (BaconMessageConnection *)data;
char *message, *subs, buf;
int cd, rc, offset;
gboolean finished;
offset = 0;
if (conn->is_server && conn->fd == g_io_channel_unix_get_fd (source)) {
accept_new_connection (conn);
return TRUE;
}
message = g_malloc (1);
cd = conn->fd;
rc = read (cd, &buf, 1);
while (rc > 0 && buf != '\n')
{
message = g_realloc (message, rc + offset + 1);
message[offset] = buf;
offset = offset + rc;
rc = read (cd, &buf, 1);
}
if (rc <= 0) {
g_io_channel_shutdown (conn->chan, FALSE, NULL);
g_io_channel_unref (conn->chan);
conn->chan = NULL;
close (conn->fd);
conn->fd = -1;
g_free (message);
conn->conn_id = 0;
return FALSE;
}
message[offset] = '\0';
subs = message;
finished = FALSE;
while (finished == FALSE && *subs != '\0')
{
if (conn->func != NULL)
(*conn->func) (subs, conn->data);
subs += strlen (subs) + 1;
if (subs - message >= offset)
finished = TRUE;
}
g_free (message);
return TRUE;
}
static char *
find_file_with_pattern (const char *dir, const char *pattern)
{
GDir *filedir;
char *found_filename;
const char *filename;
GPatternSpec *pat;
filedir = g_dir_open (dir, 0, NULL);
if (filedir == NULL)
return NULL;
pat = g_pattern_spec_new (pattern);
if (pat == NULL)
{
g_dir_close (filedir);
return NULL;
}
found_filename = NULL;
while ((filename = g_dir_read_name (filedir)))
{
if (g_pattern_match_string (pat, filename))
{
char *tmp = g_build_filename (dir, filename, NULL);
if (is_owned_by_user_and_socket (tmp))
found_filename = g_strdup (filename);
g_free (tmp);
}
if (found_filename != NULL)
break;
}
g_pattern_spec_free (pat);
g_dir_close (filedir);
return found_filename;
}
static char *
socket_filename (const char *prefix)
{
char *pattern, *newfile, *path, *filename;
const char *tmpdir;
pattern = g_strdup_printf ("%s.%s.*", prefix, g_get_user_name ());
tmpdir = g_get_tmp_dir ();
filename = find_file_with_pattern (tmpdir, pattern);
if (filename == NULL)
{
newfile = g_strdup_printf ("%s.%s.%u", prefix,
g_get_user_name (), g_random_int ());
path = g_build_filename (tmpdir, newfile, NULL);
g_free (newfile);
} else {
path = g_build_filename (tmpdir, filename, NULL);
g_free (filename);
}
g_free (pattern);
return path;
}
static gboolean
try_server (BaconMessageConnection *conn)
{
struct sockaddr_un uaddr;
uaddr.sun_family = AF_UNIX;
strncpy (uaddr.sun_path, conn->path,
MIN (strlen(conn->path)+1, UNIX_PATH_MAX));
conn->fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (bind (conn->fd, (struct sockaddr *) &uaddr, sizeof (uaddr)) == -1)
{
conn->fd = -1;
return FALSE;
}
listen (conn->fd, 5);
if (!setup_connection (conn))
return FALSE;
return TRUE;
}
static gboolean
try_client (BaconMessageConnection *conn)
{
struct sockaddr_un uaddr;
uaddr.sun_family = AF_UNIX;
strncpy (uaddr.sun_path, conn->path,
MIN(strlen(conn->path)+1, UNIX_PATH_MAX));
conn->fd = socket (PF_UNIX, SOCK_STREAM, 0);
if (connect (conn->fd, (struct sockaddr *) &uaddr,
sizeof (uaddr)) == -1)
{
conn->fd = -1;
return FALSE;
}
return setup_connection (conn);
}
BaconMessageConnection *
bacon_message_connection_new (const char *prefix)
{
BaconMessageConnection *conn;
g_return_val_if_fail (prefix != NULL, NULL);
conn = g_new0 (BaconMessageConnection, 1);
conn->path = socket_filename (prefix);
if (test_is_socket (conn->path) == FALSE)
{
if (!try_server (conn))
{
bacon_message_connection_free (conn);
return NULL;
}
conn->is_server = TRUE;
return conn;
}
if (try_client (conn) == FALSE)
{
unlink (conn->path);
try_server (conn);
if (conn->fd == -1)
{
bacon_message_connection_free (conn);
return NULL;
}
conn->is_server = TRUE;
return conn;
}
conn->is_server = FALSE;
return conn;
}
void
bacon_message_connection_free (BaconMessageConnection *conn)
{
GSList *child_conn;
g_return_if_fail (conn != NULL);
/* Only servers can accept other connections */
g_return_if_fail (conn->is_server != FALSE ||
conn->accepted_connections == NULL);
child_conn = conn->accepted_connections;
while (child_conn != NULL) {
bacon_message_connection_free (child_conn->data);
child_conn = g_slist_next (child_conn);
}
g_slist_free (conn->accepted_connections);
if (conn->conn_id) {
g_source_remove (conn->conn_id);
conn->conn_id = 0;
}
if (conn->chan) {
g_io_channel_shutdown (conn->chan, FALSE, NULL);
g_io_channel_unref (conn->chan);
}
if (conn->is_server != FALSE) {
unlink (conn->path);
}
if (conn->fd != -1) {
close (conn->fd);
}
g_free (conn->path);
g_free (conn);
}
void
bacon_message_connection_set_callback (BaconMessageConnection *conn,
BaconMessageReceivedFunc func,
gpointer user_data)
{
g_return_if_fail (conn != NULL);
conn->func = func;
conn->data = user_data;
}
void
bacon_message_connection_send (BaconMessageConnection *conn,
const char *message)
{
g_return_if_fail (conn != NULL);
g_return_if_fail (message != NULL);
g_io_channel_write_chars (conn->chan, message, strlen (message),
NULL, NULL);
g_io_channel_write_chars (conn->chan, "\n", 1, NULL, NULL);
g_io_channel_flush (conn->chan, NULL);
}
gboolean
bacon_message_connection_get_is_server (BaconMessageConnection *conn)
{
g_return_val_if_fail (conn != NULL, FALSE);
return conn->is_server;
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2003 Bastien Nocera <hadess@hadess.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef BACON_MESSAGE_CONNECTION_H
#define BACON_MESSAGE_CONNECTION_H
#include <glib.h>
G_BEGIN_DECLS
typedef void (*BaconMessageReceivedFunc) (const char *message,
gpointer user_data);
typedef struct BaconMessageConnection BaconMessageConnection;
BaconMessageConnection *bacon_message_connection_new (const char *prefix);
void bacon_message_connection_free (BaconMessageConnection *conn);
void bacon_message_connection_set_callback (BaconMessageConnection *conn,
BaconMessageReceivedFunc func,
gpointer user_data);
void bacon_message_connection_send (BaconMessageConnection *conn,
const char *message);
gboolean bacon_message_connection_get_is_server (BaconMessageConnection *conn);
G_END_DECLS
#endif /* BACON_MESSAGE_CONNECTION_H */

31
xedit/dialogs/Makefile.am Executable file
View File

@@ -0,0 +1,31 @@
uidir = $(datadir)/xedit/ui/
AM_CPPFLAGS = \
-I$(top_srcdir) \
-I$(top_builddir) \
-I$(top_srcdir)/xedit \
-I$(top_builddir)/xedit \
$(XEDIT_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED_CFLAGS)
noinst_LTLIBRARIES = libdialogs.la
libdialogs_la_SOURCES = \
xedit-preferences-dialog.h \
xedit-preferences-dialog.c \
xedit-close-confirmation-dialog.c \
xedit-close-confirmation-dialog.h \
xedit-encodings-dialog.c \
xedit-encodings-dialog.h \
xedit-search-dialog.h \
xedit-search-dialog.c
ui_DATA = \
xedit-encodings-dialog.ui \
xedit-preferences-dialog.ui \
xedit-search-dialog.ui
EXTRA_DIST = $(ui_DATA)
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,836 @@
/*
* xedit-close-confirmation-dialog.c
* This file is part of xedit
*
* Copyright (C) 2004-2005 GNOME Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2004-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n.h>
#include "xedit-close-confirmation-dialog.h"
#include <xedit/xedit-app.h>
#include <xedit/xedit-utils.h>
#include <xedit/xedit-window.h>
/* Properties */
enum
{
PROP_0,
PROP_UNSAVED_DOCUMENTS,
PROP_LOGOUT_MODE
};
/* Mode */
enum
{
SINGLE_DOC_MODE,
MULTIPLE_DOCS_MODE
};
/* Columns */
enum
{
SAVE_COLUMN,
NAME_COLUMN,
DOC_COLUMN, /* a handy pointer to the document */
N_COLUMNS
};
struct _XeditCloseConfirmationDialogPrivate
{
gboolean logout_mode;
GList *unsaved_documents;
GList *selected_documents;
GtkTreeModel *list_store;
gboolean disable_save_to_disk;
};
#define XEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
XEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG, \
XeditCloseConfirmationDialogPrivate))
#define GET_MODE(priv) (((priv->unsaved_documents != NULL) && \
(priv->unsaved_documents->next == NULL)) ? \
SINGLE_DOC_MODE : MULTIPLE_DOCS_MODE)
#if GTK_CHECK_VERSION (3, 0, 0)
#define gtk_hbox_new(X,Y) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,Y)
#define gtk_vbox_new(X,Y) gtk_box_new(GTK_ORIENTATION_VERTICAL,Y)
#endif
G_DEFINE_TYPE(XeditCloseConfirmationDialog, xedit_close_confirmation_dialog, GTK_TYPE_DIALOG)
static void set_unsaved_document (XeditCloseConfirmationDialog *dlg,
const GList *list);
static GList *get_selected_docs (GtkTreeModel *store);
/* Since we connect in the costructor we are sure this handler will be called
* before the user ones
*/
static void
response_cb (XeditCloseConfirmationDialog *dlg,
gint response_id,
gpointer data)
{
XeditCloseConfirmationDialogPrivate *priv;
g_return_if_fail (XEDIT_IS_CLOSE_CONFIRMATION_DIALOG (dlg));
priv = dlg->priv;
if (priv->selected_documents != NULL)
g_list_free (priv->selected_documents);
if (response_id == GTK_RESPONSE_YES)
{
if (GET_MODE (priv) == SINGLE_DOC_MODE)
{
priv->selected_documents =
g_list_copy (priv->unsaved_documents);
}
else
{
g_return_if_fail (priv->list_store);
priv->selected_documents =
get_selected_docs (priv->list_store);
}
}
else
priv->selected_documents = NULL;
}
static void
set_logout_mode (XeditCloseConfirmationDialog *dlg,
gboolean logout_mode)
{
dlg->priv->logout_mode = logout_mode;
if (logout_mode)
{
gtk_dialog_add_button (GTK_DIALOG (dlg),
_("Log Out _without Saving"),
GTK_RESPONSE_NO);
xedit_dialog_add_button (GTK_DIALOG (dlg),
_("_Cancel Logout"),
GTK_STOCK_CANCEL,
GTK_RESPONSE_CANCEL);
}
else
{
gtk_dialog_add_button (GTK_DIALOG (dlg),
_("Close _without Saving"),
GTK_RESPONSE_NO);
gtk_dialog_add_button (GTK_DIALOG (dlg),
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
}
if (dlg->priv->disable_save_to_disk)
{
gtk_dialog_set_default_response (GTK_DIALOG (dlg),
GTK_RESPONSE_NO);
}
else
{
const gchar *stock_id = GTK_STOCK_SAVE;
if (GET_MODE (dlg->priv) == SINGLE_DOC_MODE)
{
XeditDocument *doc;
doc = XEDIT_DOCUMENT (dlg->priv->unsaved_documents->data);
if (xedit_document_get_readonly (doc) ||
xedit_document_is_untitled (doc))
stock_id = GTK_STOCK_SAVE_AS;
}
gtk_dialog_add_button (GTK_DIALOG (dlg),
stock_id,
GTK_RESPONSE_YES);
gtk_dialog_set_default_response (GTK_DIALOG (dlg),
GTK_RESPONSE_YES);
}
}
static void
xedit_close_confirmation_dialog_init (XeditCloseConfirmationDialog *dlg)
{
AtkObject *atk_obj;
dlg->priv = XEDIT_CLOSE_CONFIRMATION_DIALOG_GET_PRIVATE (dlg);
dlg->priv->disable_save_to_disk =
xedit_app_get_lockdown (xedit_app_get_default ())
& XEDIT_LOCKDOWN_SAVE_TO_DISK;
gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
14);
gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dlg), TRUE);
gtk_window_set_title (GTK_WINDOW (dlg), "");
gtk_window_set_modal (GTK_WINDOW (dlg), TRUE);
gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE);
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (dlg));
atk_object_set_role (atk_obj, ATK_ROLE_ALERT);
atk_object_set_name (atk_obj, _("Question"));
g_signal_connect (dlg,
"response",
G_CALLBACK (response_cb),
NULL);
}
static void
xedit_close_confirmation_dialog_finalize (GObject *object)
{
XeditCloseConfirmationDialogPrivate *priv;
priv = XEDIT_CLOSE_CONFIRMATION_DIALOG (object)->priv;
if (priv->unsaved_documents != NULL)
g_list_free (priv->unsaved_documents);
if (priv->selected_documents != NULL)
g_list_free (priv->selected_documents);
/* Call the parent's destructor */
G_OBJECT_CLASS (xedit_close_confirmation_dialog_parent_class)->finalize (object);
}
static void
xedit_close_confirmation_dialog_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XeditCloseConfirmationDialog *dlg;
dlg = XEDIT_CLOSE_CONFIRMATION_DIALOG (object);
switch (prop_id)
{
case PROP_UNSAVED_DOCUMENTS:
set_unsaved_document (dlg, g_value_get_pointer (value));
break;
case PROP_LOGOUT_MODE:
set_logout_mode (dlg, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_close_confirmation_dialog_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XeditCloseConfirmationDialogPrivate *priv;
priv = XEDIT_CLOSE_CONFIRMATION_DIALOG (object)->priv;
switch( prop_id )
{
case PROP_UNSAVED_DOCUMENTS:
g_value_set_pointer (value, priv->unsaved_documents);
break;
case PROP_LOGOUT_MODE:
g_value_set_boolean (value, priv->logout_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_close_confirmation_dialog_class_init (XeditCloseConfirmationDialogClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = xedit_close_confirmation_dialog_set_property;
gobject_class->get_property = xedit_close_confirmation_dialog_get_property;
gobject_class->finalize = xedit_close_confirmation_dialog_finalize;
g_type_class_add_private (klass, sizeof (XeditCloseConfirmationDialogPrivate));
g_object_class_install_property (gobject_class,
PROP_UNSAVED_DOCUMENTS,
g_param_spec_pointer ("unsaved_documents",
"Unsaved Documents",
"List of Unsaved Documents",
(G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY)));
g_object_class_install_property (gobject_class,
PROP_LOGOUT_MODE,
g_param_spec_boolean ("logout_mode",
"Logout Mode",
"Whether the dialog is in logout mode",
FALSE,
(G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY)));
}
static GList *
get_selected_docs (GtkTreeModel *store)
{
GList *list;
gboolean valid;
GtkTreeIter iter;
list = NULL;
valid = gtk_tree_model_get_iter_first (store, &iter);
while (valid)
{
gboolean to_save;
XeditDocument *doc;
gtk_tree_model_get (store, &iter,
SAVE_COLUMN, &to_save,
DOC_COLUMN, &doc,
-1);
if (to_save)
list = g_list_prepend (list, doc);
valid = gtk_tree_model_iter_next (store, &iter);
}
list = g_list_reverse (list);
return list;
}
GList *
xedit_close_confirmation_dialog_get_selected_documents (XeditCloseConfirmationDialog *dlg)
{
g_return_val_if_fail (XEDIT_IS_CLOSE_CONFIRMATION_DIALOG (dlg), NULL);
return g_list_copy (dlg->priv->selected_documents);
}
GtkWidget *
xedit_close_confirmation_dialog_new (GtkWindow *parent,
GList *unsaved_documents,
gboolean logout_mode)
{
GtkWidget *dlg;
g_return_val_if_fail (unsaved_documents != NULL, NULL);
dlg = GTK_WIDGET (g_object_new (XEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG,
"unsaved_documents", unsaved_documents,
"logout_mode", logout_mode,
NULL));
g_return_val_if_fail (dlg != NULL, NULL);
if (parent != NULL)
{
gtk_window_group_add_window (xedit_window_get_group (XEDIT_WINDOW (parent)),
GTK_WINDOW (dlg));
gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
}
return dlg;
}
GtkWidget *
xedit_close_confirmation_dialog_new_single (GtkWindow *parent,
XeditDocument *doc,
gboolean logout_mode)
{
GtkWidget *dlg;
GList *unsaved_documents;
g_return_val_if_fail (doc != NULL, NULL);
unsaved_documents = g_list_prepend (NULL, doc);
dlg = xedit_close_confirmation_dialog_new (parent,
unsaved_documents,
logout_mode);
g_list_free (unsaved_documents);
return dlg;
}
static gchar *
get_text_secondary_label (XeditDocument *doc)
{
glong seconds;
gchar *secondary_msg;
seconds = MAX (1, _xedit_document_get_seconds_since_last_save_or_load (doc));
if (seconds < 55)
{
secondary_msg = g_strdup_printf (
ngettext ("If you don't save, changes from the last %ld second "
"will be permanently lost.",
"If you don't save, changes from the last %ld seconds "
"will be permanently lost.",
seconds),
seconds);
}
else if (seconds < 75) /* 55 <= seconds < 75 */
{
secondary_msg = g_strdup (_("If you don't save, changes from the last minute "
"will be permanently lost."));
}
else if (seconds < 110) /* 75 <= seconds < 110 */
{
secondary_msg = g_strdup_printf (
ngettext ("If you don't save, changes from the last minute and %ld "
"second will be permanently lost.",
"If you don't save, changes from the last minute and %ld "
"seconds will be permanently lost.",
seconds - 60 ),
seconds - 60);
}
else if (seconds < 3600)
{
secondary_msg = g_strdup_printf (
ngettext ("If you don't save, changes from the last %ld minute "
"will be permanently lost.",
"If you don't save, changes from the last %ld minutes "
"will be permanently lost.",
seconds / 60),
seconds / 60);
}
else if (seconds < 7200)
{
gint minutes;
seconds -= 3600;
minutes = seconds / 60;
if (minutes < 5)
{
secondary_msg = g_strdup (_("If you don't save, changes from the last hour "
"will be permanently lost."));
}
else
{
secondary_msg = g_strdup_printf (
ngettext ("If you don't save, changes from the last hour and %d "
"minute will be permanently lost.",
"If you don't save, changes from the last hour and %d "
"minutes will be permanently lost.",
minutes),
minutes);
}
}
else
{
gint hours;
hours = seconds / 3600;
secondary_msg = g_strdup_printf (
ngettext ("If you don't save, changes from the last %d hour "
"will be permanently lost.",
"If you don't save, changes from the last %d hours "
"will be permanently lost.",
hours),
hours);
}
return secondary_msg;
}
static void
build_single_doc_dialog (XeditCloseConfirmationDialog *dlg)
{
GtkWidget *hbox;
GtkWidget *vbox;
GtkWidget *primary_label;
GtkWidget *secondary_label;
GtkWidget *image;
XeditDocument *doc;
gchar *doc_name;
gchar *str;
gchar *markup_str;
g_return_if_fail (dlg->priv->unsaved_documents->data != NULL);
doc = XEDIT_DOCUMENT (dlg->priv->unsaved_documents->data);
/* Image */
#if GTK_CHECK_VERSION (3, 10, 0)
image = gtk_image_new_from_icon_name ("dialog-warning",
GTK_ICON_SIZE_DIALOG);
#else
image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
GTK_ICON_SIZE_DIALOG);
#endif
#if GTK_CHECK_VERSION (3, 0, 0)
gtk_widget_set_halign (image, GTK_ALIGN_START);
gtk_widget_set_valign (image, GTK_ALIGN_END);
#else
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
#endif
/* Primary label */
primary_label = gtk_label_new (NULL);
gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
#if GTK_CHECK_VERSION (3, 16, 0)
gtk_label_set_xalign (GTK_LABEL (primary_label), 0.0);
#else
gtk_misc_set_alignment (GTK_MISC (primary_label), 0.0, 0.5);
#endif
gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
gtk_widget_set_can_focus (GTK_WIDGET (primary_label), FALSE);
doc_name = xedit_document_get_short_name_for_display (doc);
if (dlg->priv->disable_save_to_disk)
{
str = g_markup_printf_escaped (_("Changes to document \"%s\" will be permanently lost."),
doc_name);
}
else
{
str = g_markup_printf_escaped (_("Save changes to document \"%s\" before closing?"),
doc_name);
}
g_free (doc_name);
markup_str = g_strconcat ("<span weight=\"bold\" size=\"larger\">", str, "</span>", NULL);
g_free (str);
gtk_label_set_markup (GTK_LABEL (primary_label), markup_str);
g_free (markup_str);
/* Secondary label */
if (dlg->priv->disable_save_to_disk)
str = g_strdup (_("Saving has been disabled by the system administrator."));
else
str = get_text_secondary_label (doc);
secondary_label = gtk_label_new (str);
g_free (str);
gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
#if GTK_CHECK_VERSION (3, 16, 0)
gtk_label_set_xalign (GTK_LABEL (secondary_label), 0.0);
#else
gtk_misc_set_alignment (GTK_MISC (secondary_label), 0.0, 0.5);
#endif
gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
gtk_widget_set_can_focus (GTK_WIDGET (secondary_label), FALSE);
hbox = gtk_hbox_new (FALSE, 12);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
vbox = gtk_vbox_new (FALSE, 12);
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), primary_label, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), secondary_label, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
hbox,
FALSE,
FALSE,
0);
gtk_widget_show_all (hbox);
}
static void
populate_model (GtkTreeModel *store, GList *docs)
{
GtkTreeIter iter;
while (docs != NULL)
{
XeditDocument *doc;
gchar *name;
doc = XEDIT_DOCUMENT (docs->data);
name = xedit_document_get_short_name_for_display (doc);
gtk_list_store_append (GTK_LIST_STORE (store), &iter);
gtk_list_store_set (GTK_LIST_STORE (store), &iter,
SAVE_COLUMN, TRUE,
NAME_COLUMN, name,
DOC_COLUMN, doc,
-1);
g_free (name);
docs = g_list_next (docs);
}
}
static void
save_toggled (GtkCellRendererToggle *renderer, gchar *path_str, GtkTreeModel *store)
{
GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
GtkTreeIter iter;
gboolean active;
gtk_tree_model_get_iter (store, &iter, path);
gtk_tree_model_get (store, &iter, SAVE_COLUMN, &active, -1);
active ^= 1;
gtk_list_store_set (GTK_LIST_STORE (store), &iter,
SAVE_COLUMN, active, -1);
gtk_tree_path_free (path);
}
static GtkWidget *
create_treeview (XeditCloseConfirmationDialogPrivate *priv)
{
GtkListStore *store;
GtkWidget *treeview;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
treeview = gtk_tree_view_new ();
gtk_widget_set_size_request (treeview, 260, 120);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (treeview), FALSE);
/* Create and populate the model */
store = gtk_list_store_new (N_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER);
populate_model (GTK_TREE_MODEL (store), priv->unsaved_documents);
/* Set model to the treeview */
gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (store));
g_object_unref (store);
priv->list_store = GTK_TREE_MODEL (store);
/* Add columns */
if (!priv->disable_save_to_disk)
{
renderer = gtk_cell_renderer_toggle_new ();
g_signal_connect (renderer, "toggled",
G_CALLBACK (save_toggled), store);
column = gtk_tree_view_column_new_with_attributes ("Save?",
renderer,
"active",
SAVE_COLUMN,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
}
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Name",
renderer,
"text",
NAME_COLUMN,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
return treeview;
}
static void
build_multiple_docs_dialog (XeditCloseConfirmationDialog *dlg)
{
XeditCloseConfirmationDialogPrivate *priv;
GtkWidget *hbox;
GtkWidget *image;
GtkWidget *vbox;
GtkWidget *primary_label;
GtkWidget *vbox2;
GtkWidget *select_label;
GtkWidget *scrolledwindow;
GtkWidget *treeview;
GtkWidget *secondary_label;
gchar *str;
gchar *markup_str;
priv = dlg->priv;
hbox = gtk_hbox_new (FALSE, 12);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
hbox, TRUE, TRUE, 0);
/* Image */
#if GTK_CHECK_VERSION (3, 10, 0)
image = gtk_image_new_from_icon_name ("dialog-warning",
GTK_ICON_SIZE_DIALOG);
#else
image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
GTK_ICON_SIZE_DIALOG);
#endif
#if GTK_CHECK_VERSION (3, 0, 0)
gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
gtk_widget_set_valign (image, GTK_ALIGN_START);
#else
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
#endif
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
vbox = gtk_vbox_new (FALSE, 12);
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
/* Primary label */
primary_label = gtk_label_new (NULL);
gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
#if GTK_CHECK_VERSION (3, 16, 0)
gtk_label_set_xalign (GTK_LABEL (primary_label), 0.0);
#else
gtk_misc_set_alignment (GTK_MISC (primary_label), 0.0, 0.5);
#endif
gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
if (priv->disable_save_to_disk)
str = g_strdup_printf (
ngettext ("Changes to %d document will be permanently lost.",
"Changes to %d documents will be permanently lost.",
g_list_length (priv->unsaved_documents)),
g_list_length (priv->unsaved_documents));
else
str = g_strdup_printf (
ngettext ("There is %d document with unsaved changes. "
"Save changes before closing?",
"There are %d documents with unsaved changes. "
"Save changes before closing?",
g_list_length (priv->unsaved_documents)),
g_list_length (priv->unsaved_documents));
markup_str = g_strconcat ("<span weight=\"bold\" size=\"larger\">", str, "</span>", NULL);
g_free (str);
gtk_label_set_markup (GTK_LABEL (primary_label), markup_str);
g_free (markup_str);
gtk_box_pack_start (GTK_BOX (vbox), primary_label, FALSE, FALSE, 0);
vbox2 = gtk_vbox_new (FALSE, 8);
gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0);
if (priv->disable_save_to_disk)
select_label = gtk_label_new_with_mnemonic (_("Docum_ents with unsaved changes:"));
else
select_label = gtk_label_new_with_mnemonic (_("S_elect the documents you want to save:"));
gtk_box_pack_start (GTK_BOX (vbox2), select_label, FALSE, FALSE, 0);
gtk_label_set_line_wrap (GTK_LABEL (select_label), TRUE);
#if GTK_CHECK_VERSION (3, 16, 0)
gtk_label_set_xalign (GTK_LABEL (select_label), 0.0);
#else
gtk_misc_set_alignment (GTK_MISC (select_label), 0.0, 0.5);
#endif
scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
gtk_box_pack_start (GTK_BOX (vbox2), scrolledwindow, TRUE, TRUE, 0);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_SHADOW_IN);
treeview = create_treeview (priv);
gtk_container_add (GTK_CONTAINER (scrolledwindow), treeview);
/* Secondary label */
if (priv->disable_save_to_disk)
secondary_label = gtk_label_new (_("Saving has been disabled by the system administrator."));
else
secondary_label = gtk_label_new (_("If you don't save, "
"all your changes will be permanently lost."));
gtk_box_pack_start (GTK_BOX (vbox2), secondary_label, FALSE, FALSE, 0);
gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
#if GTK_CHECK_VERSION (3, 16, 0)
gtk_label_set_xalign (GTK_LABEL (secondary_label), 0.0);
#else
gtk_misc_set_alignment (GTK_MISC (secondary_label), 0.0, 0.5);
#endif
gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
gtk_label_set_mnemonic_widget (GTK_LABEL (select_label), treeview);
gtk_widget_show_all (hbox);
}
static void
set_unsaved_document (XeditCloseConfirmationDialog *dlg,
const GList *list)
{
XeditCloseConfirmationDialogPrivate *priv;
g_return_if_fail (list != NULL);
priv = dlg->priv;
g_return_if_fail (priv->unsaved_documents == NULL);
priv->unsaved_documents = g_list_copy ((GList *)list);
if (GET_MODE (priv) == SINGLE_DOC_MODE)
{
build_single_doc_dialog (dlg);
}
else
{
build_multiple_docs_dialog (dlg);
}
}
const GList *
xedit_close_confirmation_dialog_get_unsaved_documents (XeditCloseConfirmationDialog *dlg)
{
g_return_val_if_fail (XEDIT_IS_CLOSE_CONFIRMATION_DIALOG (dlg), NULL);
return dlg->priv->unsaved_documents;
}

View File

@@ -0,0 +1,75 @@
/*
* xedit-close-confirmation-dialog.h
* This file is part of xedit
*
* Copyright (C) 2004-2005 GNOME Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2004-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*/
#ifndef __XEDIT_CLOSE_CONFIRMATION_DIALOG_H__
#define __XEDIT_CLOSE_CONFIRMATION_DIALOG_H__
#include <glib.h>
#include <gtk/gtk.h>
#include <xedit/xedit-document.h>
#define XEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG (xedit_close_confirmation_dialog_get_type ())
#define XEDIT_CLOSE_CONFIRMATION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG, XeditCloseConfirmationDialog))
#define XEDIT_CLOSE_CONFIRMATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG, XeditCloseConfirmationDialogClass))
#define XEDIT_IS_CLOSE_CONFIRMATION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG))
#define XEDIT_IS_CLOSE_CONFIRMATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG))
#define XEDIT_CLOSE_CONFIRMATION_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),XEDIT_TYPE_CLOSE_CONFIRMATION_DIALOG, XeditCloseConfirmationDialogClass))
typedef struct _XeditCloseConfirmationDialog XeditCloseConfirmationDialog;
typedef struct _XeditCloseConfirmationDialogClass XeditCloseConfirmationDialogClass;
typedef struct _XeditCloseConfirmationDialogPrivate XeditCloseConfirmationDialogPrivate;
struct _XeditCloseConfirmationDialog
{
GtkDialog parent;
/*< private > */
XeditCloseConfirmationDialogPrivate *priv;
};
struct _XeditCloseConfirmationDialogClass
{
GtkDialogClass parent_class;
};
GType xedit_close_confirmation_dialog_get_type (void) G_GNUC_CONST;
GtkWidget *xedit_close_confirmation_dialog_new (GtkWindow *parent,
GList *unsaved_documents,
gboolean logout_mode);
GtkWidget *xedit_close_confirmation_dialog_new_single (GtkWindow *parent,
XeditDocument *doc,
gboolean logout_mode);
const GList *xedit_close_confirmation_dialog_get_unsaved_documents (XeditCloseConfirmationDialog *dlg);
GList *xedit_close_confirmation_dialog_get_selected_documents (XeditCloseConfirmationDialog *dlg);
#endif /* __XEDIT_CLOSE_CONFIRMATION_DIALOG_H__ */

View File

@@ -0,0 +1,498 @@
/*
* xedit-encodings-dialog.c
* This file is part of xedit
*
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "xedit-encodings-dialog.h"
#include "xedit-encodings.h"
#include "xedit-prefs-manager.h"
#include "xedit-utils.h"
#include "xedit-debug.h"
#include "xedit-help.h"
#include "xedit-dirs.h"
#define XEDIT_ENCODINGS_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
XEDIT_TYPE_ENCODINGS_DIALOG, \
XeditEncodingsDialogPrivate))
struct _XeditEncodingsDialogPrivate
{
GtkListStore *available_liststore;
GtkListStore *displayed_liststore;
GtkWidget *available_treeview;
GtkWidget *displayed_treeview;
GtkWidget *add_button;
GtkWidget *remove_button;
GSList *show_in_menu_list;
};
G_DEFINE_TYPE(XeditEncodingsDialog, xedit_encodings_dialog, GTK_TYPE_DIALOG)
static void
xedit_encodings_dialog_finalize (GObject *object)
{
XeditEncodingsDialogPrivate *priv = XEDIT_ENCODINGS_DIALOG (object)->priv;
g_slist_free (priv->show_in_menu_list);
G_OBJECT_CLASS (xedit_encodings_dialog_parent_class)->finalize (object);
}
static void
xedit_encodings_dialog_class_init (XeditEncodingsDialogClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = xedit_encodings_dialog_finalize;
g_type_class_add_private (object_class, sizeof (XeditEncodingsDialogPrivate));
}
enum {
COLUMN_NAME,
COLUMN_CHARSET,
N_COLUMNS
};
static void
count_selected_items_func (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
gpointer data)
{
int *count = data;
*count += 1;
}
static void
available_selection_changed_callback (GtkTreeSelection *selection,
XeditEncodingsDialog *dialogs)
{
int count;
count = 0;
gtk_tree_selection_selected_foreach (selection,
count_selected_items_func,
&count);
gtk_widget_set_sensitive (dialogs->priv->add_button, count > 0);
}
static void
displayed_selection_changed_callback (GtkTreeSelection *selection,
XeditEncodingsDialog *dialogs)
{
int count;
count = 0;
gtk_tree_selection_selected_foreach (selection,
count_selected_items_func,
&count);
gtk_widget_set_sensitive (dialogs->priv->remove_button, count > 0);
}
static void
get_selected_encodings_func (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
gpointer data)
{
GSList **list = data;
gchar *charset;
const XeditEncoding *enc;
charset = NULL;
gtk_tree_model_get (model, iter, COLUMN_CHARSET, &charset, -1);
enc = xedit_encoding_get_from_charset (charset);
g_free (charset);
*list = g_slist_prepend (*list, (gpointer)enc);
}
static void
update_shown_in_menu_tree_model (GtkListStore *store,
GSList *list)
{
GtkTreeIter iter;
gtk_list_store_clear (store);
while (list != NULL)
{
const XeditEncoding *enc;
enc = (const XeditEncoding*) list->data;
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COLUMN_CHARSET,
xedit_encoding_get_charset (enc),
COLUMN_NAME,
xedit_encoding_get_name (enc), -1);
list = g_slist_next (list);
}
}
static void
add_button_clicked_callback (GtkWidget *button,
XeditEncodingsDialog *dialog)
{
GtkTreeSelection *selection;
GSList *encodings;
GSList *tmp;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->available_treeview));
encodings = NULL;
gtk_tree_selection_selected_foreach (selection,
get_selected_encodings_func,
&encodings);
tmp = encodings;
while (tmp != NULL)
{
if (g_slist_find (dialog->priv->show_in_menu_list, tmp->data) == NULL)
dialog->priv->show_in_menu_list = g_slist_prepend (dialog->priv->show_in_menu_list,
tmp->data);
tmp = g_slist_next (tmp);
}
g_slist_free (encodings);
update_shown_in_menu_tree_model (GTK_LIST_STORE (dialog->priv->displayed_liststore),
dialog->priv->show_in_menu_list);
}
static void
remove_button_clicked_callback (GtkWidget *button,
XeditEncodingsDialog *dialog)
{
GtkTreeSelection *selection;
GSList *encodings;
GSList *tmp;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->priv->displayed_treeview));
encodings = NULL;
gtk_tree_selection_selected_foreach (selection,
get_selected_encodings_func,
&encodings);
tmp = encodings;
while (tmp != NULL)
{
dialog->priv->show_in_menu_list = g_slist_remove (dialog->priv->show_in_menu_list,
tmp->data);
tmp = g_slist_next (tmp);
}
g_slist_free (encodings);
update_shown_in_menu_tree_model (GTK_LIST_STORE (dialog->priv->displayed_liststore),
dialog->priv->show_in_menu_list);
}
static void
init_shown_in_menu_tree_model (XeditEncodingsDialog *dialog)
{
GtkTreeIter iter;
GSList *list, *tmp;
/* add data to the list store */
list = xedit_prefs_manager_get_shown_in_menu_encodings ();
tmp = list;
while (tmp != NULL)
{
const XeditEncoding *enc;
enc = (const XeditEncoding *) tmp->data;
dialog->priv->show_in_menu_list = g_slist_prepend (dialog->priv->show_in_menu_list,
tmp->data);
gtk_list_store_append (dialog->priv->displayed_liststore,
&iter);
gtk_list_store_set (dialog->priv->displayed_liststore,
&iter,
COLUMN_CHARSET,
xedit_encoding_get_charset (enc),
COLUMN_NAME,
xedit_encoding_get_name (enc), -1);
tmp = g_slist_next (tmp);
}
g_slist_free (list);
}
static void
response_handler (GtkDialog *dialog,
gint response_id,
XeditEncodingsDialog *dlg)
{
if (response_id == GTK_RESPONSE_HELP)
{
xedit_help_display (GTK_WINDOW (dialog), "xedit", NULL);
g_signal_stop_emission_by_name (dialog, "response");
return;
}
if (response_id == GTK_RESPONSE_OK)
{
g_return_if_fail (xedit_prefs_manager_shown_in_menu_encodings_can_set ());
xedit_prefs_manager_set_shown_in_menu_encodings (dlg->priv->show_in_menu_list);
}
}
static void
xedit_encodings_dialog_init (XeditEncodingsDialog *dlg)
{
GtkWidget *content;
GtkCellRenderer *cell_renderer;
GtkTreeModel *sort_model;
GtkTreeViewColumn *column;
GtkTreeIter parent_iter;
GtkTreeSelection *selection;
const XeditEncoding *enc;
GtkWidget *error_widget;
int i;
gboolean ret;
gchar *file;
gchar *root_objects[] = {
"encodings-dialog-contents",
NULL
};
dlg->priv = XEDIT_ENCODINGS_DIALOG_GET_PRIVATE (dlg);
gtk_dialog_add_buttons (GTK_DIALOG (dlg),
GTK_STOCK_CANCEL,
GTK_RESPONSE_CANCEL,
GTK_STOCK_OK,
GTK_RESPONSE_OK,
GTK_STOCK_HELP,
GTK_RESPONSE_HELP,
NULL);
gtk_window_set_title (GTK_WINDOW (dlg), _("Character Encodings"));
gtk_window_set_default_size (GTK_WINDOW (dlg), 650, 400);
/* HIG defaults */
gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
2); /* 2 * 5 + 2 = 12 */
gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dlg))),
5);
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dlg))), 6);
gtk_dialog_set_default_response (GTK_DIALOG (dlg),
GTK_RESPONSE_OK);
g_signal_connect (dlg,
"response",
G_CALLBACK (response_handler),
dlg);
file = xedit_dirs_get_ui_file ("xedit-encodings-dialog.ui");
ret = xedit_utils_get_ui_objects (file,
root_objects,
&error_widget,
"encodings-dialog-contents", &content,
"add-button", &dlg->priv->add_button,
"remove-button", &dlg->priv->remove_button,
"available-treeview", &dlg->priv->available_treeview,
"displayed-treeview", &dlg->priv->displayed_treeview,
NULL);
g_free (file);
if (!ret)
{
gtk_widget_show (error_widget);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
error_widget,
TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (error_widget), 5);
return;
}
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
content, TRUE, TRUE, 0);
g_object_unref (content);
gtk_container_set_border_width (GTK_CONTAINER (content), 5);
g_signal_connect (dlg->priv->add_button,
"clicked",
G_CALLBACK (add_button_clicked_callback),
dlg);
g_signal_connect (dlg->priv->remove_button,
"clicked",
G_CALLBACK (remove_button_clicked_callback),
dlg);
/* Tree view of available encodings */
dlg->priv->available_liststore = gtk_list_store_new (N_COLUMNS,
G_TYPE_STRING,
G_TYPE_STRING);
cell_renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (_("_Description"),
cell_renderer,
"text", COLUMN_NAME,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->available_treeview),
column);
gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
cell_renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (_("_Encoding"),
cell_renderer,
"text",
COLUMN_CHARSET,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->available_treeview),
column);
gtk_tree_view_column_set_sort_column_id (column, COLUMN_CHARSET);
/* Add the data */
i = 0;
while ((enc = xedit_encoding_get_from_index (i)) != NULL)
{
gtk_list_store_append (dlg->priv->available_liststore,
&parent_iter);
gtk_list_store_set (dlg->priv->available_liststore,
&parent_iter,
COLUMN_CHARSET,
xedit_encoding_get_charset (enc),
COLUMN_NAME,
xedit_encoding_get_name (enc), -1);
++i;
}
/* Sort model */
sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (dlg->priv->available_liststore));
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
COLUMN_NAME,
GTK_SORT_ASCENDING);
gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->priv->available_treeview),
sort_model);
g_object_unref (G_OBJECT (dlg->priv->available_liststore));
g_object_unref (G_OBJECT (sort_model));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->priv->available_treeview));
gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection),
GTK_SELECTION_MULTIPLE);
available_selection_changed_callback (selection, dlg);
g_signal_connect (selection,
"changed",
G_CALLBACK (available_selection_changed_callback),
dlg);
/* Tree view of selected encodings */
dlg->priv->displayed_liststore = gtk_list_store_new (N_COLUMNS,
G_TYPE_STRING,
G_TYPE_STRING);
cell_renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (_("_Description"),
cell_renderer,
"text", COLUMN_NAME,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->displayed_treeview),
column);
gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
cell_renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (_("_Encoding"),
cell_renderer,
"text",
COLUMN_CHARSET,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->displayed_treeview),
column);
gtk_tree_view_column_set_sort_column_id (column, COLUMN_CHARSET);
/* Add the data */
init_shown_in_menu_tree_model (dlg);
/* Sort model */
sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (dlg->priv->displayed_liststore));
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE
(sort_model), COLUMN_NAME,
GTK_SORT_ASCENDING);
gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->priv->displayed_treeview),
sort_model);
g_object_unref (G_OBJECT (sort_model));
g_object_unref (G_OBJECT (dlg->priv->displayed_liststore));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->priv->displayed_treeview));
gtk_tree_selection_set_mode (GTK_TREE_SELECTION (selection),
GTK_SELECTION_MULTIPLE);
displayed_selection_changed_callback (selection, dlg);
g_signal_connect (selection,
"changed",
G_CALLBACK (displayed_selection_changed_callback),
dlg);
}
GtkWidget *
xedit_encodings_dialog_new (void)
{
GtkWidget *dlg;
dlg = GTK_WIDGET (g_object_new (XEDIT_TYPE_ENCODINGS_DIALOG, NULL));
return dlg;
}

View File

@@ -0,0 +1,86 @@
/*
* xedit-encodings-dialog.h
* This file is part of xedit
*
* Copyright (C) 2003-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2003-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_ENCODINGS_DIALOG_H__
#define __XEDIT_ENCODINGS_DIALOG_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_ENCODINGS_DIALOG (xedit_encodings_dialog_get_type())
#define XEDIT_ENCODINGS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_ENCODINGS_DIALOG, XeditEncodingsDialog))
#define XEDIT_ENCODINGS_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_ENCODINGS_DIALOG, XeditEncodingsDialog const))
#define XEDIT_ENCODINGS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_ENCODINGS_DIALOG, XeditEncodingsDialogClass))
#define XEDIT_IS_ENCODINGS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_ENCODINGS_DIALOG))
#define XEDIT_IS_ENCODINGS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_ENCODINGS_DIALOG))
#define XEDIT_ENCODINGS_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_ENCODINGS_DIALOG, XeditEncodingsDialogClass))
/* Private structure type */
typedef struct _XeditEncodingsDialogPrivate XeditEncodingsDialogPrivate;
/*
* Main object structure
*/
typedef struct _XeditEncodingsDialog XeditEncodingsDialog;
struct _XeditEncodingsDialog
{
GtkDialog dialog;
/*< private > */
XeditEncodingsDialogPrivate *priv;
};
/*
* Class definition
*/
typedef struct _XeditEncodingsDialogClass XeditEncodingsDialogClass;
struct _XeditEncodingsDialogClass
{
GtkDialogClass parent_class;
};
/*
* Public methods
*/
GType xedit_encodings_dialog_get_type (void) G_GNUC_CONST;
GtkWidget *xedit_encodings_dialog_new (void);
G_END_DECLS
#endif /* __XEDIT_ENCODINGS_DIALOG_H__ */

View File

@@ -0,0 +1,255 @@
<?xml version="1.0"?>
<!--*- mode: xml -*-->
<interface>
<object class="GtkDialog" id="encodings-dialog">
<property name="width_request">650</property>
<property name="height_request">400</property>
<property name="title" translatable="yes">Character encodings</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">True</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">True</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox3">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area3">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<object class="GtkButton" id="helpbutton1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-help</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
</object>
</child>
<child>
<object class="GtkButton" id="closebutton1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-cancel</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
</object>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-ok</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
</object>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="encodings-dialog-contents">
<property name="border_width">6</property>
<property name="visible">True</property>
<property name="homogeneous">True</property>
<property name="spacing">6</property>
<child>
<object class="GtkVBox" id="vbox6">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="available-label">
<property name="visible">True</property>
<property name="label" translatable="yes">A_vailable encodings:</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="mnemonic_widget">available-treeview</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<object class="GtkTreeView" id="available-treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">True</property>
<property name="rules_hint">True</property>
<property name="reorderable">False</property>
<property name="enable_search">True</property>
</object>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox6">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<object class="GtkButton" id="add-button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-add</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox7">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="displayed-label">
<property name="visible">True</property>
<property name="label" translatable="yes">E_ncodings shown in menu:</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="mnemonic_widget">displayed-treeview</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow3">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<object class="GtkTreeView" id="displayed-treeview">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">True</property>
<property name="rules_hint">True</property>
<property name="reorderable">False</property>
<property name="enable_search">True</property>
</object>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox8">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<object class="GtkButton" id="remove-button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-remove</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="-11">helpbutton1</action-widget>
<action-widget response="-6">closebutton1</action-widget>
<action-widget response="-5">button1</action-widget>
</action-widgets>
</object>
</interface>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,87 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xedit-preferences-dialog.c
* This file is part of xedit
*
* Copyright (C) 2001-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2003. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_PREFERENCES_DIALOG_H__
#define __XEDIT_PREFERENCES_DIALOG_H__
#include "xedit-window.h"
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_PREFERENCES_DIALOG (xedit_preferences_dialog_get_type())
#define XEDIT_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_PREFERENCES_DIALOG, XeditPreferencesDialog))
#define XEDIT_PREFERENCES_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_PREFERENCES_DIALOG, XeditPreferencesDialog const))
#define XEDIT_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_PREFERENCES_DIALOG, XeditPreferencesDialogClass))
#define XEDIT_IS_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_PREFERENCES_DIALOG))
#define XEDIT_IS_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_PREFERENCES_DIALOG))
#define XEDIT_PREFERENCES_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_PREFERENCES_DIALOG, XeditPreferencesDialogClass))
/* Private structure type */
typedef struct _XeditPreferencesDialogPrivate XeditPreferencesDialogPrivate;
/*
* Main object structure
*/
typedef struct _XeditPreferencesDialog XeditPreferencesDialog;
struct _XeditPreferencesDialog
{
GtkDialog dialog;
/*< private > */
XeditPreferencesDialogPrivate *priv;
};
/*
* Class definition
*/
typedef struct _XeditPreferencesDialogClass XeditPreferencesDialogClass;
struct _XeditPreferencesDialogClass
{
GtkDialogClass parent_class;
};
/*
* Public methods
*/
GType xedit_preferences_dialog_get_type (void) G_GNUC_CONST;
void xedit_show_preferences_dialog (XeditWindow *parent);
G_END_DECLS
#endif /* __XEDIT_PREFERENCES_DIALOG_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,654 @@
/*
* xedit-search-dialog.c
* This file is part of xedit
*
* Copyright (C) 2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "xedit-search-dialog.h"
#include "xedit-history-entry.h"
#include "xedit-utils.h"
#include "xedit-marshal.h"
#include "xedit-dirs.h"
#define XEDIT_SEARCH_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
XEDIT_TYPE_SEARCH_DIALOG, \
XeditSearchDialogPrivate))
/* Signals */
enum
{
SHOW_REPLACE,
LAST_SIGNAL
};
static guint dialog_signals [LAST_SIGNAL] = { 0 };
struct _XeditSearchDialogPrivate
{
gboolean show_replace;
GtkWidget *table;
GtkWidget *search_label;
GtkWidget *search_entry;
GtkWidget *search_text_entry;
GtkWidget *replace_label;
GtkWidget *replace_entry;
GtkWidget *replace_text_entry;
GtkWidget *match_case_checkbutton;
GtkWidget *entire_word_checkbutton;
GtkWidget *backwards_checkbutton;
GtkWidget *wrap_around_checkbutton;
GtkWidget *parse_escapes_checkbutton;
GtkWidget *find_button;
GtkWidget *replace_button;
GtkWidget *replace_all_button;
gboolean ui_error;
};
G_DEFINE_TYPE(XeditSearchDialog, xedit_search_dialog, GTK_TYPE_DIALOG)
enum
{
PROP_0,
PROP_SHOW_REPLACE
};
static void
xedit_search_dialog_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XeditSearchDialog *dlg = XEDIT_SEARCH_DIALOG (object);
switch (prop_id)
{
case PROP_SHOW_REPLACE:
xedit_search_dialog_set_show_replace (dlg,
g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_search_dialog_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XeditSearchDialog *dlg = XEDIT_SEARCH_DIALOG (object);
switch (prop_id)
{
case PROP_SHOW_REPLACE:
g_value_set_boolean (value, dlg->priv->show_replace);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
void
xedit_search_dialog_present_with_time (XeditSearchDialog *dialog,
guint32 timestamp)
{
g_return_if_fail (XEDIT_SEARCH_DIALOG (dialog));
gtk_window_present_with_time (GTK_WINDOW (dialog), timestamp);
gtk_widget_grab_focus (dialog->priv->search_text_entry);
}
static gboolean
show_replace (XeditSearchDialog *dlg)
{
xedit_search_dialog_set_show_replace (dlg, TRUE);
return TRUE;
}
static void
xedit_search_dialog_class_init (XeditSearchDialogClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkBindingSet *binding_set;
object_class->set_property = xedit_search_dialog_set_property;
object_class->get_property = xedit_search_dialog_get_property;
klass->show_replace = show_replace;
dialog_signals[SHOW_REPLACE] =
g_signal_new ("show_replace",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (XeditSearchDialogClass, show_replace),
NULL, NULL,
xedit_marshal_BOOLEAN__NONE,
G_TYPE_BOOLEAN, 0);
g_object_class_install_property (object_class, PROP_SHOW_REPLACE,
g_param_spec_boolean ("show-replace",
"Show Replace",
"Whether the dialog is used for Search&Replace",
FALSE,
G_PARAM_READWRITE));
g_type_class_add_private (object_class, sizeof (XeditSearchDialogPrivate));
binding_set = gtk_binding_set_by_class (klass);
/* Note: we cannot use the keyval/modifier associated with the
* GTK_STOCK_FIND_AND_REPLACE stock item since MATE HIG suggests Ctrl+h
* for Replace while gtk+ uses Ctrl+r */
gtk_binding_entry_add_signal (binding_set, GDK_KEY_h, GDK_CONTROL_MASK, "show_replace", 0);
gtk_binding_entry_add_signal (binding_set, GDK_KEY_H, GDK_CONTROL_MASK, "show_replace", 0);
}
static void
insert_text_handler (GtkEditable *editable,
const gchar *text,
gint length,
gint *position,
gpointer data)
{
static gboolean insert_text = FALSE;
gchar *escaped_text;
gint new_len;
/* To avoid recursive behavior */
if (insert_text)
return;
escaped_text = xedit_utils_escape_search_text (text);
new_len = strlen (escaped_text);
if (new_len == length)
{
g_free (escaped_text);
return;
}
insert_text = TRUE;
g_signal_stop_emission_by_name (editable, "insert_text");
gtk_editable_insert_text (editable, escaped_text, new_len, position);
insert_text = FALSE;
g_free (escaped_text);
}
static void
search_text_entry_changed (GtkEditable *editable,
XeditSearchDialog *dialog)
{
const gchar *search_string;
search_string = gtk_entry_get_text (GTK_ENTRY (editable));
g_return_if_fail (search_string != NULL);
if (*search_string != '\0')
{
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
XEDIT_SEARCH_DIALOG_FIND_RESPONSE, TRUE);
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
XEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE, TRUE);
}
else
{
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
XEDIT_SEARCH_DIALOG_FIND_RESPONSE, FALSE);
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
XEDIT_SEARCH_DIALOG_REPLACE_RESPONSE, FALSE);
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
XEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE, FALSE);
}
}
static void
response_handler (XeditSearchDialog *dialog,
gint response_id,
gpointer data)
{
const gchar *str;
switch (response_id)
{
case XEDIT_SEARCH_DIALOG_REPLACE_RESPONSE:
case XEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE:
str = gtk_entry_get_text (GTK_ENTRY (dialog->priv->replace_text_entry));
if (*str != '\0')
{
gchar *text;
text = xedit_utils_unescape_search_text (str);
xedit_history_entry_prepend_text
(XEDIT_HISTORY_ENTRY (dialog->priv->replace_entry),
text);
g_free (text);
}
/* fall through, so that we also save the find entry */
case XEDIT_SEARCH_DIALOG_FIND_RESPONSE:
str = gtk_entry_get_text (GTK_ENTRY (dialog->priv->search_text_entry));
if (*str != '\0')
{
gchar *text;
text = xedit_utils_unescape_search_text (str);
xedit_history_entry_prepend_text
(XEDIT_HISTORY_ENTRY (dialog->priv->search_entry),
text);
g_free (text);
}
}
}
static void
show_replace_widgets (XeditSearchDialog *dlg,
gboolean show_replace)
{
if (show_replace)
{
gtk_widget_show (dlg->priv->replace_label);
gtk_widget_show (dlg->priv->replace_entry);
gtk_widget_show (dlg->priv->replace_all_button);
gtk_widget_show (dlg->priv->replace_button);
gtk_table_set_row_spacings (GTK_TABLE (dlg->priv->table), 12);
gtk_window_set_title (GTK_WINDOW (dlg), _("Replace"));
}
else
{
gtk_widget_hide (dlg->priv->replace_label);
gtk_widget_hide (dlg->priv->replace_entry);
gtk_widget_hide (dlg->priv->replace_all_button);
gtk_widget_hide (dlg->priv->replace_button);
gtk_table_set_row_spacings (GTK_TABLE (dlg->priv->table), 0);
gtk_window_set_title (GTK_WINDOW (dlg), _("Find"));
}
gtk_widget_show (dlg->priv->find_button);
}
static void
xedit_search_dialog_init (XeditSearchDialog *dlg)
{
GtkWidget *content;
GtkWidget *error_widget;
gboolean ret;
gchar *file;
gchar *root_objects[] = {
"search_dialog_content",
NULL
};
dlg->priv = XEDIT_SEARCH_DIALOG_GET_PRIVATE (dlg);
gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE);
gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE);
gtk_dialog_add_buttons (GTK_DIALOG (dlg),
GTK_STOCK_CLOSE, GTK_RESPONSE_CANCEL,
NULL);
/* HIG defaults */
gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
2); /* 2 * 5 + 2 = 12 */
gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dlg))),
5);
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dlg))),
6);
file = xedit_dirs_get_ui_file ("xedit-search-dialog.ui");
ret = xedit_utils_get_ui_objects (file,
root_objects,
&error_widget,
"search_dialog_content", &content,
"table", &dlg->priv->table,
"search_label", &dlg->priv->search_label,
"replace_with_label", &dlg->priv->replace_label,
"match_case_checkbutton", &dlg->priv->match_case_checkbutton,
"entire_word_checkbutton", &dlg->priv->entire_word_checkbutton,
"search_backwards_checkbutton", &dlg->priv->backwards_checkbutton,
"wrap_around_checkbutton", &dlg->priv->wrap_around_checkbutton,
"parse_escapes_checkbutton", &dlg->priv->parse_escapes_checkbutton,
NULL);
g_free (file);
if (!ret)
{
gtk_widget_show (error_widget);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
error_widget,
TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (error_widget),
5);
dlg->priv->ui_error = TRUE;
return;
}
dlg->priv->search_entry = xedit_history_entry_new ("history-search-for",
TRUE);
gtk_widget_set_size_request (dlg->priv->search_entry, 300, -1);
xedit_history_entry_set_escape_func
(XEDIT_HISTORY_ENTRY (dlg->priv->search_entry),
(XeditHistoryEntryEscapeFunc) xedit_utils_escape_search_text);
dlg->priv->search_text_entry = xedit_history_entry_get_entry
(XEDIT_HISTORY_ENTRY (dlg->priv->search_entry));
gtk_entry_set_activates_default (GTK_ENTRY (dlg->priv->search_text_entry),
TRUE);
gtk_widget_show (dlg->priv->search_entry);
gtk_table_attach_defaults (GTK_TABLE (dlg->priv->table),
dlg->priv->search_entry,
1, 2, 0, 1);
dlg->priv->replace_entry = xedit_history_entry_new ("history-replace-with",
TRUE);
xedit_history_entry_set_escape_func
(XEDIT_HISTORY_ENTRY (dlg->priv->replace_entry),
(XeditHistoryEntryEscapeFunc) xedit_utils_escape_search_text);
dlg->priv->replace_text_entry = xedit_history_entry_get_entry
(XEDIT_HISTORY_ENTRY (dlg->priv->replace_entry));
gtk_entry_set_activates_default (GTK_ENTRY (dlg->priv->replace_text_entry),
TRUE);
gtk_widget_show (dlg->priv->replace_entry);
gtk_table_attach_defaults (GTK_TABLE (dlg->priv->table),
dlg->priv->replace_entry,
1, 2, 1, 2);
gtk_label_set_mnemonic_widget (GTK_LABEL (dlg->priv->search_label),
dlg->priv->search_entry);
gtk_label_set_mnemonic_widget (GTK_LABEL (dlg->priv->replace_label),
dlg->priv->replace_entry);
dlg->priv->find_button = gtk_button_new_from_stock (GTK_STOCK_FIND);
dlg->priv->replace_all_button = gtk_button_new_with_mnemonic (_("Replace _All"));
dlg->priv->replace_button = xedit_gtk_button_new_with_stock_icon (_("_Replace"),
GTK_STOCK_FIND_AND_REPLACE);
gtk_dialog_add_action_widget (GTK_DIALOG (dlg),
dlg->priv->replace_all_button,
XEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE);
gtk_dialog_add_action_widget (GTK_DIALOG (dlg),
dlg->priv->replace_button,
XEDIT_SEARCH_DIALOG_REPLACE_RESPONSE);
gtk_dialog_add_action_widget (GTK_DIALOG (dlg),
dlg->priv->find_button,
XEDIT_SEARCH_DIALOG_FIND_RESPONSE);
g_object_set (G_OBJECT (dlg->priv->find_button),
"can-default", TRUE,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dlg),
XEDIT_SEARCH_DIALOG_FIND_RESPONSE);
/* insensitive by default */
gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg),
XEDIT_SEARCH_DIALOG_FIND_RESPONSE,
FALSE);
gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg),
XEDIT_SEARCH_DIALOG_REPLACE_RESPONSE,
FALSE);
gtk_dialog_set_response_sensitive (GTK_DIALOG (dlg),
XEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE,
FALSE);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
content, FALSE, FALSE, 0);
g_object_unref (content);
gtk_container_set_border_width (GTK_CONTAINER (content), 5);
g_signal_connect (dlg->priv->search_text_entry,
"insert_text",
G_CALLBACK (insert_text_handler),
NULL);
g_signal_connect (dlg->priv->replace_text_entry,
"insert_text",
G_CALLBACK (insert_text_handler),
NULL);
g_signal_connect (dlg->priv->search_text_entry,
"changed",
G_CALLBACK (search_text_entry_changed),
dlg);
g_signal_connect (dlg,
"response",
G_CALLBACK (response_handler),
NULL);
}
GtkWidget *
xedit_search_dialog_new (GtkWindow *parent,
gboolean show_replace)
{
XeditSearchDialog *dlg;
dlg = g_object_new (XEDIT_TYPE_SEARCH_DIALOG,
"show-replace", show_replace,
NULL);
if (parent != NULL)
{
gtk_window_set_transient_for (GTK_WINDOW (dlg),
parent);
gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg),
TRUE);
}
return GTK_WIDGET (dlg);
}
gboolean
xedit_search_dialog_get_show_replace (XeditSearchDialog *dialog)
{
g_return_val_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog), FALSE);
return dialog->priv->show_replace;
}
void
xedit_search_dialog_set_show_replace (XeditSearchDialog *dialog,
gboolean show_replace)
{
g_return_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog));
if (dialog->priv->ui_error)
return;
dialog->priv->show_replace = show_replace != FALSE;
show_replace_widgets (dialog, dialog->priv->show_replace);
g_object_notify (G_OBJECT (dialog), "show-replace");
}
void
xedit_search_dialog_set_search_text (XeditSearchDialog *dialog,
const gchar *text)
{
g_return_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog));
g_return_if_fail (text != NULL);
gtk_entry_set_text (GTK_ENTRY (dialog->priv->search_text_entry),
text);
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
XEDIT_SEARCH_DIALOG_FIND_RESPONSE,
(text != '\0'));
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
XEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE,
(text != '\0'));
}
/*
* The text must be unescaped before searching.
*/
const gchar *
xedit_search_dialog_get_search_text (XeditSearchDialog *dialog)
{
g_return_val_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog), NULL);
return gtk_entry_get_text (GTK_ENTRY (dialog->priv->search_text_entry));
}
void
xedit_search_dialog_set_replace_text (XeditSearchDialog *dialog,
const gchar *text)
{
g_return_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog));
g_return_if_fail (text != NULL);
gtk_entry_set_text (GTK_ENTRY (dialog->priv->replace_text_entry),
text);
}
const gchar *
xedit_search_dialog_get_replace_text (XeditSearchDialog *dialog)
{
g_return_val_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog), NULL);
return gtk_entry_get_text (GTK_ENTRY (dialog->priv->replace_text_entry));
}
void
xedit_search_dialog_set_match_case (XeditSearchDialog *dialog,
gboolean match_case)
{
g_return_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->match_case_checkbutton),
match_case);
}
gboolean
xedit_search_dialog_get_match_case (XeditSearchDialog *dialog)
{
g_return_val_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog), FALSE);
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->match_case_checkbutton));
}
void
xedit_search_dialog_set_entire_word (XeditSearchDialog *dialog,
gboolean entire_word)
{
g_return_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->entire_word_checkbutton),
entire_word);
}
gboolean
xedit_search_dialog_get_entire_word (XeditSearchDialog *dialog)
{
g_return_val_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog), FALSE);
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->entire_word_checkbutton));
}
void
xedit_search_dialog_set_backwards (XeditSearchDialog *dialog,
gboolean backwards)
{
g_return_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->backwards_checkbutton),
backwards);
}
gboolean
xedit_search_dialog_get_backwards (XeditSearchDialog *dialog)
{
g_return_val_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog), FALSE);
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->backwards_checkbutton));
}
void
xedit_search_dialog_set_wrap_around (XeditSearchDialog *dialog,
gboolean wrap_around)
{
g_return_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->wrap_around_checkbutton),
wrap_around);
}
gboolean
xedit_search_dialog_get_wrap_around (XeditSearchDialog *dialog)
{
g_return_val_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog), FALSE);
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->wrap_around_checkbutton));
}
void
xedit_search_dialog_set_parse_escapes (XeditSearchDialog *dialog,
gboolean parse_escapes)
{
g_return_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->priv->parse_escapes_checkbutton),
parse_escapes);
}
gboolean
xedit_search_dialog_get_parse_escapes (XeditSearchDialog *dialog)
{
g_return_val_if_fail (XEDIT_IS_SEARCH_DIALOG (dialog), FALSE);
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->parse_escapes_checkbutton));
}

View File

@@ -0,0 +1,133 @@
/*
* xedit-search-dialog.h
* This file is part of xedit
*
* Copyright (C) 2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_SEARCH_DIALOG_H__
#define __XEDIT_SEARCH_DIALOG_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_SEARCH_DIALOG (xedit_search_dialog_get_type())
#define XEDIT_SEARCH_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_SEARCH_DIALOG, XeditSearchDialog))
#define XEDIT_SEARCH_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_SEARCH_DIALOG, XeditSearchDialog const))
#define XEDIT_SEARCH_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_SEARCH_DIALOG, XeditSearchDialogClass))
#define XEDIT_IS_SEARCH_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_SEARCH_DIALOG))
#define XEDIT_IS_SEARCH_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_SEARCH_DIALOG))
#define XEDIT_SEARCH_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_SEARCH_DIALOG, XeditSearchDialogClass))
/* Private structure type */
typedef struct _XeditSearchDialogPrivate XeditSearchDialogPrivate;
/*
* Main object structure
*/
typedef struct _XeditSearchDialog XeditSearchDialog;
struct _XeditSearchDialog
{
GtkDialog dialog;
/*< private > */
XeditSearchDialogPrivate *priv;
};
/*
* Class definition
*/
typedef struct _XeditSearchDialogClass XeditSearchDialogClass;
struct _XeditSearchDialogClass
{
GtkDialogClass parent_class;
/* Key bindings */
gboolean (* show_replace) (XeditSearchDialog *dlg);
};
enum
{
XEDIT_SEARCH_DIALOG_FIND_RESPONSE = 100,
XEDIT_SEARCH_DIALOG_REPLACE_RESPONSE,
XEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE
};
/*
* Public methods
*/
GType xedit_search_dialog_get_type (void) G_GNUC_CONST;
GtkWidget *xedit_search_dialog_new (GtkWindow *parent,
gboolean show_replace);
void xedit_search_dialog_present_with_time (XeditSearchDialog *dialog,
guint32 timestamp);
gboolean xedit_search_dialog_get_show_replace (XeditSearchDialog *dialog);
void xedit_search_dialog_set_show_replace (XeditSearchDialog *dialog,
gboolean show_replace);
void xedit_search_dialog_set_search_text (XeditSearchDialog *dialog,
const gchar *text);
const gchar *xedit_search_dialog_get_search_text (XeditSearchDialog *dialog);
void xedit_search_dialog_set_replace_text (XeditSearchDialog *dialog,
const gchar *text);
const gchar *xedit_search_dialog_get_replace_text (XeditSearchDialog *dialog);
void xedit_search_dialog_set_match_case (XeditSearchDialog *dialog,
gboolean match_case);
gboolean xedit_search_dialog_get_match_case (XeditSearchDialog *dialog);
void xedit_search_dialog_set_entire_word (XeditSearchDialog *dialog,
gboolean entire_word);
gboolean xedit_search_dialog_get_entire_word (XeditSearchDialog *dialog);
void xedit_search_dialog_set_backwards (XeditSearchDialog *dialog,
gboolean backwards);
gboolean xedit_search_dialog_get_backwards (XeditSearchDialog *dialog);
void xedit_search_dialog_set_wrap_around (XeditSearchDialog *dialog,
gboolean wrap_around);
gboolean xedit_search_dialog_get_wrap_around (XeditSearchDialog *dialog);
void xedit_search_dialog_set_parse_escapes (XeditSearchDialog *dialog,
gboolean parse_escapes);
gboolean xedit_search_dialog_get_parse_escapes (XeditSearchDialog *dialog);
G_END_DECLS
#endif /* __XEDIT_SEARCH_DIALOG_H__ */

View File

@@ -0,0 +1,272 @@
<?xml version="1.0"?>
<!--*- mode: xml -*-->
<interface>
<object class="GtkDialog" id="dialog">
<property name="title" translatable="yes">Replace</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">False</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">8</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property>
<child>
<object class="GtkButton" id="close_button">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
</object>
</child>
<child>
<object class="GtkButton" id="replace_all_button">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Replace All</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
</object>
</child>
<child>
<object class="GtkButton" id="replace_button">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Replace</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
</object>
</child>
<child>
<object class="GtkButton" id="find_next_button">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-find</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
</object>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="search_dialog_content">
<property name="border_width">5</property>
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">18</property>
<child>
<object class="GtkTable" id="table">
<property name="visible">True</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
<property name="homogeneous">False</property>
<property name="row_spacing">12</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkLabel" id="search_label">
<property name="visible">True</property>
<property name="label" translatable="yes">_Search for: </property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"/>
</packing>
</child>
<child>
<object class="GtkLabel" id="replace_with_label">
<property name="visible">True</property>
<property name="label" translatable="yes">Replace _with: </property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"/>
</packing>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox3">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">12</property>
<child>
<object class="GtkCheckButton" id="match_case_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">_Match case</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="entire_word_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Match _entire word only</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="search_backwards_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Search _backwards</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">False</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="wrap_around_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">_Wrap around</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">True</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="parse_escapes_checkbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">_Parse escape sequences (e.g. \n)</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="active">True</property>
<property name="inconsistent">False</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</object>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">close_button</action-widget>
<action-widget response="0">replace_all_button</action-widget>
<action-widget response="0">replace_button</action-widget>
<action-widget response="0">find_next_button</action-widget>
</action-widgets>
</object>
</interface>

View File

@@ -0,0 +1,39 @@
platform_defines = -DEGG_SM_CLIENT_BACKEND_XSMP
platform_libs = libeggdesktopfile.la
platform_ltlibraries = libeggdesktopfile.la
platform_sources = eggsmclient-xsmp.c
AM_CPPFLAGS = \
-DG_LOG_DOMAIN=\""EggSMClient"\" \
$(XEDIT_CFLAGS) \
$(platform_defines) \
$(EGG_SMCLIENT_CFLAGS)
noinst_LTLIBRARIES = \
libeggsmclient.la \
$(platform_ltlibraries)
libeggsmclient_la_LIBADD = \
$(EGG_SMCLIENT_LIBS) \
$(platform_libs)
libeggsmclient_la_LDFLAGS = \
$(platform_ldflags)
libeggsmclient_la_SOURCES = \
eggsmclient.c \
eggsmclient.h \
eggsmclient-private.h \
$(platform_sources)
libeggdesktopfile_la_LIBADD = \
$(EGG_LIBS)
libeggdesktopfile_la_SOURCES = \
eggdesktopfile.c \
eggdesktopfile.h
EXTRA_DIST = \
eggsmclient-xsmp.c
-include $(top_srcdir)/git.mk

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,160 @@
/* eggdesktopfile.h - Freedesktop.Org Desktop Files
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING.LIB. If not,
* write to the Free Software Foundation, Inc., 151 Franklin Street,
* Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __EGG_DESKTOP_FILE_H__
#define __EGG_DESKTOP_FILE_H__
#include <glib.h>
G_BEGIN_DECLS
typedef struct EggDesktopFile EggDesktopFile;
typedef enum {
EGG_DESKTOP_FILE_TYPE_UNRECOGNIZED,
EGG_DESKTOP_FILE_TYPE_APPLICATION,
EGG_DESKTOP_FILE_TYPE_LINK,
EGG_DESKTOP_FILE_TYPE_DIRECTORY
} EggDesktopFileType;
EggDesktopFile *egg_desktop_file_new (const char *desktop_file_path,
GError **error);
EggDesktopFile *egg_desktop_file_new_from_data_dirs (const char *desktop_file_path,
GError **error);
EggDesktopFile *egg_desktop_file_new_from_dirs (const char *desktop_file_path,
const char **search_dirs,
GError **error);
EggDesktopFile *egg_desktop_file_new_from_key_file (GKeyFile *key_file,
const char *source,
GError **error);
void egg_desktop_file_free (EggDesktopFile *desktop_file);
const char *egg_desktop_file_get_source (EggDesktopFile *desktop_file);
EggDesktopFileType egg_desktop_file_get_desktop_file_type (EggDesktopFile *desktop_file);
const char *egg_desktop_file_get_name (EggDesktopFile *desktop_file);
const char *egg_desktop_file_get_icon (EggDesktopFile *desktop_file);
gboolean egg_desktop_file_can_launch (EggDesktopFile *desktop_file,
const char *desktop_environment);
gboolean egg_desktop_file_accepts_documents (EggDesktopFile *desktop_file);
gboolean egg_desktop_file_accepts_multiple (EggDesktopFile *desktop_file);
gboolean egg_desktop_file_accepts_uris (EggDesktopFile *desktop_file);
char *egg_desktop_file_parse_exec (EggDesktopFile *desktop_file,
GSList *documents,
GError **error);
gboolean egg_desktop_file_launch (EggDesktopFile *desktop_file,
GSList *documents,
GError **error,
...) G_GNUC_NULL_TERMINATED;
typedef enum {
EGG_DESKTOP_FILE_LAUNCH_CLEARENV = 1,
EGG_DESKTOP_FILE_LAUNCH_PUTENV,
EGG_DESKTOP_FILE_LAUNCH_SCREEN,
EGG_DESKTOP_FILE_LAUNCH_WORKSPACE,
EGG_DESKTOP_FILE_LAUNCH_DIRECTORY,
EGG_DESKTOP_FILE_LAUNCH_TIME,
EGG_DESKTOP_FILE_LAUNCH_FLAGS,
EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC,
EGG_DESKTOP_FILE_LAUNCH_RETURN_PID,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE,
EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID
} EggDesktopFileLaunchOption;
/* Standard Keys */
#define EGG_DESKTOP_FILE_GROUP "Desktop Entry"
#define EGG_DESKTOP_FILE_KEY_TYPE "Type"
#define EGG_DESKTOP_FILE_KEY_VERSION "Version"
#define EGG_DESKTOP_FILE_KEY_NAME "Name"
#define EGG_DESKTOP_FILE_KEY_GENERIC_NAME "GenericName"
#define EGG_DESKTOP_FILE_KEY_NO_DISPLAY "NoDisplay"
#define EGG_DESKTOP_FILE_KEY_COMMENT "Comment"
#define EGG_DESKTOP_FILE_KEY_ICON "Icon"
#define EGG_DESKTOP_FILE_KEY_HIDDEN "Hidden"
#define EGG_DESKTOP_FILE_KEY_ONLY_SHOW_IN "OnlyShowIn"
#define EGG_DESKTOP_FILE_KEY_NOT_SHOW_IN "NotShowIn"
#define EGG_DESKTOP_FILE_KEY_TRY_EXEC "TryExec"
#define EGG_DESKTOP_FILE_KEY_EXEC "Exec"
#define EGG_DESKTOP_FILE_KEY_PATH "Path"
#define EGG_DESKTOP_FILE_KEY_TERMINAL "Terminal"
#define EGG_DESKTOP_FILE_KEY_MIME_TYPE "MimeType"
#define EGG_DESKTOP_FILE_KEY_CATEGORIES "Categories"
#define EGG_DESKTOP_FILE_KEY_STARTUP_NOTIFY "StartupNotify"
#define EGG_DESKTOP_FILE_KEY_STARTUP_WM_CLASS "StartupWMClass"
#define EGG_DESKTOP_FILE_KEY_URL "URL"
/* Accessors */
gboolean egg_desktop_file_has_key (EggDesktopFile *desktop_file,
const char *key,
GError **error);
char *egg_desktop_file_get_string (EggDesktopFile *desktop_file,
const char *key,
GError **error) G_GNUC_MALLOC;
char *egg_desktop_file_get_locale_string (EggDesktopFile *desktop_file,
const char *key,
const char *locale,
GError **error) G_GNUC_MALLOC;
gboolean egg_desktop_file_get_boolean (EggDesktopFile *desktop_file,
const char *key,
GError **error);
double egg_desktop_file_get_numeric (EggDesktopFile *desktop_file,
const char *key,
GError **error);
char **egg_desktop_file_get_string_list (EggDesktopFile *desktop_file,
const char *key,
gsize *length,
GError **error) G_GNUC_MALLOC;
char **egg_desktop_file_get_locale_string_list (EggDesktopFile *desktop_file,
const char *key,
const char *locale,
gsize *length,
GError **error) G_GNUC_MALLOC;
/* Errors */
#define EGG_DESKTOP_FILE_ERROR egg_desktop_file_error_quark()
GQuark egg_desktop_file_error_quark (void);
typedef enum {
EGG_DESKTOP_FILE_ERROR_INVALID,
EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION
} EggDesktopFileError;
/* Global application desktop file */
void egg_set_desktop_file (const char *desktop_file_path);
void egg_set_desktop_file_without_defaults (const char *desktop_file_path);
EggDesktopFile *egg_get_desktop_file (void);
G_END_DECLS
#endif /* __EGG_DESKTOP_FILE_H__ */

View File

@@ -0,0 +1,42 @@
/* eggsmclient-private.h
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __EGG_SM_CLIENT_PRIVATE_H__
#define __EGG_SM_CLIENT_PRIVATE_H__
#include <gtk/gtk.h>
#if !GTK_CHECK_VERSION (3, 0, 0)
#include <gdkconfig.h>
#endif
#include "eggsmclient.h"
G_BEGIN_DECLS
GKeyFile *egg_sm_client_save_state (EggSMClient *client);
void egg_sm_client_quit_requested (EggSMClient *client);
void egg_sm_client_quit_cancelled (EggSMClient *client);
void egg_sm_client_quit (EggSMClient *client);
GType egg_sm_client_xsmp_get_type (void);
EggSMClient *egg_sm_client_xsmp_new (void);
G_END_DECLS
#endif /* __EGG_SM_CLIENT_PRIVATE_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,573 @@
/*
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "config.h"
#include <string.h>
#include <glib/gi18n.h>
#include "eggsmclient.h"
#include "eggsmclient-private.h"
static void egg_sm_client_debug_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer user_data);
enum {
SAVE_STATE,
QUIT_REQUESTED,
QUIT_CANCELLED,
QUIT,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
struct _EggSMClientPrivate {
GKeyFile *state_file;
};
#define EGG_SM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_SM_CLIENT, EggSMClientPrivate))
G_DEFINE_TYPE (EggSMClient, egg_sm_client, G_TYPE_OBJECT)
static EggSMClient *global_client;
static EggSMClientMode global_client_mode = EGG_SM_CLIENT_MODE_NORMAL;
static void
egg_sm_client_init (EggSMClient *client)
{
;
}
static void
egg_sm_client_class_init (EggSMClientClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (EggSMClientPrivate));
/**
* EggSMClient::save_state:
* @client: the client
* @state_file: a #GKeyFile to save state information into
*
* Emitted when the session manager has requested that the
* application save information about its current state. The
* application should save its state into @state_file, and then the
* session manager may then restart the application in a future
* session and tell it to initialize itself from that state.
*
* You should not save any data into @state_file's "start group"
* (ie, the %NULL group). Instead, applications should save their
* data into groups with names that start with the application name,
* and libraries that connect to this signal should save their data
* into groups with names that start with the library name.
*
* Alternatively, rather than (or in addition to) using @state_file,
* the application can save its state by calling
* egg_sm_client_set_restart_command() during the processing of this
* signal (eg, to include a list of files to open).
**/
signals[SAVE_STATE] =
g_signal_new ("save_state",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, save_state),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
1, G_TYPE_POINTER);
/**
* EggSMClient::quit_requested:
* @client: the client
*
* Emitted when the session manager requests that the application
* exit (generally because the user is logging out). The application
* should decide whether or not it is willing to quit (perhaps after
* asking the user what to do with documents that have unsaved
* changes) and then call egg_sm_client_will_quit(), passing %TRUE
* or %FALSE to give its answer to the session manager. (It does not
* need to give an answer before returning from the signal handler;
* it can interact with the user asynchronously and then give its
* answer later on.) If the application does not connect to this
* signal, then #EggSMClient will automatically return %TRUE on its
* behalf.
*
* The application should not save its session state as part of
* handling this signal; if the user has requested that the session
* be saved when logging out, then ::save_state will be emitted
* separately.
*
* If the application agrees to quit, it should then wait for either
* the ::quit_cancelled or ::quit signals to be emitted.
**/
signals[QUIT_REQUESTED] =
g_signal_new ("quit_requested",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, quit_requested),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
/**
* EggSMClient::quit_cancelled:
* @client: the client
*
* Emitted when the session manager decides to cancel a logout after
* the application has already agreed to quit. After receiving this
* signal, the application can go back to what it was doing before
* receiving the ::quit_requested signal.
**/
signals[QUIT_CANCELLED] =
g_signal_new ("quit_cancelled",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, quit_cancelled),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
/**
* EggSMClient::quit:
* @client: the client
*
* Emitted when the session manager wants the application to quit
* (generally because the user is logging out). The application
* should exit as soon as possible after receiving this signal; if
* it does not, the session manager may choose to forcibly kill it.
*
* Normally a GUI application would only be sent a ::quit if it
* agreed to quit in response to a ::quit_requested signal. However,
* this is not guaranteed; in some situations the session manager
* may decide to end the session without giving applications a
* chance to object.
**/
signals[QUIT] =
g_signal_new ("quit",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EggSMClientClass, quit),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
}
static gboolean sm_client_disable = FALSE;
static char *sm_client_state_file = NULL;
static char *sm_client_id = NULL;
static char *sm_config_prefix = NULL;
static gboolean
sm_client_post_parse_func (GOptionContext *context,
GOptionGroup *group,
gpointer data,
GError **error)
{
EggSMClient *client = egg_sm_client_get ();
if (sm_client_id == NULL)
{
const gchar *desktop_autostart_id;
desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID");
if (desktop_autostart_id != NULL)
sm_client_id = g_strdup (desktop_autostart_id);
}
/* Unset DESKTOP_AUTOSTART_ID in order to avoid child processes to
* use the same client id. */
g_unsetenv ("DESKTOP_AUTOSTART_ID");
if (EGG_SM_CLIENT_GET_CLASS (client)->startup)
EGG_SM_CLIENT_GET_CLASS (client)->startup (client, sm_client_id);
return TRUE;
}
/**
* egg_sm_client_get_option_group:
*
* Creates a %GOptionGroup containing the session-management-related
* options. You should add this group to the application's
* %GOptionContext if you want to use #EggSMClient.
*
* Return value: the %GOptionGroup
**/
GOptionGroup *
egg_sm_client_get_option_group (void)
{
const GOptionEntry entries[] = {
{ "sm-client-disable", 0, 0,
G_OPTION_ARG_NONE, &sm_client_disable,
N_("Disable connection to session manager"), NULL },
{ "sm-client-state-file", 0, 0,
G_OPTION_ARG_FILENAME, &sm_client_state_file,
N_("Specify file containing saved configuration"), N_("FILE") },
{ "sm-client-id", 0, 0,
G_OPTION_ARG_STRING, &sm_client_id,
N_("Specify session management ID"), N_("ID") },
/* MateClient compatibility option */
{ "sm-disable", 0, G_OPTION_FLAG_HIDDEN,
G_OPTION_ARG_NONE, &sm_client_disable,
NULL, NULL },
/* MateClient compatibility option. This is a dummy option that only
* exists so that sessions saved by apps with MateClient can be restored
* later when they've switched to EggSMClient. See bug #575308.
*/
{ "sm-config-prefix", 0, G_OPTION_FLAG_HIDDEN,
G_OPTION_ARG_STRING, &sm_config_prefix,
NULL, NULL },
{ NULL }
};
GOptionGroup *group;
/* Use our own debug handler for the "EggSMClient" domain. */
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
egg_sm_client_debug_handler, NULL);
group = g_option_group_new ("sm-client",
_("Session management options:"),
_("Show session management options"),
NULL, NULL);
g_option_group_add_entries (group, entries);
g_option_group_set_parse_hooks (group, NULL, sm_client_post_parse_func);
return group;
}
/**
* egg_sm_client_set_mode:
* @mode: an #EggSMClient mode
*
* Sets the "mode" of #EggSMClient as follows:
*
* %EGG_SM_CLIENT_MODE_DISABLED: Session management is completely
* disabled. The application will not even connect to the session
* manager. (egg_sm_client_get() will still return an #EggSMClient,
* but it will just be a dummy object.)
*
* %EGG_SM_CLIENT_MODE_NO_RESTART: The application will connect to
* the session manager (and thus will receive notification when the
* user is logging out, etc), but will request to not be
* automatically restarted with saved state in future sessions.
*
* %EGG_SM_CLIENT_MODE_NORMAL: The default. #EggSMCLient will
* function normally.
*
* This must be called before the application's main loop begins.
**/
void
egg_sm_client_set_mode (EggSMClientMode mode)
{
global_client_mode = mode;
}
/**
* egg_sm_client_get_mode:
*
* Gets the global #EggSMClientMode. See egg_sm_client_set_mode()
* for details.
*
* Return value: the global #EggSMClientMode
**/
EggSMClientMode
egg_sm_client_get_mode (void)
{
return global_client_mode;
}
/**
* egg_sm_client_get:
*
* Returns the master #EggSMClient for the application.
*
* On platforms that support saved sessions (ie, POSIX/X11), the
* application will only request to be restarted by the session
* manager if you call egg_set_desktop_file() to set an application
* desktop file. In particular, if the desktop file contains the key
* "X
*
* Return value: the master #EggSMClient.
**/
EggSMClient *
egg_sm_client_get (void)
{
if (!global_client)
{
if (global_client_mode != EGG_SM_CLIENT_MODE_DISABLED &&
!sm_client_disable)
{
global_client = egg_sm_client_xsmp_new ();
}
/* Fallback: create a dummy client, so that callers don't have
* to worry about a %NULL return value.
*/
if (!global_client)
global_client = g_object_new (EGG_TYPE_SM_CLIENT, NULL);
}
return global_client;
}
/**
* egg_sm_client_is_resumed:
* @client: the client
*
* Checks whether or not the current session has been resumed from
* a previous saved session. If so, the application should call
* egg_sm_client_get_state_file() and restore its state from the
* returned #GKeyFile.
*
* Return value: %TRUE if the session has been resumed
**/
gboolean
egg_sm_client_is_resumed (EggSMClient *client)
{
g_return_val_if_fail (client == global_client, FALSE);
return sm_client_state_file != NULL;
}
/**
* egg_sm_client_get_state_file:
* @client: the client
*
* If the application was resumed by the session manager, this will
* return the #GKeyFile containing its state from the previous
* session.
*
* Note that other libraries and #EggSMClient itself may also store
* state in the key file, so if you call egg_sm_client_get_groups(),
* on it, the return value will likely include groups that you did not
* put there yourself. (It is also not guaranteed that the first
* group created by the application will still be the "start group"
* when it is resumed.)
*
* Return value: the #GKeyFile containing the application's earlier
* state, or %NULL on error. You should not free this key file; it
* is owned by @client.
**/
GKeyFile *
egg_sm_client_get_state_file (EggSMClient *client)
{
EggSMClientPrivate *priv = EGG_SM_CLIENT_GET_PRIVATE (client);
char *state_file_path;
GError *err = NULL;
g_return_val_if_fail (client == global_client, NULL);
if (!sm_client_state_file)
return NULL;
if (priv->state_file)
return priv->state_file;
if (!strncmp (sm_client_state_file, "file://", 7))
state_file_path = g_filename_from_uri (sm_client_state_file, NULL, NULL);
else
state_file_path = g_strdup (sm_client_state_file);
priv->state_file = g_key_file_new ();
if (!g_key_file_load_from_file (priv->state_file, state_file_path, 0, &err))
{
g_warning ("Could not load SM state file '%s': %s",
sm_client_state_file, err->message);
g_clear_error (&err);
g_key_file_free (priv->state_file);
priv->state_file = NULL;
}
g_free (state_file_path);
return priv->state_file;
}
/**
* egg_sm_client_set_restart_command:
* @client: the client
* @argc: the length of @argv
* @argv: argument vector
*
* Sets the command used to restart @client if it does not have a
* .desktop file that can be used to find its restart command.
*
* This can also be used when handling the ::save_state signal, to
* save the current state via an updated command line. (Eg, providing
* a list of filenames to open when the application is resumed.)
**/
void
egg_sm_client_set_restart_command (EggSMClient *client,
int argc,
const char **argv)
{
g_return_if_fail (EGG_IS_SM_CLIENT (client));
if (EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command)
EGG_SM_CLIENT_GET_CLASS (client)->set_restart_command (client, argc, argv);
}
/**
* egg_sm_client_will_quit:
* @client: the client
* @will_quit: whether or not the application is willing to quit
*
* This MUST be called in response to the ::quit_requested signal, to
* indicate whether or not the application is willing to quit. The
* application may call it either directly from the signal handler, or
* at some later point (eg, after asynchronously interacting with the
* user).
*
* If the application does not connect to ::quit_requested,
* #EggSMClient will call this method on its behalf (passing %TRUE
* for @will_quit).
*
* After calling this method, the application should wait to receive
* either ::quit_cancelled or ::quit.
**/
void
egg_sm_client_will_quit (EggSMClient *client,
gboolean will_quit)
{
g_return_if_fail (EGG_IS_SM_CLIENT (client));
if (EGG_SM_CLIENT_GET_CLASS (client)->will_quit)
EGG_SM_CLIENT_GET_CLASS (client)->will_quit (client, will_quit);
}
/**
* egg_sm_client_end_session:
* @style: a hint at how to end the session
* @request_confirmation: whether or not the user should get a chance
* to confirm the action
*
* Requests that the session manager end the current session. @style
* indicates how the session should be ended, and
* @request_confirmation indicates whether or not the user should be
* given a chance to confirm the logout/reboot/shutdown. Both of these
* flags are merely hints though; the session manager may choose to
* ignore them.
*
* Return value: %TRUE if the request was sent; %FALSE if it could not
* be (eg, because it could not connect to the session manager).
**/
gboolean
egg_sm_client_end_session (EggSMClientEndStyle style,
gboolean request_confirmation)
{
EggSMClient *client = egg_sm_client_get ();
g_return_val_if_fail (EGG_IS_SM_CLIENT (client), FALSE);
if (EGG_SM_CLIENT_GET_CLASS (client)->end_session)
{
return EGG_SM_CLIENT_GET_CLASS (client)->end_session (client, style,
request_confirmation);
}
else
return FALSE;
}
/* Signal-emitting callbacks from platform-specific code */
GKeyFile *
egg_sm_client_save_state (EggSMClient *client)
{
GKeyFile *state_file;
char *group;
g_return_val_if_fail (client == global_client, NULL);
state_file = g_key_file_new ();
g_debug ("Emitting save_state");
g_signal_emit (client, signals[SAVE_STATE], 0, state_file);
g_debug ("Done emitting save_state");
group = g_key_file_get_start_group (state_file);
if (group)
{
g_free (group);
return state_file;
}
else
{
g_key_file_free (state_file);
return NULL;
}
}
void
egg_sm_client_quit_requested (EggSMClient *client)
{
g_return_if_fail (client == global_client);
if (!g_signal_has_handler_pending (client, signals[QUIT_REQUESTED], 0, FALSE))
{
g_debug ("Not emitting quit_requested because no one is listening");
egg_sm_client_will_quit (client, TRUE);
return;
}
g_debug ("Emitting quit_requested");
g_signal_emit (client, signals[QUIT_REQUESTED], 0);
g_debug ("Done emitting quit_requested");
}
void
egg_sm_client_quit_cancelled (EggSMClient *client)
{
g_return_if_fail (client == global_client);
g_debug ("Emitting quit_cancelled");
g_signal_emit (client, signals[QUIT_CANCELLED], 0);
g_debug ("Done emitting quit_cancelled");
}
void
egg_sm_client_quit (EggSMClient *client)
{
g_return_if_fail (client == global_client);
g_debug ("Emitting quit");
g_signal_emit (client, signals[QUIT], 0);
g_debug ("Done emitting quit");
/* FIXME: should we just call gtk_main_quit() here? */
}
static void
egg_sm_client_debug_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer user_data)
{
static int debug = -1;
if (debug < 0)
debug = (g_getenv ("EGG_SM_CLIENT_DEBUG") != NULL);
if (debug)
g_log_default_handler (log_domain, log_level, message, NULL);
}

View File

@@ -0,0 +1,117 @@
/* eggsmclient.h
* Copyright (C) 2007 Novell, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __EGG_SM_CLIENT_H__
#define __EGG_SM_CLIENT_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define EGG_TYPE_SM_CLIENT (egg_sm_client_get_type ())
#define EGG_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT, EggSMClient))
#define EGG_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT, EggSMClientClass))
#define EGG_IS_SM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT))
#define EGG_IS_SM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT))
#define EGG_SM_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT, EggSMClientClass))
typedef struct _EggSMClient EggSMClient;
typedef struct _EggSMClientClass EggSMClientClass;
typedef struct _EggSMClientPrivate EggSMClientPrivate;
typedef enum {
EGG_SM_CLIENT_END_SESSION_DEFAULT,
EGG_SM_CLIENT_LOGOUT,
EGG_SM_CLIENT_REBOOT,
EGG_SM_CLIENT_SHUTDOWN
} EggSMClientEndStyle;
typedef enum {
EGG_SM_CLIENT_MODE_DISABLED,
EGG_SM_CLIENT_MODE_NO_RESTART,
EGG_SM_CLIENT_MODE_NORMAL
} EggSMClientMode;
struct _EggSMClient
{
GObject parent;
};
struct _EggSMClientClass
{
GObjectClass parent_class;
/* signals */
void (*save_state) (EggSMClient *client,
GKeyFile *state_file);
void (*quit_requested) (EggSMClient *client);
void (*quit_cancelled) (EggSMClient *client);
void (*quit) (EggSMClient *client);
/* virtual methods */
void (*startup) (EggSMClient *client,
const char *client_id);
void (*set_restart_command) (EggSMClient *client,
int argc,
const char **argv);
void (*will_quit) (EggSMClient *client,
gboolean will_quit);
gboolean (*end_session) (EggSMClient *client,
EggSMClientEndStyle style,
gboolean request_confirmation);
/* Padding for future expansion */
void (*_egg_reserved1) (void);
void (*_egg_reserved2) (void);
void (*_egg_reserved3) (void);
void (*_egg_reserved4) (void);
};
GType egg_sm_client_get_type (void) G_GNUC_CONST;
GOptionGroup *egg_sm_client_get_option_group (void);
/* Initialization */
void egg_sm_client_set_mode (EggSMClientMode mode);
EggSMClientMode egg_sm_client_get_mode (void);
EggSMClient *egg_sm_client_get (void);
/* Resuming a saved session */
gboolean egg_sm_client_is_resumed (EggSMClient *client);
GKeyFile *egg_sm_client_get_state_file (EggSMClient *client);
/* Alternate means of saving state */
void egg_sm_client_set_restart_command (EggSMClient *client,
int argc,
const char **argv);
/* Handling "quit_requested" signal */
void egg_sm_client_will_quit (EggSMClient *client,
gboolean will_quit);
/* Initiate a logout/reboot/shutdown */
gboolean egg_sm_client_end_session (EggSMClientEndStyle style,
gboolean request_confirmation);
G_END_DECLS
#endif /* __EGG_SM_CLIENT_H__ */

898
xedit/xedit-app.c Normal file
View File

@@ -0,0 +1,898 @@
/*
* xedit-app.c
* This file is part of xedit
*
* Copyright (C) 2005-2006 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <unistd.h>
#include <glib/gi18n.h>
#include "xedit-app.h"
#include "xedit-prefs-manager-app.h"
#include "xedit-commands.h"
#include "xedit-notebook.h"
#include "xedit-debug.h"
#include "xedit-utils.h"
#include "xedit-enum-types.h"
#include "xedit-dirs.h"
#define XEDIT_PAGE_SETUP_FILE "xedit-page-setup"
#define XEDIT_PRINT_SETTINGS_FILE "xedit-print-settings"
#define XEDIT_APP_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), XEDIT_TYPE_APP, XeditAppPrivate))
/* Properties */
enum
{
PROP_0,
PROP_LOCKDOWN
};
struct _XeditAppPrivate
{
GList *windows;
XeditWindow *active_window;
XeditLockdownMask lockdown;
GtkPageSetup *page_setup;
GtkPrintSettings *print_settings;
};
G_DEFINE_TYPE(XeditApp, xedit_app, G_TYPE_OBJECT)
static void
xedit_app_finalize (GObject *object)
{
XeditApp *app = XEDIT_APP (object);
g_list_free (app->priv->windows);
if (app->priv->page_setup)
g_object_unref (app->priv->page_setup);
if (app->priv->print_settings)
g_object_unref (app->priv->print_settings);
G_OBJECT_CLASS (xedit_app_parent_class)->finalize (object);
}
static void
xedit_app_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XeditApp *app = XEDIT_APP (object);
switch (prop_id)
{
case PROP_LOCKDOWN:
g_value_set_flags (value, xedit_app_get_lockdown (app));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_app_class_init (XeditAppClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = xedit_app_finalize;
object_class->get_property = xedit_app_get_property;
g_object_class_install_property (object_class,
PROP_LOCKDOWN,
g_param_spec_flags ("lockdown",
"Lockdown",
"The lockdown mask",
XEDIT_TYPE_LOCKDOWN_MASK,
0,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
g_type_class_add_private (object_class, sizeof(XeditAppPrivate));
}
static gboolean
ensure_user_config_dir (void)
{
gchar *config_dir;
gboolean ret = TRUE;
gint res;
config_dir = xedit_dirs_get_user_config_dir ();
if (config_dir == NULL)
{
g_warning ("Could not get config directory\n");
return FALSE;
}
res = g_mkdir_with_parents (config_dir, 0755);
if (res < 0)
{
g_warning ("Could not create config directory\n");
ret = FALSE;
}
g_free (config_dir);
return ret;
}
static void
load_accels (void)
{
gchar *filename;
filename = xedit_dirs_get_user_accels_file ();
if (filename != NULL)
{
xedit_debug_message (DEBUG_APP, "Loading keybindings from %s\n", filename);
gtk_accel_map_load (filename);
g_free (filename);
}
}
static void
save_accels (void)
{
gchar *filename;
filename = xedit_dirs_get_user_accels_file ();
if (filename != NULL)
{
xedit_debug_message (DEBUG_APP, "Saving keybindings in %s\n", filename);
gtk_accel_map_save (filename);
g_free (filename);
}
}
static gchar *
get_page_setup_file (void)
{
gchar *config_dir;
gchar *setup = NULL;
config_dir = xedit_dirs_get_user_config_dir ();
if (config_dir != NULL)
{
setup = g_build_filename (config_dir,
XEDIT_PAGE_SETUP_FILE,
NULL);
g_free (config_dir);
}
return setup;
}
static void
load_page_setup (XeditApp *app)
{
gchar *filename;
GError *error = NULL;
g_return_if_fail (app->priv->page_setup == NULL);
filename = get_page_setup_file ();
app->priv->page_setup = gtk_page_setup_new_from_file (filename,
&error);
if (error)
{
/* Ignore file not found error */
if (error->domain != G_FILE_ERROR ||
error->code != G_FILE_ERROR_NOENT)
{
g_warning ("%s", error->message);
}
g_error_free (error);
}
g_free (filename);
/* fall back to default settings */
if (app->priv->page_setup == NULL)
app->priv->page_setup = gtk_page_setup_new ();
}
static void
save_page_setup (XeditApp *app)
{
gchar *filename;
GError *error = NULL;
if (app->priv->page_setup == NULL)
return;
filename = get_page_setup_file ();
gtk_page_setup_to_file (app->priv->page_setup,
filename,
&error);
if (error)
{
g_warning ("%s", error->message);
g_error_free (error);
}
g_free (filename);
}
static gchar *
get_print_settings_file (void)
{
gchar *config_dir;
gchar *settings = NULL;
config_dir = xedit_dirs_get_user_config_dir ();
if (config_dir != NULL)
{
settings = g_build_filename (config_dir,
XEDIT_PRINT_SETTINGS_FILE,
NULL);
g_free (config_dir);
}
return settings;
}
static void
load_print_settings (XeditApp *app)
{
gchar *filename;
GError *error = NULL;
g_return_if_fail (app->priv->print_settings == NULL);
filename = get_print_settings_file ();
app->priv->print_settings = gtk_print_settings_new_from_file (filename,
&error);
if (error)
{
/* Ignore file not found error */
if (error->domain != G_FILE_ERROR ||
error->code != G_FILE_ERROR_NOENT)
{
g_warning ("%s", error->message);
}
g_error_free (error);
}
g_free (filename);
/* fall back to default settings */
if (app->priv->print_settings == NULL)
app->priv->print_settings = gtk_print_settings_new ();
}
static void
save_print_settings (XeditApp *app)
{
gchar *filename;
GError *error = NULL;
if (app->priv->print_settings == NULL)
return;
filename = get_print_settings_file ();
gtk_print_settings_to_file (app->priv->print_settings,
filename,
&error);
if (error)
{
g_warning ("%s", error->message);
g_error_free (error);
}
g_free (filename);
}
static void
xedit_app_init (XeditApp *app)
{
app->priv = XEDIT_APP_GET_PRIVATE (app);
load_accels ();
/* initial lockdown state */
app->priv->lockdown = xedit_prefs_manager_get_lockdown ();
}
static void
app_weak_notify (gpointer data,
GObject *where_the_app_was)
{
gtk_main_quit ();
}
/**
* xedit_app_get_default:
*
* Returns the #XeditApp object. This object is a singleton and
* represents the running xedit instance.
*
* Return value: the #XeditApp pointer
*/
XeditApp *
xedit_app_get_default (void)
{
static XeditApp *app = NULL;
if (app != NULL)
return app;
app = XEDIT_APP (g_object_new (XEDIT_TYPE_APP, NULL));
g_object_add_weak_pointer (G_OBJECT (app),
(gpointer) &app);
g_object_weak_ref (G_OBJECT (app),
app_weak_notify,
NULL);
return app;
}
static void
set_active_window (XeditApp *app,
XeditWindow *window)
{
app->priv->active_window = window;
}
static gboolean
window_focus_in_event (XeditWindow *window,
GdkEventFocus *event,
XeditApp *app)
{
/* updates active_view and active_child when a new toplevel receives focus */
g_return_val_if_fail (XEDIT_IS_WINDOW (window), FALSE);
set_active_window (app, window);
return FALSE;
}
static gboolean
window_delete_event (XeditWindow *window,
GdkEvent *event,
XeditApp *app)
{
XeditWindowState ws;
ws = xedit_window_get_state (window);
if (ws &
(XEDIT_WINDOW_STATE_SAVING |
XEDIT_WINDOW_STATE_PRINTING |
XEDIT_WINDOW_STATE_SAVING_SESSION))
return TRUE;
_xedit_cmd_file_quit (NULL, window);
/* Do not destroy the window */
return TRUE;
}
static void
window_destroy (XeditWindow *window,
XeditApp *app)
{
app->priv->windows = g_list_remove (app->priv->windows,
window);
if (window == app->priv->active_window)
{
set_active_window (app, app->priv->windows != NULL ? app->priv->windows->data : NULL);
}
/* CHECK: I don't think we have to disconnect this function, since windows
is being destroyed */
/*
g_signal_handlers_disconnect_by_func (window,
G_CALLBACK (window_focus_in_event),
app);
g_signal_handlers_disconnect_by_func (window,
G_CALLBACK (window_destroy),
app);
*/
if (app->priv->windows == NULL)
{
/* Last window is gone... save some settings and exit */
ensure_user_config_dir ();
save_accels ();
save_page_setup (app);
save_print_settings (app);
g_object_unref (app);
}
}
/* Generates a unique string for a window role */
static gchar *
gen_role (void)
{
GTimeVal result;
static gint serial;
g_get_current_time (&result);
return g_strdup_printf ("xedit-window-%ld-%ld-%d-%s",
result.tv_sec,
result.tv_usec,
serial++,
g_get_host_name ());
}
static XeditWindow *
xedit_app_create_window_real (XeditApp *app,
gboolean set_geometry,
const gchar *role)
{
XeditWindow *window;
xedit_debug (DEBUG_APP);
/*
* We need to be careful here, there is a race condition:
* when another xedit is launched it checks active_window,
* so we must do our best to ensure that active_window
* is never NULL when at least a window exists.
*/
if (app->priv->windows == NULL)
{
window = g_object_new (XEDIT_TYPE_WINDOW, NULL);
set_active_window (app, window);
}
else
{
window = g_object_new (XEDIT_TYPE_WINDOW, NULL);
}
app->priv->windows = g_list_prepend (app->priv->windows,
window);
xedit_debug_message (DEBUG_APP, "Window created");
if (role != NULL)
{
gtk_window_set_role (GTK_WINDOW (window), role);
}
else
{
gchar *newrole;
newrole = gen_role ();
gtk_window_set_role (GTK_WINDOW (window), newrole);
g_free (newrole);
}
if (set_geometry)
{
GdkWindowState state;
gint w, h;
state = xedit_prefs_manager_get_window_state ();
if ((state & GDK_WINDOW_STATE_MAXIMIZED) != 0)
{
xedit_prefs_manager_get_default_window_size (&w, &h);
gtk_window_set_default_size (GTK_WINDOW (window), w, h);
gtk_window_maximize (GTK_WINDOW (window));
}
else
{
xedit_prefs_manager_get_window_size (&w, &h);
gtk_window_set_default_size (GTK_WINDOW (window), w, h);
gtk_window_unmaximize (GTK_WINDOW (window));
}
if ((state & GDK_WINDOW_STATE_STICKY ) != 0)
gtk_window_stick (GTK_WINDOW (window));
else
gtk_window_unstick (GTK_WINDOW (window));
}
g_signal_connect (window,
"focus_in_event",
G_CALLBACK (window_focus_in_event),
app);
g_signal_connect (window,
"delete_event",
G_CALLBACK (window_delete_event),
app);
g_signal_connect (window,
"destroy",
G_CALLBACK (window_destroy),
app);
return window;
}
/**
* xedit_app_create_window:
* @app: the #XeditApp
* @screen: (allow-none):
*
* Create a new #XeditWindow part of @app.
*
* Return value: the new #XeditWindow
*/
XeditWindow *
xedit_app_create_window (XeditApp *app,
GdkScreen *screen)
{
XeditWindow *window;
window = xedit_app_create_window_real (app, TRUE, NULL);
if (screen != NULL)
gtk_window_set_screen (GTK_WINDOW (window), screen);
return window;
}
/*
* Same as _create_window, but doesn't set the geometry.
* The session manager takes care of it. Used in mate-session.
*/
XeditWindow *
_xedit_app_restore_window (XeditApp *app,
const gchar *role)
{
XeditWindow *window;
window = xedit_app_create_window_real (app, FALSE, role);
return window;
}
/**
* xedit_app_get_windows:
* @app: the #XeditApp
*
* Returns all the windows currently present in #XeditApp.
*
* Return value: (transfer none): the list of #XeditWindows objects.
* The list should not be freed
*/
const GList *
xedit_app_get_windows (XeditApp *app)
{
g_return_val_if_fail (XEDIT_IS_APP (app), NULL);
return app->priv->windows;
}
/**
* xedit_app_get_active_window:
* @app: the #XeditApp
*
* Retrives the #XeditWindow currently active.
*
* Return value: the active #XeditWindow
*/
XeditWindow *
xedit_app_get_active_window (XeditApp *app)
{
g_return_val_if_fail (XEDIT_IS_APP (app), NULL);
/* make sure our active window is always realized:
* this is needed on startup if we launch two xedit fast
* enough that the second instance comes up before the
* first one shows its window.
*/
if (!gtk_widget_get_realized (GTK_WIDGET (app->priv->active_window)))
gtk_widget_realize (GTK_WIDGET (app->priv->active_window));
return app->priv->active_window;
}
static gboolean
is_in_viewport (XeditWindow *window,
GdkScreen *screen,
gint workspace,
gint viewport_x,
gint viewport_y)
{
GdkScreen *s;
GdkDisplay *display;
GdkWindow *gdkwindow;
const gchar *cur_name;
const gchar *name;
gint cur_n;
gint n;
gint ws;
gint sc_width, sc_height;
gint x, y, width, height;
gint vp_x, vp_y;
/* Check for screen and display match */
display = gdk_screen_get_display (screen);
cur_name = gdk_display_get_name (display);
cur_n = gdk_screen_get_number (screen);
s = gtk_window_get_screen (GTK_WINDOW (window));
display = gdk_screen_get_display (s);
name = gdk_display_get_name (display);
n = gdk_screen_get_number (s);
if (strcmp (cur_name, name) != 0 || cur_n != n)
return FALSE;
/* Check for workspace match */
ws = xedit_utils_get_window_workspace (GTK_WINDOW (window));
if (ws != workspace && ws != XEDIT_ALL_WORKSPACES)
return FALSE;
/* Check for viewport match */
gdkwindow = gtk_widget_get_window (GTK_WIDGET (window));
gdk_window_get_position (gdkwindow, &x, &y);
width = gdk_window_get_width(gdkwindow);
height = gdk_window_get_height(gdkwindow);
xedit_utils_get_current_viewport (screen, &vp_x, &vp_y);
x += vp_x;
y += vp_y;
sc_width = gdk_screen_get_width (screen);
sc_height = gdk_screen_get_height (screen);
return x + width * .25 >= viewport_x &&
x + width * .75 <= viewport_x + sc_width &&
y >= viewport_y &&
y + height <= viewport_y + sc_height;
}
/**
* _xedit_app_get_window_in_viewport
* @app: the #XeditApp
* @screen: the #GdkScreen
* @workspace: the workspace number
* @viewport_x: the viewport horizontal origin
* @viewport_y: the viewport vertical origin
*
* Since a workspace can be larger than the screen, it is divided into several
* equal parts called viewports. This function retrives the #XeditWindow in
* the given viewport of the given workspace.
*
* Return value: the #XeditWindow in the given viewport of the given workspace.
*/
XeditWindow *
_xedit_app_get_window_in_viewport (XeditApp *app,
GdkScreen *screen,
gint workspace,
gint viewport_x,
gint viewport_y)
{
XeditWindow *window;
GList *l;
g_return_val_if_fail (XEDIT_IS_APP (app), NULL);
/* first try if the active window */
window = app->priv->active_window;
g_return_val_if_fail (XEDIT_IS_WINDOW (window), NULL);
if (is_in_viewport (window, screen, workspace, viewport_x, viewport_y))
return window;
/* otherwise try to see if there is a window on this workspace */
for (l = app->priv->windows; l != NULL; l = l->next)
{
window = l->data;
if (is_in_viewport (window, screen, workspace, viewport_x, viewport_y))
return window;
}
/* no window on this workspace... create a new one */
return xedit_app_create_window (app, screen);
}
/**
* xedit_app_get_documents:
* @app: the #XeditApp
*
* Returns all the documents currently open in #XeditApp.
*
* Return value: (element-type Xedit.Document) (transfer container):
* a newly allocated list of #XeditDocument objects
*/
GList *
xedit_app_get_documents (XeditApp *app)
{
GList *res = NULL;
GList *windows;
g_return_val_if_fail (XEDIT_IS_APP (app), NULL);
windows = app->priv->windows;
while (windows != NULL)
{
res = g_list_concat (res,
xedit_window_get_documents (XEDIT_WINDOW (windows->data)));
windows = g_list_next (windows);
}
return res;
}
/**
* xedit_app_get_views:
* @app: the #XeditApp
*
* Returns all the views currently present in #XeditApp.
*
* Return value: (element-type Xedit.View) (transfer container):
* a newly allocated list of #XeditView objects
*/
GList *
xedit_app_get_views (XeditApp *app)
{
GList *res = NULL;
GList *windows;
g_return_val_if_fail (XEDIT_IS_APP (app), NULL);
windows = app->priv->windows;
while (windows != NULL)
{
res = g_list_concat (res,
xedit_window_get_views (XEDIT_WINDOW (windows->data)));
windows = g_list_next (windows);
}
return res;
}
/**
* xedit_app_get_lockdown:
* @app: a #XeditApp
*
* Gets the lockdown mask (see #XeditLockdownMask) for the application.
* The lockdown mask determines which functions are locked down using
* the MATE-wise lockdown GSettings keys.
**/
XeditLockdownMask
xedit_app_get_lockdown (XeditApp *app)
{
g_return_val_if_fail (XEDIT_IS_APP (app), XEDIT_LOCKDOWN_ALL);
return app->priv->lockdown;
}
static void
app_lockdown_changed (XeditApp *app)
{
GList *l;
for (l = app->priv->windows; l != NULL; l = l->next)
_xedit_window_set_lockdown (XEDIT_WINDOW (l->data),
app->priv->lockdown);
g_object_notify (G_OBJECT (app), "lockdown");
}
void
_xedit_app_set_lockdown (XeditApp *app,
XeditLockdownMask lockdown)
{
g_return_if_fail (XEDIT_IS_APP (app));
app->priv->lockdown = lockdown;
app_lockdown_changed (app);
}
void
_xedit_app_set_lockdown_bit (XeditApp *app,
XeditLockdownMask bit,
gboolean value)
{
g_return_if_fail (XEDIT_IS_APP (app));
if (value)
app->priv->lockdown |= bit;
else
app->priv->lockdown &= ~bit;
app_lockdown_changed (app);
}
/* Returns a copy */
GtkPageSetup *
_xedit_app_get_default_page_setup (XeditApp *app)
{
g_return_val_if_fail (XEDIT_IS_APP (app), NULL);
if (app->priv->page_setup == NULL)
load_page_setup (app);
return gtk_page_setup_copy (app->priv->page_setup);
}
void
_xedit_app_set_default_page_setup (XeditApp *app,
GtkPageSetup *page_setup)
{
g_return_if_fail (XEDIT_IS_APP (app));
g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
if (app->priv->page_setup != NULL)
g_object_unref (app->priv->page_setup);
app->priv->page_setup = g_object_ref (page_setup);
}
/* Returns a copy */
GtkPrintSettings *
_xedit_app_get_default_print_settings (XeditApp *app)
{
g_return_val_if_fail (XEDIT_IS_APP (app), NULL);
if (app->priv->print_settings == NULL)
load_print_settings (app);
return gtk_print_settings_copy (app->priv->print_settings);
}
void
_xedit_app_set_default_print_settings (XeditApp *app,
GtkPrintSettings *settings)
{
g_return_if_fail (XEDIT_IS_APP (app));
g_return_if_fail (GTK_IS_PRINT_SETTINGS (settings));
if (app->priv->print_settings != NULL)
g_object_unref (app->priv->print_settings);
app->priv->print_settings = g_object_ref (settings);
}

142
xedit/xedit-app.h Normal file
View File

@@ -0,0 +1,142 @@
/*
* xedit-app.h
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_APP_H__
#define __XEDIT_APP_H__
#include <gtk/gtk.h>
#include <xedit/xedit-window.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_APP (xedit_app_get_type())
#define XEDIT_APP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_APP, XeditApp))
#define XEDIT_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_APP, XeditAppClass))
#define XEDIT_IS_APP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_APP))
#define XEDIT_IS_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_APP))
#define XEDIT_APP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_APP, XeditAppClass))
/* Private structure type */
typedef struct _XeditAppPrivate XeditAppPrivate;
/*
* Main object structure
*/
typedef struct _XeditApp XeditApp;
struct _XeditApp
{
GObject object;
/*< private > */
XeditAppPrivate *priv;
};
/*
* Class definition
*/
typedef struct _XeditAppClass XeditAppClass;
struct _XeditAppClass
{
GObjectClass parent_class;
};
/*
* Lockdown mask definition
*/
typedef enum
{
XEDIT_LOCKDOWN_COMMAND_LINE = 1 << 0,
XEDIT_LOCKDOWN_PRINTING = 1 << 1,
XEDIT_LOCKDOWN_PRINT_SETUP = 1 << 2,
XEDIT_LOCKDOWN_SAVE_TO_DISK = 1 << 3,
XEDIT_LOCKDOWN_ALL = 0xF
} XeditLockdownMask;
/*
* Public methods
*/
GType xedit_app_get_type (void) G_GNUC_CONST;
XeditApp *xedit_app_get_default (void);
XeditWindow *xedit_app_create_window (XeditApp *app,
GdkScreen *screen);
const GList *xedit_app_get_windows (XeditApp *app);
XeditWindow *xedit_app_get_active_window (XeditApp *app);
/* Returns a newly allocated list with all the documents */
GList *xedit_app_get_documents (XeditApp *app);
/* Returns a newly allocated list with all the views */
GList *xedit_app_get_views (XeditApp *app);
/* Lockdown state */
XeditLockdownMask xedit_app_get_lockdown (XeditApp *app);
/*
* Non exported functions
*/
XeditWindow *_xedit_app_restore_window (XeditApp *app,
const gchar *role);
XeditWindow *_xedit_app_get_window_in_viewport (XeditApp *app,
GdkScreen *screen,
gint workspace,
gint viewport_x,
gint viewport_y);
void _xedit_app_set_lockdown (XeditApp *app,
XeditLockdownMask lockdown);
void _xedit_app_set_lockdown_bit (XeditApp *app,
XeditLockdownMask bit,
gboolean value);
/*
* This one is a xedit-window function, but we declare it here to avoid
* #include headaches since it needs the XeditLockdownMask declaration.
*/
void _xedit_window_set_lockdown (XeditWindow *window,
XeditLockdownMask lockdown);
/* global print config */
GtkPageSetup *_xedit_app_get_default_page_setup (XeditApp *app);
void _xedit_app_set_default_page_setup (XeditApp *app,
GtkPageSetup *page_setup);
GtkPrintSettings *_xedit_app_get_default_print_settings (XeditApp *app);
void _xedit_app_set_default_print_settings (XeditApp *app,
GtkPrintSettings *settings);
G_END_DECLS
#endif /* __XEDIT_APP_H__ */

View File

@@ -0,0 +1,84 @@
/*
* xedit-close-button.c
* This file is part of xedit
*
* Copyright (C) 2010 - Paolo Borelli
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "xedit-close-button.h"
G_DEFINE_TYPE (XeditCloseButton, xedit_close_button, GTK_TYPE_BUTTON)
static void
xedit_close_button_style_set (GtkWidget *button,
GtkStyle *previous_style)
{
gint h, w;
#if GTK_CHECK_VERSION (3, 10, 0)
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
#else
gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (button),
GTK_ICON_SIZE_MENU, &w, &h);
#endif
gtk_widget_set_size_request (button, w + 2, h + 2);
GTK_WIDGET_CLASS (xedit_close_button_parent_class)->style_set (button, previous_style);
}
static void
xedit_close_button_class_init (XeditCloseButtonClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->style_set = xedit_close_button_style_set;
}
static void
xedit_close_button_init (XeditCloseButton *button)
{
GtkRcStyle *rcstyle;
GtkWidget *image;
/* make it as small as possible */
rcstyle = gtk_rc_style_new ();
rcstyle->xthickness = rcstyle->ythickness = 0;
gtk_widget_modify_style (GTK_WIDGET (button), rcstyle);
g_object_unref (rcstyle);
image = gtk_image_new_from_stock (GTK_STOCK_CLOSE,
GTK_ICON_SIZE_MENU);
gtk_widget_show (image);
gtk_container_add (GTK_CONTAINER (button), image);
}
GtkWidget *
xedit_close_button_new ()
{
XeditCloseButton *button;
button = g_object_new (XEDIT_TYPE_CLOSE_BUTTON,
"relief", GTK_RELIEF_NONE,
"focus-on-click", FALSE,
NULL);
return GTK_WIDGET (button);
}

View File

@@ -0,0 +1,56 @@
/*
* xedit-close-button.h
* This file is part of xedit
*
* Copyright (C) 2010 - Paolo Borelli
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __XEDIT_CLOSE_BUTTON_H__
#define __XEDIT_CLOSE_BUTTON_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define XEDIT_TYPE_CLOSE_BUTTON (xedit_close_button_get_type ())
#define XEDIT_CLOSE_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_CLOSE_BUTTON, XeditCloseButton))
#define XEDIT_CLOSE_BUTTON_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_CLOSE_BUTTON, XeditCloseButton const))
#define XEDIT_CLOSE_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XEDIT_TYPE_CLOSE_BUTTON, XeditCloseButtonClass))
#define XEDIT_IS_CLOSE_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XEDIT_TYPE_CLOSE_BUTTON))
#define XEDIT_IS_CLOSE_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_CLOSE_BUTTON))
#define XEDIT_CLOSE_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XEDIT_TYPE_CLOSE_BUTTON, XeditCloseButtonClass))
typedef struct _XeditCloseButton XeditCloseButton;
typedef struct _XeditCloseButtonClass XeditCloseButtonClass;
typedef struct _XeditCloseButtonPrivate XeditCloseButtonPrivate;
struct _XeditCloseButton {
GtkButton parent;
};
struct _XeditCloseButtonClass {
GtkButtonClass parent_class;
};
GType xedit_close_button_get_type (void) G_GNUC_CONST;
GtkWidget *xedit_close_button_new (void);
G_END_DECLS
#endif /* __XEDIT_CLOSE_BUTTON_H__ */

View File

@@ -0,0 +1,87 @@
/*
* xedit-documents-commands.c
* This file is part of xedit
*
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 1998-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gtk/gtk.h>
#include "xedit-commands.h"
#include "xedit-window.h"
#include "xedit-notebook.h"
#include "xedit-debug.h"
void
_xedit_cmd_documents_previous_document (GtkAction *action,
XeditWindow *window)
{
GtkNotebook *notebook;
xedit_debug (DEBUG_COMMANDS);
notebook = GTK_NOTEBOOK (_xedit_window_get_notebook (window));
gtk_notebook_prev_page (notebook);
}
void
_xedit_cmd_documents_next_document (GtkAction *action,
XeditWindow *window)
{
GtkNotebook *notebook;
xedit_debug (DEBUG_COMMANDS);
notebook = GTK_NOTEBOOK (_xedit_window_get_notebook (window));
gtk_notebook_next_page (notebook);
}
void
_xedit_cmd_documents_move_to_new_window (GtkAction *action,
XeditWindow *window)
{
XeditNotebook *old_notebook;
XeditTab *tab;
xedit_debug (DEBUG_COMMANDS);
tab = xedit_window_get_active_tab (window);
if (tab == NULL)
return;
old_notebook = XEDIT_NOTEBOOK (_xedit_window_get_notebook (window));
g_return_if_fail (gtk_notebook_get_n_pages (GTK_NOTEBOOK (old_notebook)) > 1);
_xedit_window_move_tab_to_new_window (window, tab);
}

174
xedit/xedit-commands-edit.c Normal file
View File

@@ -0,0 +1,174 @@
/*
* xedit-commands-edit.c
* This file is part of xedit
*
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 1998-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gtk/gtk.h>
#include "xedit-commands.h"
#include "xedit-window.h"
#include "xedit-debug.h"
#include "xedit-view.h"
#include "dialogs/xedit-preferences-dialog.h"
void
_xedit_cmd_edit_undo (GtkAction *action,
XeditWindow *window)
{
XeditView *active_view;
GtkSourceBuffer *active_document;
xedit_debug (DEBUG_COMMANDS);
active_view = xedit_window_get_active_view (window);
g_return_if_fail (active_view);
active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
gtk_source_buffer_undo (active_document);
xedit_view_scroll_to_cursor (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
void
_xedit_cmd_edit_redo (GtkAction *action,
XeditWindow *window)
{
XeditView *active_view;
GtkSourceBuffer *active_document;
xedit_debug (DEBUG_COMMANDS);
active_view = xedit_window_get_active_view (window);
g_return_if_fail (active_view);
active_document = GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
gtk_source_buffer_redo (active_document);
xedit_view_scroll_to_cursor (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
void
_xedit_cmd_edit_cut (GtkAction *action,
XeditWindow *window)
{
XeditView *active_view;
xedit_debug (DEBUG_COMMANDS);
active_view = xedit_window_get_active_view (window);
g_return_if_fail (active_view);
xedit_view_cut_clipboard (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
void
_xedit_cmd_edit_copy (GtkAction *action,
XeditWindow *window)
{
XeditView *active_view;
xedit_debug (DEBUG_COMMANDS);
active_view = xedit_window_get_active_view (window);
g_return_if_fail (active_view);
xedit_view_copy_clipboard (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
void
_xedit_cmd_edit_paste (GtkAction *action,
XeditWindow *window)
{
XeditView *active_view;
xedit_debug (DEBUG_COMMANDS);
active_view = xedit_window_get_active_view (window);
g_return_if_fail (active_view);
xedit_view_paste_clipboard (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
void
_xedit_cmd_edit_delete (GtkAction *action,
XeditWindow *window)
{
XeditView *active_view;
xedit_debug (DEBUG_COMMANDS);
active_view = xedit_window_get_active_view (window);
g_return_if_fail (active_view);
xedit_view_delete_selection (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
void
_xedit_cmd_edit_select_all (GtkAction *action,
XeditWindow *window)
{
XeditView *active_view;
xedit_debug (DEBUG_COMMANDS);
active_view = xedit_window_get_active_view (window);
g_return_if_fail (active_view);
xedit_view_select_all (active_view);
gtk_widget_grab_focus (GTK_WIDGET (active_view));
}
void
_xedit_cmd_edit_preferences (GtkAction *action,
XeditWindow *window)
{
xedit_debug (DEBUG_COMMANDS);
xedit_show_preferences_dialog (window);
}

View File

@@ -0,0 +1,74 @@
/*
* xedit-commands-file-print.c
* This file is part of xedit
*
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 1998-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "xedit-commands.h"
#include "xedit-window.h"
#include "xedit-tab.h"
#include "xedit-debug.h"
void
_xedit_cmd_file_print_preview (GtkAction *action,
XeditWindow *window)
{
XeditTab *tab;
xedit_debug (DEBUG_COMMANDS);
tab = xedit_window_get_active_tab (window);
if (tab == NULL)
return;
_xedit_tab_print_preview (tab);
}
void
_xedit_cmd_file_print (GtkAction *action,
XeditWindow *window)
{
XeditTab *tab;
xedit_debug (DEBUG_COMMANDS);
tab = xedit_window_get_active_tab (window);
if (tab == NULL)
return;
_xedit_tab_print (tab);
}

1847
xedit/xedit-commands-file.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
/*
* xedit-help-commands.c
* This file is part of xedit
*
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
* Copyright (C) 2002-2005 Paolo Maggi
* Copyright (C) 2011 Perberos
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the gedit Team, 1998-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include "xedit-commands.h"
#include "xedit-debug.h"
#include "xedit-help.h"
#include "xedit-dirs.h"
void _xedit_cmd_help_contents(GtkAction* action, XeditWindow* window)
{
xedit_debug(DEBUG_COMMANDS);
xedit_help_display(GTK_WINDOW(window), NULL, NULL);
}
void _xedit_cmd_help_about(GtkAction* action, XeditWindow* window)
{
static const gchar* const authors[] = {
"Paolo Maggi <paolo@gnome.org>",
"Paolo Borelli <pborelli@katamail.com>",
"Steve Fr\303\251cinaux <steve@istique.net>",
"Jesse van den Kieboom <jessevdk@gnome.org>",
"Ignacio Casal Quinteiro <icq@gnome.org>",
"James Willcox <jwillcox@gnome.org>",
"Chema Celorio",
"Federico Mena Quintero <federico@novell.com>",
"Perberos <perberos@gmail.com>",
NULL
};
static const gchar* const documenters[] = {
"Sun GNOME Documentation Team <gdocteam@sun.com>",
"Eric Baudais <baudais@okstate.edu>",
NULL
};
static const gchar copyright[] = \
"Copyright \xc2\xa9 1998-2000 Evan Lawrence, Alex Robert\n"
"Copyright \xc2\xa9 2000-2002 Chema Celorio, Paolo Maggi\n"
"Copyright \xc2\xa9 2003-2006 Paolo Maggi\n"
"Copyright \xc2\xa9 2004-2010 Paolo Borelli, Jesse van den Kieboom\nSteve Fr\303\251cinaux, Ignacio Casal Quinteiro\n"
"Copyright \xc2\xa9 2011 Perberos\n"
"Copyright \xc2\xa9 2012-2014 MATE developers";
static const gchar comments[] = \
N_("Xedit is a small and lightweight text editor for the MATE Desktop");
xedit_debug (DEBUG_COMMANDS);
gtk_show_about_dialog(GTK_WINDOW(window),
"program-name", "Xedit",
"authors", authors,
"comments", _(comments),
"copyright", copyright,
"documenters", documenters,
"logo_icon_name", "accessories-text-editor",
"translator-credits", _("translator-credits"),
"version", VERSION,
"website", "http://mate-desktop.org",
NULL);
}

View File

@@ -0,0 +1,793 @@
/*
* xedit-search-commands.c
* This file is part of xedit
*
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
* Copyright (C) 2002-2006 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 1998-2006. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#if GTK_CHECK_VERSION (3, 0, 0)
#define GTK_OBJECT G_OBJECT
#endif
#include "xedit-commands.h"
#include "xedit-debug.h"
#include "xedit-statusbar.h"
#include "xedit-window.h"
#include "xedit-window-private.h"
#include "xedit-utils.h"
#include "dialogs/xedit-search-dialog.h"
#define XEDIT_SEARCH_DIALOG_KEY "xedit-search-dialog-key"
#define XEDIT_LAST_SEARCH_DATA_KEY "xedit-last-search-data-key"
typedef struct _LastSearchData LastSearchData;
struct _LastSearchData
{
gint x;
gint y;
};
static void
last_search_data_free (LastSearchData *data)
{
g_slice_free (LastSearchData, data);
}
static void
last_search_data_restore_position (XeditSearchDialog *dlg)
{
LastSearchData *data;
data = g_object_get_data (G_OBJECT (dlg), XEDIT_LAST_SEARCH_DATA_KEY);
if (data != NULL)
{
gtk_window_move (GTK_WINDOW (dlg),
data->x,
data->y);
}
}
static void
last_search_data_store_position (XeditSearchDialog *dlg)
{
LastSearchData *data;
data = g_object_get_data (G_OBJECT (dlg), XEDIT_LAST_SEARCH_DATA_KEY);
if (data == NULL)
{
data = g_slice_new (LastSearchData);
g_object_set_data_full (G_OBJECT (dlg),
XEDIT_LAST_SEARCH_DATA_KEY,
data,
(GDestroyNotify) last_search_data_free);
}
gtk_window_get_position (GTK_WINDOW (dlg),
&data->x,
&data->y);
}
/* Use occurrences only for Replace All */
static void
text_found (XeditWindow *window,
gint occurrences)
{
if (occurrences > 1)
{
xedit_statusbar_flash_message (XEDIT_STATUSBAR (window->priv->statusbar),
window->priv->generic_message_cid,
ngettext("Found and replaced %d occurrence",
"Found and replaced %d occurrences",
occurrences),
occurrences);
}
else
{
if (occurrences == 1)
xedit_statusbar_flash_message (XEDIT_STATUSBAR (window->priv->statusbar),
window->priv->generic_message_cid,
_("Found and replaced one occurrence"));
else
xedit_statusbar_flash_message (XEDIT_STATUSBAR (window->priv->statusbar),
window->priv->generic_message_cid,
" ");
}
}
#define MAX_MSG_LENGTH 40
static void
text_not_found (XeditWindow *window,
const gchar *text)
{
gchar *searched;
searched = xedit_utils_str_end_truncate (text, MAX_MSG_LENGTH);
xedit_statusbar_flash_message (XEDIT_STATUSBAR (window->priv->statusbar),
window->priv->generic_message_cid,
/* Translators: %s is replaced by the text
entered by the user in the search box */
_("\"%s\" not found"), searched);
g_free (searched);
}
static gboolean
run_search (XeditView *view,
gboolean wrap_around,
gboolean search_backwards)
{
XeditDocument *doc;
GtkTextIter start_iter;
GtkTextIter match_start;
GtkTextIter match_end;
gboolean found = FALSE;
doc = XEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)));
if (!search_backwards)
{
gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc),
NULL,
&start_iter);
found = xedit_document_search_forward (doc,
&start_iter,
NULL,
&match_start,
&match_end);
}
else
{
gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (doc),
&start_iter,
NULL);
found = xedit_document_search_backward (doc,
NULL,
&start_iter,
&match_start,
&match_end);
}
if (!found && wrap_around)
{
if (!search_backwards)
found = xedit_document_search_forward (doc,
NULL,
NULL, /* FIXME: set the end_inter */
&match_start,
&match_end);
else
found = xedit_document_search_backward (doc,
NULL, /* FIXME: set the start_inter */
NULL,
&match_start,
&match_end);
}
if (found)
{
gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc),
&match_start);
gtk_text_buffer_move_mark_by_name (GTK_TEXT_BUFFER (doc),
"selection_bound",
&match_end);
xedit_view_scroll_to_cursor (view);
}
else
{
gtk_text_buffer_place_cursor (GTK_TEXT_BUFFER (doc),
&start_iter);
}
return found;
}
static void
do_find (XeditSearchDialog *dialog,
XeditWindow *window)
{
XeditView *active_view;
XeditDocument *doc;
gchar *search_text;
const gchar *entry_text;
gboolean match_case;
gboolean entire_word;
gboolean wrap_around;
gboolean search_backwards;
gboolean parse_escapes;
guint flags = 0;
guint old_flags = 0;
gboolean found;
/* TODO: make the dialog insensitive when all the tabs are closed
* and assert here that the view is not NULL */
active_view = xedit_window_get_active_view (window);
if (active_view == NULL)
return;
doc = XEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
match_case = xedit_search_dialog_get_match_case (dialog);
entire_word = xedit_search_dialog_get_entire_word (dialog);
search_backwards = xedit_search_dialog_get_backwards (dialog);
wrap_around = xedit_search_dialog_get_wrap_around (dialog);
parse_escapes = xedit_search_dialog_get_parse_escapes (dialog);
if (!parse_escapes) {
entry_text = xedit_utils_escape_search_text (xedit_search_dialog_get_search_text (dialog));
} else {
entry_text = xedit_search_dialog_get_search_text (dialog);
}
XEDIT_SEARCH_SET_CASE_SENSITIVE (flags, match_case);
XEDIT_SEARCH_SET_ENTIRE_WORD (flags, entire_word);
search_text = xedit_document_get_search_text (doc, &old_flags);
if ((search_text == NULL) ||
(strcmp (search_text, entry_text) != 0) ||
(flags != old_flags))
{
xedit_document_set_search_text (doc, entry_text, flags);
}
g_free (search_text);
found = run_search (active_view,
wrap_around,
search_backwards);
if (found)
text_found (window, 0);
else {
if (!parse_escapes) {
text_not_found (window, xedit_utils_unescape_search_text (entry_text));
} else {
text_not_found (window, entry_text);
}
}
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
XEDIT_SEARCH_DIALOG_REPLACE_RESPONSE,
found);
}
/* FIXME: move in xedit-document.c and share it with xedit-view */
static gboolean
get_selected_text (GtkTextBuffer *doc,
gchar **selected_text,
gint *len)
{
GtkTextIter start, end;
g_return_val_if_fail (selected_text != NULL, FALSE);
g_return_val_if_fail (*selected_text == NULL, FALSE);
if (!gtk_text_buffer_get_selection_bounds (doc, &start, &end))
{
if (len != NULL)
len = 0;
return FALSE;
}
*selected_text = gtk_text_buffer_get_slice (doc, &start, &end, TRUE);
if (len != NULL)
*len = g_utf8_strlen (*selected_text, -1);
return TRUE;
}
static void
replace_selected_text (GtkTextBuffer *buffer,
const gchar *replace)
{
g_return_if_fail (gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL));
g_return_if_fail (replace != NULL);
gtk_text_buffer_begin_user_action (buffer);
gtk_text_buffer_delete_selection (buffer, FALSE, TRUE);
gtk_text_buffer_insert_at_cursor (buffer, replace, strlen (replace));
gtk_text_buffer_end_user_action (buffer);
}
static void
do_replace (XeditSearchDialog *dialog,
XeditWindow *window)
{
XeditDocument *doc;
const gchar *search_entry_text;
const gchar *replace_entry_text;
gchar *unescaped_search_text;
gchar *unescaped_replace_text;
gchar *selected_text = NULL;
gboolean match_case;
gboolean parse_escapes;
doc = xedit_window_get_active_document (window);
if (doc == NULL)
return;
parse_escapes = xedit_search_dialog_get_parse_escapes (dialog);
if (!parse_escapes) {
search_entry_text = xedit_utils_escape_search_text (xedit_search_dialog_get_search_text (dialog));
} else {
search_entry_text = xedit_search_dialog_get_search_text (dialog);
}
g_return_if_fail ((search_entry_text) != NULL);
g_return_if_fail ((*search_entry_text) != '\0');
/* replace text may be "", we just delete */
if (!parse_escapes) {
replace_entry_text = xedit_utils_escape_search_text (xedit_search_dialog_get_replace_text (dialog));
} else {
replace_entry_text = xedit_search_dialog_get_replace_text (dialog);
}
g_return_if_fail ((replace_entry_text) != NULL);
unescaped_search_text = xedit_utils_unescape_search_text (search_entry_text);
get_selected_text (GTK_TEXT_BUFFER (doc),
&selected_text,
NULL);
match_case = xedit_search_dialog_get_match_case (dialog);
if ((selected_text == NULL) ||
(match_case && (strcmp (selected_text, unescaped_search_text) != 0)) ||
(!match_case && !g_utf8_caselessnmatch (selected_text,
unescaped_search_text,
strlen (selected_text),
strlen (unescaped_search_text)) != 0))
{
do_find (dialog, window);
g_free (unescaped_search_text);
g_free (selected_text);
return;
}
unescaped_replace_text = xedit_utils_unescape_search_text (replace_entry_text);
replace_selected_text (GTK_TEXT_BUFFER (doc), unescaped_replace_text);
g_free (unescaped_search_text);
g_free (selected_text);
g_free (unescaped_replace_text);
do_find (dialog, window);
}
static void
do_replace_all (XeditSearchDialog *dialog,
XeditWindow *window)
{
XeditView *active_view;
XeditDocument *doc;
const gchar *search_entry_text;
const gchar *replace_entry_text;
gboolean match_case;
gboolean entire_word;
gboolean parse_escapes;
guint flags = 0;
gint count;
active_view = xedit_window_get_active_view (window);
if (active_view == NULL)
return;
doc = XEDIT_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (active_view)));
parse_escapes = xedit_search_dialog_get_parse_escapes (dialog);
if (!parse_escapes) {
search_entry_text = xedit_utils_escape_search_text(xedit_search_dialog_get_search_text (dialog));
} else {
search_entry_text = xedit_search_dialog_get_search_text (dialog);
}
g_return_if_fail ((search_entry_text) != NULL);
g_return_if_fail ((*search_entry_text) != '\0');
/* replace text may be "", we just delete all occurrencies */
if (!parse_escapes) {
replace_entry_text = xedit_utils_escape_search_text (xedit_search_dialog_get_replace_text (dialog));
} else {
replace_entry_text = xedit_search_dialog_get_replace_text (dialog);
}
g_return_if_fail ((replace_entry_text) != NULL);
match_case = xedit_search_dialog_get_match_case (dialog);
entire_word = xedit_search_dialog_get_entire_word (dialog);
XEDIT_SEARCH_SET_CASE_SENSITIVE (flags, match_case);
XEDIT_SEARCH_SET_ENTIRE_WORD (flags, entire_word);
count = xedit_document_replace_all (doc,
search_entry_text,
replace_entry_text,
flags);
if (count > 0)
{
text_found (window, count);
}
else
{
if (!parse_escapes) {
text_not_found (window, xedit_utils_unescape_search_text (search_entry_text));
} else {
text_not_found (window, search_entry_text);
}
}
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
XEDIT_SEARCH_DIALOG_REPLACE_RESPONSE,
FALSE);
}
static void
search_dialog_response_cb (XeditSearchDialog *dialog,
gint response_id,
XeditWindow *window)
{
xedit_debug (DEBUG_COMMANDS);
switch (response_id)
{
case XEDIT_SEARCH_DIALOG_FIND_RESPONSE:
do_find (dialog, window);
break;
case XEDIT_SEARCH_DIALOG_REPLACE_RESPONSE:
do_replace (dialog, window);
break;
case XEDIT_SEARCH_DIALOG_REPLACE_ALL_RESPONSE:
do_replace_all (dialog, window);
break;
default:
last_search_data_store_position (dialog);
gtk_widget_hide (GTK_WIDGET (dialog));
}
}
static gboolean
search_dialog_delete_event_cb (GtkWidget *widget,
GdkEventAny *event,
gpointer user_data)
{
xedit_debug (DEBUG_COMMANDS);
/* prevent destruction */
return TRUE;
}
static void
search_dialog_destroyed (XeditWindow *window,
XeditSearchDialog *dialog)
{
xedit_debug (DEBUG_COMMANDS);
g_object_set_data (G_OBJECT (window),
XEDIT_SEARCH_DIALOG_KEY,
NULL);
g_object_set_data (G_OBJECT (dialog),
XEDIT_LAST_SEARCH_DATA_KEY,
NULL);
}
static GtkWidget *
create_dialog (XeditWindow *window, gboolean show_replace)
{
GtkWidget *dialog;
dialog = xedit_search_dialog_new (GTK_WINDOW (window), show_replace);
g_signal_connect (dialog,
"response",
G_CALLBACK (search_dialog_response_cb),
window);
g_signal_connect (dialog,
"delete-event",
G_CALLBACK (search_dialog_delete_event_cb),
NULL);
g_object_set_data (G_OBJECT (window),
XEDIT_SEARCH_DIALOG_KEY,
dialog);
g_object_weak_ref (G_OBJECT (dialog),
(GWeakNotify) search_dialog_destroyed,
window);
return dialog;
}
void
_xedit_cmd_search_find (GtkAction *action,
XeditWindow *window)
{
gpointer data;
GtkWidget *search_dialog;
XeditDocument *doc;
gboolean selection_exists;
gboolean parse_escapes;
gchar *find_text = NULL;
const gchar *search_text = NULL;
gint sel_len;
xedit_debug (DEBUG_COMMANDS);
data = g_object_get_data (G_OBJECT (window), XEDIT_SEARCH_DIALOG_KEY);
if (data == NULL)
{
search_dialog = create_dialog (window, FALSE);
}
else
{
g_return_if_fail (XEDIT_IS_SEARCH_DIALOG (data));
search_dialog = GTK_WIDGET (data);
/* turn the dialog into a find dialog if needed */
if (xedit_search_dialog_get_show_replace (XEDIT_SEARCH_DIALOG (search_dialog)))
xedit_search_dialog_set_show_replace (XEDIT_SEARCH_DIALOG (search_dialog),
FALSE);
}
doc = xedit_window_get_active_document (window);
g_return_if_fail (doc != NULL);
selection_exists = get_selected_text (GTK_TEXT_BUFFER (doc),
&find_text,
&sel_len);
if (selection_exists && find_text != NULL && sel_len < 80)
{
/*
* Special case: if the currently selected text
* is the same as the unescaped search text and
* escape sequence parsing is activated, use the
* same old search text. (Without this, if you e.g.
* search for '\n' in escaped mode and then open
* the search dialog again, you'll get an unprintable
* single-character literal '\n' in the "search for"
* box).
*/
parse_escapes = xedit_search_dialog_get_parse_escapes (XEDIT_SEARCH_DIALOG (search_dialog));
search_text = xedit_search_dialog_get_search_text (XEDIT_SEARCH_DIALOG (search_dialog));
if (!(search_text != NULL
&& !strcmp(xedit_utils_unescape_search_text(search_text), find_text)
&& parse_escapes)) {
/* General case */
xedit_search_dialog_set_search_text (XEDIT_SEARCH_DIALOG (search_dialog),
find_text);
}
g_free (find_text);
}
else
{
g_free (find_text);
}
gtk_widget_show (search_dialog);
last_search_data_restore_position (XEDIT_SEARCH_DIALOG (search_dialog));
xedit_search_dialog_present_with_time (XEDIT_SEARCH_DIALOG (search_dialog),
GDK_CURRENT_TIME);
}
void
_xedit_cmd_search_replace (GtkAction *action,
XeditWindow *window)
{
gpointer data;
GtkWidget *replace_dialog;
XeditDocument *doc;
gboolean selection_exists;
gboolean parse_escapes;
gchar *find_text = NULL;
const gchar *search_text = NULL;
gint sel_len;
xedit_debug (DEBUG_COMMANDS);
data = g_object_get_data (G_OBJECT (window), XEDIT_SEARCH_DIALOG_KEY);
if (data == NULL)
{
replace_dialog = create_dialog (window, TRUE);
}
else
{
g_return_if_fail (XEDIT_IS_SEARCH_DIALOG (data));
replace_dialog = GTK_WIDGET (data);
/* turn the dialog into a find dialog if needed */
if (!xedit_search_dialog_get_show_replace (XEDIT_SEARCH_DIALOG (replace_dialog)))
xedit_search_dialog_set_show_replace (XEDIT_SEARCH_DIALOG (replace_dialog),
TRUE);
}
doc = xedit_window_get_active_document (window);
g_return_if_fail (doc != NULL);
selection_exists = get_selected_text (GTK_TEXT_BUFFER (doc),
&find_text,
&sel_len);
if (selection_exists && find_text != NULL && sel_len < 80)
{
/*
* Special case: if the currently selected text
* is the same as the unescaped search text and
* escape sequence parsing is activated, use the
* same old search text. (Without this, if you e.g.
* search for '\n' in escaped mode and then open
* the search dialog again, you'll get an unprintable
* single-character literal '\n' in the "search for"
* box).
*/
parse_escapes = xedit_search_dialog_get_parse_escapes (XEDIT_SEARCH_DIALOG (replace_dialog));
search_text = xedit_search_dialog_get_search_text (XEDIT_SEARCH_DIALOG (replace_dialog));
if (!(search_text != NULL
&& !strcmp(xedit_utils_unescape_search_text(search_text), find_text)
&& parse_escapes)) {
/* General case */
xedit_search_dialog_set_search_text (XEDIT_SEARCH_DIALOG (replace_dialog),
find_text);
}
g_free (find_text);
}
else
{
g_free (find_text);
}
gtk_widget_show (replace_dialog);
last_search_data_restore_position (XEDIT_SEARCH_DIALOG (replace_dialog));
xedit_search_dialog_present_with_time (XEDIT_SEARCH_DIALOG (replace_dialog),
GDK_CURRENT_TIME);
}
static void
do_find_again (XeditWindow *window,
gboolean backward)
{
XeditView *active_view;
gboolean wrap_around = TRUE;
gpointer data;
active_view = xedit_window_get_active_view (window);
g_return_if_fail (active_view != NULL);
data = g_object_get_data (G_OBJECT (window), XEDIT_SEARCH_DIALOG_KEY);
if (data != NULL)
wrap_around = xedit_search_dialog_get_wrap_around (XEDIT_SEARCH_DIALOG (data));
run_search (active_view,
wrap_around,
backward);
}
void
_xedit_cmd_search_find_next (GtkAction *action,
XeditWindow *window)
{
xedit_debug (DEBUG_COMMANDS);
do_find_again (window, FALSE);
}
void
_xedit_cmd_search_find_prev (GtkAction *action,
XeditWindow *window)
{
xedit_debug (DEBUG_COMMANDS);
do_find_again (window, TRUE);
}
void
_xedit_cmd_search_clear_highlight (GtkAction *action,
XeditWindow *window)
{
XeditDocument *doc;
xedit_debug (DEBUG_COMMANDS);
doc = xedit_window_get_active_document (window);
xedit_document_set_search_text (XEDIT_DOCUMENT (doc),
"",
XEDIT_SEARCH_DONT_SET_FLAGS);
}
void
_xedit_cmd_search_goto_line (GtkAction *action,
XeditWindow *window)
{
XeditView *active_view;
xedit_debug (DEBUG_COMMANDS);
active_view = xedit_window_get_active_view (window);
if (active_view == NULL)
return;
/* Focus the view if needed: we need to focus the view otherwise
activating the binding for goto line has no effect */
gtk_widget_grab_focus (GTK_WIDGET (active_view));
/* goto line is builtin in XeditView, just activate
* the corrisponding binding.
*/
gtk_bindings_activate (GTK_OBJECT (active_view),
GDK_KEY_i,
GDK_CONTROL_MASK);
}
void
_xedit_cmd_search_incremental_search (GtkAction *action,
XeditWindow *window)
{
XeditView *active_view;
xedit_debug (DEBUG_COMMANDS);
active_view = xedit_window_get_active_view (window);
if (active_view == NULL)
return;
/* Focus the view if needed: we need to focus the view otherwise
activating the binding for incremental search has no effect */
gtk_widget_grab_focus (GTK_WIDGET (active_view));
/* incremental search is builtin in XeditView, just activate
* the corrisponding binding.
*/
gtk_bindings_activate (GTK_OBJECT (active_view),
GDK_KEY_k,
GDK_CONTROL_MASK);
}

154
xedit/xedit-commands-view.c Normal file
View File

@@ -0,0 +1,154 @@
/*
* xedit-view-commands.c
* This file is part of xedit
*
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 1998-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gtk/gtk.h>
#include "xedit-commands.h"
#include "xedit-debug.h"
#include "xedit-window.h"
#include "xedit-window-private.h"
void
_xedit_cmd_view_show_toolbar (GtkAction *action,
XeditWindow *window)
{
gboolean visible;
xedit_debug (DEBUG_COMMANDS);
visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
if (visible)
gtk_widget_show (window->priv->toolbar);
else
gtk_widget_hide (window->priv->toolbar);
}
void
_xedit_cmd_view_show_statusbar (GtkAction *action,
XeditWindow *window)
{
gboolean visible;
xedit_debug (DEBUG_COMMANDS);
visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
if (visible)
gtk_widget_show (window->priv->statusbar);
else
gtk_widget_hide (window->priv->statusbar);
}
void
_xedit_cmd_view_show_side_pane (GtkAction *action,
XeditWindow *window)
{
gboolean visible;
XeditPanel *panel;
xedit_debug (DEBUG_COMMANDS);
visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
panel = xedit_window_get_side_panel (window);
if (visible)
{
gtk_widget_show (GTK_WIDGET (panel));
gtk_widget_grab_focus (GTK_WIDGET (panel));
}
else
{
gtk_widget_hide (GTK_WIDGET (panel));
}
}
void
_xedit_cmd_view_show_bottom_pane (GtkAction *action,
XeditWindow *window)
{
gboolean visible;
XeditPanel *panel;
xedit_debug (DEBUG_COMMANDS);
visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
panel = xedit_window_get_bottom_panel (window);
if (visible)
{
gtk_widget_show (GTK_WIDGET (panel));
gtk_widget_grab_focus (GTK_WIDGET (panel));
}
else
{
gtk_widget_hide (GTK_WIDGET (panel));
}
}
void
_xedit_cmd_view_toggle_fullscreen_mode (GtkAction *action,
XeditWindow *window)
{
xedit_debug (DEBUG_COMMANDS);
if (_xedit_window_is_fullscreen (window))
_xedit_window_unfullscreen (window);
else
_xedit_window_fullscreen (window);
}
void
_xedit_cmd_view_leave_fullscreen_mode (GtkAction *action,
XeditWindow *window)
{
GtkAction *view_action;
view_action = gtk_action_group_get_action (window->priv->always_sensitive_action_group,
"ViewFullscreen");
g_signal_handlers_block_by_func
(view_action, G_CALLBACK (_xedit_cmd_view_toggle_fullscreen_mode),
window);
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (view_action),
FALSE);
_xedit_window_unfullscreen (window);
g_signal_handlers_unblock_by_func
(view_action, G_CALLBACK (_xedit_cmd_view_toggle_fullscreen_mode),
window);
}

159
xedit/xedit-commands.h Normal file
View File

@@ -0,0 +1,159 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xedit-commands.h
* This file is part of xedit
*
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 1998-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_COMMANDS_H__
#define __XEDIT_COMMANDS_H__
#include <gtk/gtk.h>
#include <xedit/xedit-window.h>
G_BEGIN_DECLS
/* Do nothing if URI does not exist */
void xedit_commands_load_uri (XeditWindow *window,
const gchar *uri,
const XeditEncoding *encoding,
gint line_pos);
/* Ignore non-existing URIs */
gint xedit_commands_load_uris (XeditWindow *window,
const GSList *uris,
const XeditEncoding *encoding,
gint line_pos);
void xedit_commands_save_document (XeditWindow *window,
XeditDocument *document);
void xedit_commands_save_all_documents (XeditWindow *window);
/*
* Non-exported functions
*/
/* Create titled documens for non-existing URIs */
gint _xedit_cmd_load_files_from_prompt (XeditWindow *window,
GSList *files,
const XeditEncoding *encoding,
gint line_pos);
void _xedit_cmd_file_new (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_file_open (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_file_save (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_file_save_as (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_file_save_all (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_file_revert (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_file_open_uri (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_file_print_preview (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_file_print (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_file_close (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_file_close_all (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_file_quit (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_edit_undo (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_edit_redo (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_edit_cut (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_edit_copy (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_edit_paste (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_edit_delete (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_edit_select_all (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_edit_preferences (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_view_show_toolbar (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_view_show_statusbar (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_view_show_side_pane (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_view_show_bottom_pane (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_view_toggle_fullscreen_mode (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_view_leave_fullscreen_mode (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_search_find (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_search_find_next (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_search_find_prev (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_search_replace (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_search_clear_highlight (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_search_goto_line (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_search_incremental_search (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_documents_previous_document (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_documents_next_document (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_documents_move_to_new_window (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_help_contents (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_help_about (GtkAction *action,
XeditWindow *window);
void _xedit_cmd_file_close_tab (XeditTab *tab,
XeditWindow *window);
void _xedit_cmd_file_save_documents_list (XeditWindow *window,
GList *docs);
G_END_DECLS
#endif /* __XEDIT_COMMANDS_H__ */

158
xedit/xedit-debug.c Normal file
View File

@@ -0,0 +1,158 @@
/*
* xedit-debug.c
* This file is part of xedit
*
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
* Copyright (C) 2002 - 2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 1998-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include "xedit-debug.h"
#define ENABLE_PROFILING
#ifdef ENABLE_PROFILING
static GTimer *timer = NULL;
static gdouble last = 0.0;
#endif
static XeditDebugSection debug = XEDIT_NO_DEBUG;
void
xedit_debug_init (void)
{
if (g_getenv ("XEDIT_DEBUG") != NULL)
{
/* enable all debugging */
debug = ~XEDIT_NO_DEBUG;
goto out;
}
if (g_getenv ("XEDIT_DEBUG_VIEW") != NULL)
debug = debug | XEDIT_DEBUG_VIEW;
if (g_getenv ("XEDIT_DEBUG_SEARCH") != NULL)
debug = debug | XEDIT_DEBUG_SEARCH;
if (g_getenv ("XEDIT_DEBUG_PREFS") != NULL)
debug = debug | XEDIT_DEBUG_PREFS;
if (g_getenv ("XEDIT_DEBUG_PRINT") != NULL)
debug = debug | XEDIT_DEBUG_PRINT;
if (g_getenv ("XEDIT_DEBUG_PLUGINS") != NULL)
debug = debug | XEDIT_DEBUG_PLUGINS;
if (g_getenv ("XEDIT_DEBUG_TAB") != NULL)
debug = debug | XEDIT_DEBUG_TAB;
if (g_getenv ("XEDIT_DEBUG_DOCUMENT") != NULL)
debug = debug | XEDIT_DEBUG_DOCUMENT;
if (g_getenv ("XEDIT_DEBUG_COMMANDS") != NULL)
debug = debug | XEDIT_DEBUG_COMMANDS;
if (g_getenv ("XEDIT_DEBUG_APP") != NULL)
debug = debug | XEDIT_DEBUG_APP;
if (g_getenv ("XEDIT_DEBUG_SESSION") != NULL)
debug = debug | XEDIT_DEBUG_SESSION;
if (g_getenv ("XEDIT_DEBUG_UTILS") != NULL)
debug = debug | XEDIT_DEBUG_UTILS;
if (g_getenv ("XEDIT_DEBUG_METADATA") != NULL)
debug = debug | XEDIT_DEBUG_METADATA;
if (g_getenv ("XEDIT_DEBUG_WINDOW") != NULL)
debug = debug | XEDIT_DEBUG_WINDOW;
if (g_getenv ("XEDIT_DEBUG_LOADER") != NULL)
debug = debug | XEDIT_DEBUG_LOADER;
if (g_getenv ("XEDIT_DEBUG_SAVER") != NULL)
debug = debug | XEDIT_DEBUG_SAVER;
out:
#ifdef ENABLE_PROFILING
if (debug != XEDIT_NO_DEBUG)
timer = g_timer_new ();
#endif
return;
}
void
xedit_debug_message (XeditDebugSection section,
const gchar *file,
gint line,
const gchar *function,
const gchar *format, ...)
{
if (G_UNLIKELY (debug & section))
{
#ifdef ENABLE_PROFILING
gdouble seconds;
g_return_if_fail (timer != NULL);
#endif
va_list args;
gchar *msg;
g_return_if_fail (format != NULL);
va_start (args, format);
msg = g_strdup_vprintf (format, args);
va_end (args);
#ifdef ENABLE_PROFILING
seconds = g_timer_elapsed (timer, NULL);
g_print ("[%f (%f)] %s:%d (%s) %s\n",
seconds, seconds - last, file, line, function, msg);
last = seconds;
#else
g_print ("%s:%d (%s) %s\n", file, line, function, msg);
#endif
fflush (stdout);
g_free (msg);
}
}
void xedit_debug (XeditDebugSection section,
const gchar *file,
gint line,
const gchar *function)
{
if (G_UNLIKELY (debug & section))
{
#ifdef ENABLE_PROFILING
gdouble seconds;
g_return_if_fail (timer != NULL);
seconds = g_timer_elapsed (timer, NULL);
g_print ("[%f (%f)] %s:%d (%s)\n",
seconds, seconds - last, file, line, function);
last = seconds;
#else
g_print ("%s:%d (%s)\n", file, line, function);
#endif
fflush (stdout);
}
}

94
xedit/xedit-debug.h Normal file
View File

@@ -0,0 +1,94 @@
/*
* xedit-debug.h
* This file is part of xedit
*
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
* Copyright (C) 2002 - 2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 1998-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_DEBUG_H__
#define __XEDIT_DEBUG_H__
#include <glib.h>
/*
* Set an environmental var of the same name to turn on
* debugging output. Setting XEDIT_DEBUG will turn on all
* sections.
*/
typedef enum {
XEDIT_NO_DEBUG = 0,
XEDIT_DEBUG_VIEW = 1 << 0,
XEDIT_DEBUG_SEARCH = 1 << 1,
XEDIT_DEBUG_PRINT = 1 << 2,
XEDIT_DEBUG_PREFS = 1 << 3,
XEDIT_DEBUG_PLUGINS = 1 << 4,
XEDIT_DEBUG_TAB = 1 << 5,
XEDIT_DEBUG_DOCUMENT = 1 << 6,
XEDIT_DEBUG_COMMANDS = 1 << 7,
XEDIT_DEBUG_APP = 1 << 8,
XEDIT_DEBUG_SESSION = 1 << 9,
XEDIT_DEBUG_UTILS = 1 << 10,
XEDIT_DEBUG_METADATA = 1 << 11,
XEDIT_DEBUG_WINDOW = 1 << 12,
XEDIT_DEBUG_LOADER = 1 << 13,
XEDIT_DEBUG_SAVER = 1 << 14
} XeditDebugSection;
/* FIXME this is an issue for introspection */
#define DEBUG_VIEW XEDIT_DEBUG_VIEW, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_SEARCH XEDIT_DEBUG_SEARCH, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_PRINT XEDIT_DEBUG_PRINT, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_PREFS XEDIT_DEBUG_PREFS, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_PLUGINS XEDIT_DEBUG_PLUGINS, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_TAB XEDIT_DEBUG_TAB, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_DOCUMENT XEDIT_DEBUG_DOCUMENT,__FILE__, __LINE__, G_STRFUNC
#define DEBUG_COMMANDS XEDIT_DEBUG_COMMANDS,__FILE__, __LINE__, G_STRFUNC
#define DEBUG_APP XEDIT_DEBUG_APP, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_SESSION XEDIT_DEBUG_SESSION, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_UTILS XEDIT_DEBUG_UTILS, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_METADATA XEDIT_DEBUG_METADATA,__FILE__, __LINE__, G_STRFUNC
#define DEBUG_WINDOW XEDIT_DEBUG_WINDOW, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_LOADER XEDIT_DEBUG_LOADER, __FILE__, __LINE__, G_STRFUNC
#define DEBUG_SAVER XEDIT_DEBUG_SAVER, __FILE__, __LINE__, G_STRFUNC
void xedit_debug_init (void);
void xedit_debug (XeditDebugSection section,
const gchar *file,
gint line,
const gchar *function);
void xedit_debug_message (XeditDebugSection section,
const gchar *file,
gint line,
const gchar *function,
const gchar *format, ...) G_GNUC_PRINTF(5, 6);
#endif /* __XEDIT_DEBUG_H__ */

123
xedit/xedit-dirs.c Normal file
View File

@@ -0,0 +1,123 @@
/*
* xedit-dirs.c
* This file is part of xedit
*
* Copyright (C) 2008 Ignacio Casal Quinteiro
* Copyright (C) 2011 Perberos
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "xedit-dirs.h"
gchar* xedit_dirs_get_user_config_dir(void)
{
gchar* config_dir = NULL;
config_dir = g_build_filename(g_get_user_config_dir(), "xedit", NULL);
return config_dir;
}
gchar* xedit_dirs_get_user_cache_dir(void)
{
const gchar* cache_dir;
cache_dir = g_get_user_cache_dir();
return g_build_filename(cache_dir, "xedit", NULL);
}
gchar* xedit_dirs_get_user_plugins_dir(void)
{
gchar* plugin_dir;
plugin_dir = g_build_filename(g_get_user_data_dir(), "xedit", "plugins", NULL);
return plugin_dir;
}
gchar* xedit_dirs_get_user_accels_file(void)
{
gchar* accels = NULL;
gchar *config_dir = NULL;
config_dir = xedit_dirs_get_user_config_dir();
accels = g_build_filename(config_dir, "accels", NULL);
g_free(config_dir);
return accels;
}
gchar* xedit_dirs_get_xedit_data_dir(void)
{
return g_build_filename(DATADIR, "xedit", NULL);
}
gchar* xedit_dirs_get_xedit_locale_dir(void)
{
return g_build_filename(DATADIR, "locale", NULL);
}
gchar* xedit_dirs_get_xedit_lib_dir(void)
{
return g_build_filename(LIBDIR, "xedit", NULL);
}
gchar* xedit_dirs_get_xedit_plugins_dir(void)
{
gchar* lib_dir;
gchar* plugin_dir;
lib_dir = xedit_dirs_get_xedit_lib_dir();
plugin_dir = g_build_filename(lib_dir, "plugins", NULL);
g_free(lib_dir);
return plugin_dir;
}
gchar* xedit_dirs_get_xedit_plugin_loaders_dir(void)
{
gchar* lib_dir;
gchar* loader_dir;
lib_dir = xedit_dirs_get_xedit_lib_dir();
loader_dir = g_build_filename(lib_dir, "plugin-loaders", NULL);
g_free(lib_dir);
return loader_dir;
}
gchar* xedit_dirs_get_ui_file(const gchar* file)
{
gchar* datadir;
gchar* ui_file;
g_return_val_if_fail(file != NULL, NULL);
datadir = xedit_dirs_get_xedit_data_dir();
ui_file = g_build_filename(datadir, "ui", file, NULL);
g_free(datadir);
return ui_file;
}

54
xedit/xedit-dirs.h Normal file
View File

@@ -0,0 +1,54 @@
/*
* xedit-dirs.h
* This file is part of xedit
*
* Copyright (C) 2008 Ignacio Casal Quinteiro
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __XEDIT_DIRS_H__
#define __XEDIT_DIRS_H__
#include <glib.h>
G_BEGIN_DECLS
gchar *xedit_dirs_get_user_config_dir (void);
gchar *xedit_dirs_get_user_cache_dir (void);
gchar *xedit_dirs_get_user_plugins_dir (void);
gchar *xedit_dirs_get_user_accels_file (void);
gchar *xedit_dirs_get_xedit_data_dir (void);
gchar *xedit_dirs_get_xedit_locale_dir (void);
gchar *xedit_dirs_get_xedit_lib_dir (void);
gchar *xedit_dirs_get_xedit_plugins_dir (void);
gchar *xedit_dirs_get_xedit_plugin_loaders_dir
(void);
gchar *xedit_dirs_get_ui_file (const gchar *file);
G_END_DECLS
#endif /* __XEDIT_DIRS_H__ */

View File

@@ -0,0 +1,479 @@
/*
* xedit-document-input-stream.c
* This file is part of xedit
*
* Copyright (C) 2010 - Ignacio Casal Quinteiro
*
* xedit 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.
*
* xedit 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 xedit; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <glib.h>
#include <gio/gio.h>
#include <string.h>
#include "xedit-document-input-stream.h"
#include "xedit-enum-types.h"
/* NOTE: never use async methods on this stream, the stream is just
* a wrapper around GtkTextBuffer api so that we can use GIO Stream
* methods, but the undelying code operates on a GtkTextBuffer, so
* there is no I/O involved and should be accessed only by the main
* thread */
G_DEFINE_TYPE (XeditDocumentInputStream, xedit_document_input_stream, G_TYPE_INPUT_STREAM);
struct _XeditDocumentInputStreamPrivate
{
GtkTextBuffer *buffer;
GtkTextMark *pos;
gint bytes_partial;
XeditDocumentNewlineType newline_type;
guint newline_added : 1;
guint is_initialized : 1;
};
enum
{
PROP_0,
PROP_BUFFER,
PROP_NEWLINE_TYPE
};
static gssize xedit_document_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
static gboolean xedit_document_input_stream_close (GInputStream *stream,
GCancellable *cancellable,
GError **error);
static void
xedit_document_input_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XeditDocumentInputStream *stream = XEDIT_DOCUMENT_INPUT_STREAM (object);
switch (prop_id)
{
case PROP_BUFFER:
stream->priv->buffer = GTK_TEXT_BUFFER (g_value_get_object (value));
break;
case PROP_NEWLINE_TYPE:
stream->priv->newline_type = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_document_input_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XeditDocumentInputStream *stream = XEDIT_DOCUMENT_INPUT_STREAM (object);
switch (prop_id)
{
case PROP_BUFFER:
g_value_set_object (value, stream->priv->buffer);
break;
case PROP_NEWLINE_TYPE:
g_value_set_enum (value, stream->priv->newline_type);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_document_input_stream_class_init (XeditDocumentInputStreamClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
g_type_class_add_private (klass, sizeof (XeditDocumentInputStreamPrivate));
gobject_class->get_property = xedit_document_input_stream_get_property;
gobject_class->set_property = xedit_document_input_stream_set_property;
stream_class->read_fn = xedit_document_input_stream_read;
stream_class->close_fn = xedit_document_input_stream_close;
g_object_class_install_property (gobject_class,
PROP_BUFFER,
g_param_spec_object ("buffer",
"Buffer",
"The buffer which is read",
GTK_TYPE_TEXT_BUFFER,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
/**
* XeditDocumentInputStream:newline-type:
*
* The :newline-type property determines what is considered
* as a line ending when reading complete lines from the stream.
*/
g_object_class_install_property (gobject_class,
PROP_NEWLINE_TYPE,
g_param_spec_enum ("newline-type",
"Newline type",
"The accepted types of line ending",
XEDIT_TYPE_DOCUMENT_NEWLINE_TYPE,
XEDIT_DOCUMENT_NEWLINE_TYPE_LF,
G_PARAM_READWRITE |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB |
G_PARAM_CONSTRUCT_ONLY));
}
static void
xedit_document_input_stream_init (XeditDocumentInputStream *stream)
{
stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
XEDIT_TYPE_DOCUMENT_INPUT_STREAM,
XeditDocumentInputStreamPrivate);
}
static gsize
get_new_line_size (XeditDocumentInputStream *stream)
{
gsize ret;
switch (stream->priv->newline_type)
{
case XEDIT_DOCUMENT_NEWLINE_TYPE_CR:
case XEDIT_DOCUMENT_NEWLINE_TYPE_LF:
ret = 1;
break;
case XEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF:
ret = 2;
break;
default:
g_warn_if_reached ();
ret = 1;
break;
}
return ret;
}
/**
* xedit_document_input_stream_new:
* @buffer: a #GtkTextBuffer
*
* Reads the data from @buffer.
*
* Returns: a new #GInputStream to read @buffer
*/
GInputStream *
xedit_document_input_stream_new (GtkTextBuffer *buffer,
XeditDocumentNewlineType type)
{
XeditDocumentInputStream *stream;
g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
stream = g_object_new (XEDIT_TYPE_DOCUMENT_INPUT_STREAM,
"buffer", buffer,
"newline-type", type,
NULL);
return G_INPUT_STREAM (stream);
}
gsize
xedit_document_input_stream_get_total_size (XeditDocumentInputStream *stream)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_INPUT_STREAM (stream), 0);
return gtk_text_buffer_get_char_count (stream->priv->buffer);
}
gsize
xedit_document_input_stream_tell (XeditDocumentInputStream *stream)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_INPUT_STREAM (stream), 0);
/* FIXME: is this potentially inefficient? If yes, we could keep
track of the offset internally, assuming the mark doesn't move
during the operation */
if (!stream->priv->is_initialized)
{
return 0;
}
else
{
GtkTextIter iter;
gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
&iter,
stream->priv->pos);
return gtk_text_iter_get_offset (&iter);
}
}
static const gchar *
get_new_line (XeditDocumentInputStream *stream)
{
const gchar *ret;
switch (stream->priv->newline_type)
{
case XEDIT_DOCUMENT_NEWLINE_TYPE_CR:
ret = "\r";
break;
case XEDIT_DOCUMENT_NEWLINE_TYPE_LF:
ret = "\n";
break;
case XEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF:
ret = "\r\n";
break;
default:
g_warn_if_reached ();
ret = "\n";
break;
}
return ret;
}
static gsize
read_line (XeditDocumentInputStream *stream,
gchar *outbuf,
gsize space_left)
{
GtkTextIter start, next, end;
gchar *buf;
gint bytes; /* int since it's what iter_get_offset returns */
gsize bytes_to_write, newline_size, read;
const gchar *newline;
gboolean is_last;
gtk_text_buffer_get_iter_at_mark (stream->priv->buffer,
&start,
stream->priv->pos);
if (gtk_text_iter_is_end (&start))
return 0;
end = next = start;
newline = get_new_line (stream);
/* Check needed for empty lines */
if (!gtk_text_iter_ends_line (&end))
gtk_text_iter_forward_to_line_end (&end);
gtk_text_iter_forward_line (&next);
buf = gtk_text_iter_get_slice (&start, &end);
/* the bytes of a line includes also the newline, so with the
offsets we remove the newline and we add the new newline size */
bytes = gtk_text_iter_get_bytes_in_line (&start) - stream->priv->bytes_partial;
/* bytes_in_line includes the newlines, so we remove that assuming that
they are single byte characters */
bytes = bytes - (gtk_text_iter_get_offset (&next) - gtk_text_iter_get_offset (&end));
is_last = gtk_text_iter_is_end (&end);
/* bytes_to_write contains the amount of bytes we would like to write.
This means its the amount of bytes in the line (without the newline
in the buffer) + the amount of bytes for the newline we want to
write (newline_size) */
bytes_to_write = bytes;
/* do not add the new newline_size for the last line */
newline_size = get_new_line_size (stream);
if (!is_last)
bytes_to_write += newline_size;
if (bytes_to_write > space_left)
{
gchar *ptr;
gint char_offset;
gint written;
gsize to_write;
/* Here the line does not fit in the buffer, we thus write
the amount of bytes we can still fit, storing the position
for the next read with the mark. Do not try to write the
new newline in this case, it will be handled in the next
iteration */
to_write = MIN (space_left, bytes);
ptr = buf;
written = 0;
char_offset = 0;
while (written < to_write)
{
gint w;
ptr = g_utf8_next_char (ptr);
w = (ptr - buf);
if (w > to_write)
{
break;
}
else
{
written = w;
++char_offset;
}
}
memcpy (outbuf, buf, written);
/* Note: offset is one past what we wrote */
gtk_text_iter_forward_chars (&start, char_offset);
stream->priv->bytes_partial += written;
read = written;
}
else
{
/* First just copy the bytes without the newline */
memcpy (outbuf, buf, bytes);
/* Then add the newline, but not for the last line */
if (!is_last)
{
memcpy (outbuf + bytes, newline, newline_size);
}
start = next;
stream->priv->bytes_partial = 0;
read = bytes_to_write;
}
gtk_text_buffer_move_mark (stream->priv->buffer,
stream->priv->pos,
&start);
g_free (buf);
return read;
}
static gssize
xedit_document_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
XeditDocumentInputStream *dstream;
GtkTextIter iter;
gssize space_left, read, n;
dstream = XEDIT_DOCUMENT_INPUT_STREAM (stream);
if (count < 6)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NO_SPACE,
"Not enougth space in destination");
return -1;
}
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return -1;
/* Initialize the mark to the first char in the text buffer */
if (!dstream->priv->is_initialized)
{
gtk_text_buffer_get_start_iter (dstream->priv->buffer, &iter);
dstream->priv->pos = gtk_text_buffer_create_mark (dstream->priv->buffer,
NULL,
&iter,
FALSE);
dstream->priv->is_initialized = TRUE;
}
space_left = count;
read = 0;
do
{
n = read_line (dstream, buffer + read, space_left);
read += n;
space_left -= n;
} while (space_left > 0 && n != 0 && dstream->priv->bytes_partial == 0);
/* Make sure that non-empty files are always terminated with \n (see bug #95676).
* Note that we strip the trailing \n when loading the file */
gtk_text_buffer_get_iter_at_mark (dstream->priv->buffer,
&iter,
dstream->priv->pos);
if (gtk_text_iter_is_end (&iter) &&
!gtk_text_iter_is_start (&iter))
{
gssize newline_size;
newline_size = get_new_line_size (dstream);
if (space_left >= newline_size &&
!dstream->priv->newline_added)
{
const gchar *newline;
newline = get_new_line (dstream);
memcpy (buffer + read, newline, newline_size);
read += newline_size;
dstream->priv->newline_added = TRUE;
}
}
return read;
}
static gboolean
xedit_document_input_stream_close (GInputStream *stream,
GCancellable *cancellable,
GError **error)
{
XeditDocumentInputStream *dstream = XEDIT_DOCUMENT_INPUT_STREAM (stream);
dstream->priv->newline_added = FALSE;
if (dstream->priv->is_initialized)
{
gtk_text_buffer_delete_mark (dstream->priv->buffer, dstream->priv->pos);
}
return TRUE;
}

View File

@@ -0,0 +1,68 @@
/*
* xedit-document-input-stream.h
* This file is part of xedit
*
* Copyright (C) 2010 - Ignacio Casal Quinteiro
*
* xedit 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.
*
* xedit 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 xedit; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#ifndef __XEDIT_DOCUMENT_INPUT_STREAM_H__
#define __XEDIT_DOCUMENT_INPUT_STREAM_H__
#include <gio/gio.h>
#include <gtk/gtk.h>
#include "xedit-document.h"
G_BEGIN_DECLS
#define XEDIT_TYPE_DOCUMENT_INPUT_STREAM (xedit_document_input_stream_get_type ())
#define XEDIT_DOCUMENT_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_DOCUMENT_INPUT_STREAM, XeditDocumentInputStream))
#define XEDIT_DOCUMENT_INPUT_STREAM_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_DOCUMENT_INPUT_STREAM, XeditDocumentInputStream const))
#define XEDIT_DOCUMENT_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XEDIT_TYPE_DOCUMENT_INPUT_STREAM, XeditDocumentInputStreamClass))
#define XEDIT_IS_DOCUMENT_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XEDIT_TYPE_DOCUMENT_INPUT_STREAM))
#define XEDIT_IS_DOCUMENT_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_DOCUMENT_INPUT_STREAM))
#define XEDIT_DOCUMENT_INPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XEDIT_TYPE_DOCUMENT_INPUT_STREAM, XeditDocumentInputStreamClass))
typedef struct _XeditDocumentInputStream XeditDocumentInputStream;
typedef struct _XeditDocumentInputStreamClass XeditDocumentInputStreamClass;
typedef struct _XeditDocumentInputStreamPrivate XeditDocumentInputStreamPrivate;
struct _XeditDocumentInputStream
{
GInputStream parent;
XeditDocumentInputStreamPrivate *priv;
};
struct _XeditDocumentInputStreamClass
{
GInputStreamClass parent_class;
};
GType xedit_document_input_stream_get_type (void) G_GNUC_CONST;
GInputStream *xedit_document_input_stream_new (GtkTextBuffer *buffer,
XeditDocumentNewlineType type);
gsize xedit_document_input_stream_get_total_size (XeditDocumentInputStream *stream);
gsize xedit_document_input_stream_tell (XeditDocumentInputStream *stream);
G_END_DECLS
#endif /* __XEDIT_DOCUMENT_INPUT_STREAM_H__ */

View File

@@ -0,0 +1,357 @@
/*
* xedit-document-loader.c
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005-2007. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n.h>
#include "xedit-document-loader.h"
#include "xedit-debug.h"
#include "xedit-metadata-manager.h"
#include "xedit-utils.h"
#include "xedit-marshal.h"
#include "xedit-enum-types.h"
/* Those are for the the xedit_document_loader_new() factory */
#include "xedit-gio-document-loader.h"
G_DEFINE_ABSTRACT_TYPE(XeditDocumentLoader, xedit_document_loader, G_TYPE_OBJECT)
/* Signals */
enum {
LOADING,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
/* Properties */
enum
{
PROP_0,
PROP_DOCUMENT,
PROP_URI,
PROP_ENCODING,
PROP_NEWLINE_TYPE
};
static void
xedit_document_loader_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XeditDocumentLoader *loader = XEDIT_DOCUMENT_LOADER (object);
switch (prop_id)
{
case PROP_DOCUMENT:
g_return_if_fail (loader->document == NULL);
loader->document = g_value_get_object (value);
break;
case PROP_URI:
g_return_if_fail (loader->uri == NULL);
loader->uri = g_value_dup_string (value);
break;
case PROP_ENCODING:
g_return_if_fail (loader->encoding == NULL);
loader->encoding = g_value_get_boxed (value);
break;
case PROP_NEWLINE_TYPE:
loader->auto_detected_newline_type = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_document_loader_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XeditDocumentLoader *loader = XEDIT_DOCUMENT_LOADER (object);
switch (prop_id)
{
case PROP_DOCUMENT:
g_value_set_object (value, loader->document);
break;
case PROP_URI:
g_value_set_string (value, loader->uri);
break;
case PROP_ENCODING:
g_value_set_boxed (value, xedit_document_loader_get_encoding (loader));
break;
case PROP_NEWLINE_TYPE:
g_value_set_enum (value, loader->auto_detected_newline_type);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_document_loader_finalize (GObject *object)
{
XeditDocumentLoader *loader = XEDIT_DOCUMENT_LOADER (object);
g_free (loader->uri);
if (loader->info)
g_object_unref (loader->info);
G_OBJECT_CLASS (xedit_document_loader_parent_class)->finalize (object);
}
static void
xedit_document_loader_dispose (GObject *object)
{
XeditDocumentLoader *loader = XEDIT_DOCUMENT_LOADER (object);
if (loader->info != NULL)
{
g_object_unref (loader->info);
loader->info = NULL;
}
G_OBJECT_CLASS (xedit_document_loader_parent_class)->dispose (object);
}
static void
xedit_document_loader_class_init (XeditDocumentLoaderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = xedit_document_loader_finalize;
object_class->dispose = xedit_document_loader_dispose;
object_class->get_property = xedit_document_loader_get_property;
object_class->set_property = xedit_document_loader_set_property;
g_object_class_install_property (object_class,
PROP_DOCUMENT,
g_param_spec_object ("document",
"Document",
"The XeditDocument this XeditDocumentLoader is associated with",
XEDIT_TYPE_DOCUMENT,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
PROP_URI,
g_param_spec_string ("uri",
"URI",
"The URI this XeditDocumentLoader loads the document from",
"",
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_ENCODING,
g_param_spec_boxed ("encoding",
"Encoding",
"The encoding of the saved file",
XEDIT_TYPE_ENCODING,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_NEWLINE_TYPE,
g_param_spec_enum ("newline-type",
"Newline type",
"The accepted types of line ending",
XEDIT_TYPE_DOCUMENT_NEWLINE_TYPE,
XEDIT_DOCUMENT_NEWLINE_TYPE_LF,
G_PARAM_READWRITE |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB));
signals[LOADING] =
g_signal_new ("loading",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XeditDocumentLoaderClass, loading),
NULL, NULL,
xedit_marshal_VOID__BOOLEAN_POINTER,
G_TYPE_NONE,
2,
G_TYPE_BOOLEAN,
G_TYPE_POINTER);
}
static void
xedit_document_loader_init (XeditDocumentLoader *loader)
{
loader->used = FALSE;
loader->auto_detected_newline_type = XEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT;
}
void
xedit_document_loader_loading (XeditDocumentLoader *loader,
gboolean completed,
GError *error)
{
/* the object will be unrefed in the callback of the loading signal
* (when completed == TRUE), so we need to prevent finalization.
*/
if (completed)
{
g_object_ref (loader);
}
g_signal_emit (loader, signals[LOADING], 0, completed, error);
if (completed)
{
if (error == NULL)
xedit_debug_message (DEBUG_LOADER, "load completed");
else
xedit_debug_message (DEBUG_LOADER, "load failed");
g_object_unref (loader);
}
}
/* This is a factory method that returns an appopriate loader
* for the given uri.
*/
XeditDocumentLoader *
xedit_document_loader_new (XeditDocument *doc,
const gchar *uri,
const XeditEncoding *encoding)
{
XeditDocumentLoader *loader;
GType loader_type;
g_return_val_if_fail (XEDIT_IS_DOCUMENT (doc), NULL);
/* At the moment we just use gio loader in all cases...
* In the future it would be great to have a PolicyKit
* loader to get permission to save systen files etc */
loader_type = XEDIT_TYPE_GIO_DOCUMENT_LOADER;
loader = XEDIT_DOCUMENT_LOADER (g_object_new (loader_type,
"document", doc,
"uri", uri,
"encoding", encoding,
NULL));
return loader;
}
/* If enconding == NULL, the encoding will be autodetected */
void
xedit_document_loader_load (XeditDocumentLoader *loader)
{
xedit_debug (DEBUG_LOADER);
g_return_if_fail (XEDIT_IS_DOCUMENT_LOADER (loader));
/* the loader can be used just once, then it must be thrown away */
g_return_if_fail (loader->used == FALSE);
loader->used = TRUE;
XEDIT_DOCUMENT_LOADER_GET_CLASS (loader)->load (loader);
}
gboolean
xedit_document_loader_cancel (XeditDocumentLoader *loader)
{
xedit_debug (DEBUG_LOADER);
g_return_val_if_fail (XEDIT_IS_DOCUMENT_LOADER (loader), FALSE);
return XEDIT_DOCUMENT_LOADER_GET_CLASS (loader)->cancel (loader);
}
XeditDocument *
xedit_document_loader_get_document (XeditDocumentLoader *loader)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_LOADER (loader), NULL);
return loader->document;
}
/* Returns STDIN_URI if loading from stdin */
const gchar *
xedit_document_loader_get_uri (XeditDocumentLoader *loader)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_LOADER (loader), NULL);
return loader->uri;
}
goffset
xedit_document_loader_get_bytes_read (XeditDocumentLoader *loader)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_LOADER (loader), 0);
return XEDIT_DOCUMENT_LOADER_GET_CLASS (loader)->get_bytes_read (loader);
}
const XeditEncoding *
xedit_document_loader_get_encoding (XeditDocumentLoader *loader)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_LOADER (loader), NULL);
if (loader->encoding != NULL)
return loader->encoding;
g_return_val_if_fail (loader->auto_detected_encoding != NULL,
xedit_encoding_get_current ());
return loader->auto_detected_encoding;
}
XeditDocumentNewlineType
xedit_document_loader_get_newline_type (XeditDocumentLoader *loader)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_LOADER (loader),
XEDIT_DOCUMENT_NEWLINE_TYPE_LF);
return loader->auto_detected_newline_type;
}
GFileInfo *
xedit_document_loader_get_info (XeditDocumentLoader *loader)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_LOADER (loader), NULL);
return loader->info;
}

View File

@@ -0,0 +1,130 @@
/*
* xedit-document-loader.h
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005-2007. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_DOCUMENT_LOADER_H__
#define __XEDIT_DOCUMENT_LOADER_H__
#include <xedit/xedit-document.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_DOCUMENT_LOADER (xedit_document_loader_get_type())
#define XEDIT_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_DOCUMENT_LOADER, XeditDocumentLoader))
#define XEDIT_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_DOCUMENT_LOADER, XeditDocumentLoaderClass))
#define XEDIT_IS_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_DOCUMENT_LOADER))
#define XEDIT_IS_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_DOCUMENT_LOADER))
#define XEDIT_DOCUMENT_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_DOCUMENT_LOADER, XeditDocumentLoaderClass))
/* Private structure type */
typedef struct _XeditDocumentLoaderPrivate XeditDocumentLoaderPrivate;
/*
* Main object structure
*/
typedef struct _XeditDocumentLoader XeditDocumentLoader;
struct _XeditDocumentLoader
{
GObject object;
XeditDocument *document;
gboolean used;
/* Info on the current file */
GFileInfo *info;
gchar *uri;
const XeditEncoding *encoding;
const XeditEncoding *auto_detected_encoding;
XeditDocumentNewlineType auto_detected_newline_type;
};
/*
* Class definition
*/
typedef struct _XeditDocumentLoaderClass XeditDocumentLoaderClass;
struct _XeditDocumentLoaderClass
{
GObjectClass parent_class;
/* Signals */
void (* loading) (XeditDocumentLoader *loader,
gboolean completed,
const GError *error);
/* VTable */
void (* load) (XeditDocumentLoader *loader);
gboolean (* cancel) (XeditDocumentLoader *loader);
goffset (* get_bytes_read) (XeditDocumentLoader *loader);
};
/*
* Public methods
*/
GType xedit_document_loader_get_type (void) G_GNUC_CONST;
/* If enconding == NULL, the encoding will be autodetected */
XeditDocumentLoader *xedit_document_loader_new (XeditDocument *doc,
const gchar *uri,
const XeditEncoding *encoding);
void xedit_document_loader_loading (XeditDocumentLoader *loader,
gboolean completed,
GError *error);
void xedit_document_loader_load (XeditDocumentLoader *loader);
#if 0
gboolean xedit_document_loader_load_from_stdin (XeditDocumentLoader *loader);
#endif
gboolean xedit_document_loader_cancel (XeditDocumentLoader *loader);
XeditDocument *xedit_document_loader_get_document (XeditDocumentLoader *loader);
/* Returns STDIN_URI if loading from stdin */
#define STDIN_URI "stdin:"
const gchar *xedit_document_loader_get_uri (XeditDocumentLoader *loader);
const XeditEncoding *xedit_document_loader_get_encoding (XeditDocumentLoader *loader);
XeditDocumentNewlineType xedit_document_loader_get_newline_type (XeditDocumentLoader *loader);
goffset xedit_document_loader_get_bytes_read (XeditDocumentLoader *loader);
/* You can get from the info: content_type, time_modified, standard_size, access_can_write
and also the metadata*/
GFileInfo *xedit_document_loader_get_info (XeditDocumentLoader *loader);
G_END_DECLS
#endif /* __XEDIT_DOCUMENT_LOADER_H__ */

View File

@@ -0,0 +1,419 @@
/*
* xedit-document-output-stream.c
* This file is part of xedit
*
* Copyright (C) 2010 - Ignacio Casal Quinteiro
*
* xedit 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.
*
* xedit 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 xedit; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <string.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
#include "xedit-document-output-stream.h"
/* NOTE: never use async methods on this stream, the stream is just
* a wrapper around GtkTextBuffer api so that we can use GIO Stream
* methods, but the undelying code operates on a GtkTextBuffer, so
* there is no I/O involved and should be accessed only by the main
* thread */
#define XEDIT_DOCUMENT_OUTPUT_STREAM_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object),\
XEDIT_TYPE_DOCUMENT_OUTPUT_STREAM,\
XeditDocumentOutputStreamPrivate))
#define MAX_UNICHAR_LEN 6
struct _XeditDocumentOutputStreamPrivate
{
XeditDocument *doc;
GtkTextIter pos;
gchar *buffer;
gsize buflen;
guint is_initialized : 1;
guint is_closed : 1;
};
enum
{
PROP_0,
PROP_DOCUMENT
};
G_DEFINE_TYPE (XeditDocumentOutputStream, xedit_document_output_stream, G_TYPE_OUTPUT_STREAM)
static gssize xedit_document_output_stream_write (GOutputStream *stream,
const void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
static gboolean xedit_document_output_stream_flush (GOutputStream *stream,
GCancellable *cancellable,
GError **error);
static gboolean xedit_document_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
GError **error);
static void
xedit_document_output_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XeditDocumentOutputStream *stream = XEDIT_DOCUMENT_OUTPUT_STREAM (object);
switch (prop_id)
{
case PROP_DOCUMENT:
stream->priv->doc = XEDIT_DOCUMENT (g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_document_output_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XeditDocumentOutputStream *stream = XEDIT_DOCUMENT_OUTPUT_STREAM (object);
switch (prop_id)
{
case PROP_DOCUMENT:
g_value_set_object (value, stream->priv->doc);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_document_output_stream_finalize (GObject *object)
{
XeditDocumentOutputStream *stream = XEDIT_DOCUMENT_OUTPUT_STREAM (object);
g_free (stream->priv->buffer);
G_OBJECT_CLASS (xedit_document_output_stream_parent_class)->finalize (object);
}
static void
xedit_document_output_stream_constructed (GObject *object)
{
XeditDocumentOutputStream *stream = XEDIT_DOCUMENT_OUTPUT_STREAM (object);
if (!stream->priv->doc)
{
g_critical ("This should never happen, a problem happened constructing the Document Output Stream!");
return;
}
/* Init the undoable action */
gtk_source_buffer_begin_not_undoable_action (GTK_SOURCE_BUFFER (stream->priv->doc));
/* clear the buffer */
gtk_text_buffer_set_text (GTK_TEXT_BUFFER (stream->priv->doc),
"", 0);
gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->doc),
FALSE);
gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (stream->priv->doc));
}
static void
xedit_document_output_stream_class_init (XeditDocumentOutputStreamClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
object_class->get_property = xedit_document_output_stream_get_property;
object_class->set_property = xedit_document_output_stream_set_property;
object_class->finalize = xedit_document_output_stream_finalize;
object_class->constructed = xedit_document_output_stream_constructed;
stream_class->write_fn = xedit_document_output_stream_write;
stream_class->flush = xedit_document_output_stream_flush;
stream_class->close_fn = xedit_document_output_stream_close;
g_object_class_install_property (object_class,
PROP_DOCUMENT,
g_param_spec_object ("document",
"Document",
"The document which is written",
XEDIT_TYPE_DOCUMENT,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_type_class_add_private (object_class, sizeof (XeditDocumentOutputStreamPrivate));
}
static void
xedit_document_output_stream_init (XeditDocumentOutputStream *stream)
{
stream->priv = XEDIT_DOCUMENT_OUTPUT_STREAM_GET_PRIVATE (stream);
stream->priv->buffer = NULL;
stream->priv->buflen = 0;
stream->priv->is_initialized = FALSE;
stream->priv->is_closed = FALSE;
}
static XeditDocumentNewlineType
get_newline_type (GtkTextIter *end)
{
XeditDocumentNewlineType res;
GtkTextIter copy;
gunichar c;
copy = *end;
c = gtk_text_iter_get_char (&copy);
if (g_unichar_break_type (c) == G_UNICODE_BREAK_CARRIAGE_RETURN)
{
if (gtk_text_iter_forward_char (&copy) &&
g_unichar_break_type (gtk_text_iter_get_char (&copy)) == G_UNICODE_BREAK_LINE_FEED)
{
res = XEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF;
}
else
{
res = XEDIT_DOCUMENT_NEWLINE_TYPE_CR;
}
}
else
{
res = XEDIT_DOCUMENT_NEWLINE_TYPE_LF;
}
return res;
}
GOutputStream *
xedit_document_output_stream_new (XeditDocument *doc)
{
return G_OUTPUT_STREAM (g_object_new (XEDIT_TYPE_DOCUMENT_OUTPUT_STREAM,
"document", doc, NULL));
}
XeditDocumentNewlineType
xedit_document_output_stream_detect_newline_type (XeditDocumentOutputStream *stream)
{
XeditDocumentNewlineType type;
GtkTextIter iter;
g_return_val_if_fail (XEDIT_IS_DOCUMENT_OUTPUT_STREAM (stream),
XEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT);
type = XEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT;
gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (stream->priv->doc),
&iter);
if (gtk_text_iter_ends_line (&iter) || gtk_text_iter_forward_to_line_end (&iter))
{
type = get_newline_type (&iter);
}
return type;
}
/* If the last char is a newline, remove it from the buffer (otherwise
GtkTextView shows it as an empty line). See bug #324942. */
static void
remove_ending_newline (XeditDocumentOutputStream *stream)
{
GtkTextIter end;
GtkTextIter start;
gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (stream->priv->doc), &end);
start = end;
gtk_text_iter_set_line_offset (&start, 0);
if (gtk_text_iter_ends_line (&start) &&
gtk_text_iter_backward_line (&start))
{
if (!gtk_text_iter_ends_line (&start))
{
gtk_text_iter_forward_to_line_end (&start);
}
/* Delete the empty line which is from 'start' to 'end' */
gtk_text_buffer_delete (GTK_TEXT_BUFFER (stream->priv->doc),
&start,
&end);
}
}
static void
end_append_text_to_document (XeditDocumentOutputStream *stream)
{
remove_ending_newline (stream);
gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->doc),
FALSE);
gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (stream->priv->doc));
}
static gssize
xedit_document_output_stream_write (GOutputStream *stream,
const void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
XeditDocumentOutputStream *ostream;
gchar *text;
gsize len;
gboolean freetext = FALSE;
const gchar *end;
gboolean valid;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return -1;
ostream = XEDIT_DOCUMENT_OUTPUT_STREAM (stream);
if (!ostream->priv->is_initialized)
{
/* Init the undoable action */
gtk_source_buffer_begin_not_undoable_action (GTK_SOURCE_BUFFER (ostream->priv->doc));
gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (ostream->priv->doc),
&ostream->priv->pos);
ostream->priv->is_initialized = TRUE;
}
if (ostream->priv->buflen > 0)
{
len = ostream->priv->buflen + count;
text = g_new (gchar , len + 1);
memcpy (text, ostream->priv->buffer, ostream->priv->buflen);
memcpy (text + ostream->priv->buflen, buffer, count);
text[len] = '\0';
g_free (ostream->priv->buffer);
ostream->priv->buffer = NULL;
ostream->priv->buflen = 0;
freetext = TRUE;
}
else
{
text = (gchar *) buffer;
len = count;
}
/* validate */
valid = g_utf8_validate (text, len, &end);
/* Avoid keeping a CRLF across two buffers. */
if (valid && len > 1 && end[-1] == '\r')
{
valid = FALSE;
end--;
}
if (!valid)
{
gsize nvalid = end - text;
gsize remainder = len - nvalid;
gunichar ch;
if ((remainder < MAX_UNICHAR_LEN) &&
((ch = g_utf8_get_char_validated (text + nvalid, remainder)) == (gunichar)-2 ||
ch == (gunichar)'\r'))
{
ostream->priv->buffer = g_strndup (end, remainder);
ostream->priv->buflen = remainder;
len -= remainder;
}
else
{
/* TODO: we could escape invalid text and tag it in red
* and make the doc readonly.
*/
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
_("Invalid UTF-8 sequence in input"));
if (freetext)
g_free (text);
return -1;
}
}
gtk_text_buffer_insert (GTK_TEXT_BUFFER (ostream->priv->doc),
&ostream->priv->pos, text, len);
if (freetext)
g_free (text);
return count;
}
static gboolean
xedit_document_output_stream_flush (GOutputStream *stream,
GCancellable *cancellable,
GError **error)
{
XeditDocumentOutputStream *ostream = XEDIT_DOCUMENT_OUTPUT_STREAM (stream);
/* Flush deferred data if some. */
if (!ostream->priv->is_closed && ostream->priv->is_initialized &&
ostream->priv->buflen > 0 &&
xedit_document_output_stream_write (stream, "", 0, cancellable,
error) == -1)
return FALSE;
return TRUE;
}
static gboolean
xedit_document_output_stream_close (GOutputStream *stream,
GCancellable *cancellable,
GError **error)
{
XeditDocumentOutputStream *ostream = XEDIT_DOCUMENT_OUTPUT_STREAM (stream);
if (!ostream->priv->is_closed && ostream->priv->is_initialized)
{
end_append_text_to_document (ostream);
ostream->priv->is_closed = TRUE;
}
if (ostream->priv->buflen > 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
_("Incomplete UTF-8 sequence in input"));
return FALSE;
}
return TRUE;
}

View File

@@ -0,0 +1,64 @@
/*
* xedit-document-output-stream.h
* This file is part of xedit
*
* Copyright (C) 2010 - Ignacio Casal Quinteiro
*
* xedit 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.
*
* xedit 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 xedit; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#ifndef __XEDIT_DOCUMENT_OUTPUT_STREAM_H__
#define __XEDIT_DOCUMENT_OUTPUT_STREAM_H__
#include <gio/gio.h>
#include "xedit-document.h"
G_BEGIN_DECLS
#define XEDIT_TYPE_DOCUMENT_OUTPUT_STREAM (xedit_document_output_stream_get_type ())
#define XEDIT_DOCUMENT_OUTPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, XeditDocumentOutputStream))
#define XEDIT_DOCUMENT_OUTPUT_STREAM_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, XeditDocumentOutputStream const))
#define XEDIT_DOCUMENT_OUTPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, XeditDocumentOutputStreamClass))
#define XEDIT_IS_DOCUMENT_OUTPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XEDIT_TYPE_DOCUMENT_OUTPUT_STREAM))
#define XEDIT_IS_DOCUMENT_OUTPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_DOCUMENT_OUTPUT_STREAM))
#define XEDIT_DOCUMENT_OUTPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XEDIT_TYPE_DOCUMENT_OUTPUT_STREAM, XeditDocumentOutputStreamClass))
typedef struct _XeditDocumentOutputStream XeditDocumentOutputStream;
typedef struct _XeditDocumentOutputStreamClass XeditDocumentOutputStreamClass;
typedef struct _XeditDocumentOutputStreamPrivate XeditDocumentOutputStreamPrivate;
struct _XeditDocumentOutputStream
{
GOutputStream parent;
XeditDocumentOutputStreamPrivate *priv;
};
struct _XeditDocumentOutputStreamClass
{
GOutputStreamClass parent_class;
};
GType xedit_document_output_stream_get_type (void) G_GNUC_CONST;
GOutputStream *xedit_document_output_stream_new (XeditDocument *doc);
XeditDocumentNewlineType xedit_document_output_stream_detect_newline_type (XeditDocumentOutputStream *stream);
G_END_DECLS
#endif /* __XEDIT_DOCUMENT_OUTPUT_STREAM_H__ */

View File

@@ -0,0 +1,359 @@
/*
* xedit-document-saver.c
* This file is part of xedit
*
* Copyright (C) 2005-2006 - Paolo Borelli and Paolo Maggi
* Copyright (C) 2007 - Paolo Borelli, Paolo Maggi, Steve Frécinaux
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005-2006. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <glib/gi18n.h>
#include "xedit-document-saver.h"
#include "xedit-debug.h"
#include "xedit-prefs-manager.h"
#include "xedit-marshal.h"
#include "xedit-utils.h"
#include "xedit-enum-types.h"
#include "xedit-gio-document-saver.h"
G_DEFINE_ABSTRACT_TYPE(XeditDocumentSaver, xedit_document_saver, G_TYPE_OBJECT)
/* Signals */
enum {
SAVING,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
/* Properties */
enum {
PROP_0,
PROP_DOCUMENT,
PROP_URI,
PROP_ENCODING,
PROP_NEWLINE_TYPE,
PROP_FLAGS
};
static void
xedit_document_saver_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XeditDocumentSaver *saver = XEDIT_DOCUMENT_SAVER (object);
switch (prop_id)
{
case PROP_DOCUMENT:
g_return_if_fail (saver->document == NULL);
saver->document = g_value_get_object (value);
break;
case PROP_URI:
g_return_if_fail (saver->uri == NULL);
saver->uri = g_value_dup_string (value);
break;
case PROP_ENCODING:
g_return_if_fail (saver->encoding == NULL);
saver->encoding = g_value_get_boxed (value);
break;
case PROP_NEWLINE_TYPE:
saver->newline_type = g_value_get_enum (value);
break;
case PROP_FLAGS:
saver->flags = g_value_get_flags (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_document_saver_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XeditDocumentSaver *saver = XEDIT_DOCUMENT_SAVER (object);
switch (prop_id)
{
case PROP_DOCUMENT:
g_value_set_object (value, saver->document);
break;
case PROP_URI:
g_value_set_string (value, saver->uri);
break;
case PROP_ENCODING:
g_value_set_boxed (value, saver->encoding);
break;
case PROP_NEWLINE_TYPE:
g_value_set_enum (value, saver->newline_type);
break;
case PROP_FLAGS:
g_value_set_flags (value, saver->flags);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_document_saver_finalize (GObject *object)
{
XeditDocumentSaver *saver = XEDIT_DOCUMENT_SAVER (object);
g_free (saver->uri);
G_OBJECT_CLASS (xedit_document_saver_parent_class)->finalize (object);
}
static void
xedit_document_saver_dispose (GObject *object)
{
XeditDocumentSaver *saver = XEDIT_DOCUMENT_SAVER (object);
if (saver->info != NULL)
{
g_object_unref (saver->info);
saver->info = NULL;
}
G_OBJECT_CLASS (xedit_document_saver_parent_class)->dispose (object);
}
static void
xedit_document_saver_class_init (XeditDocumentSaverClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = xedit_document_saver_finalize;
object_class->dispose = xedit_document_saver_dispose;
object_class->set_property = xedit_document_saver_set_property;
object_class->get_property = xedit_document_saver_get_property;
g_object_class_install_property (object_class,
PROP_DOCUMENT,
g_param_spec_object ("document",
"Document",
"The XeditDocument this XeditDocumentSaver is associated with",
XEDIT_TYPE_DOCUMENT,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
PROP_URI,
g_param_spec_string ("uri",
"URI",
"The URI this XeditDocumentSaver saves the document to",
"",
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
PROP_ENCODING,
g_param_spec_boxed ("encoding",
"URI",
"The encoding of the saved file",
XEDIT_TYPE_ENCODING,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
PROP_NEWLINE_TYPE,
g_param_spec_enum ("newline-type",
"Newline type",
"The accepted types of line ending",
XEDIT_TYPE_DOCUMENT_NEWLINE_TYPE,
XEDIT_DOCUMENT_NEWLINE_TYPE_LF,
G_PARAM_READWRITE |
G_PARAM_STATIC_NAME |
G_PARAM_STATIC_BLURB |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_FLAGS,
g_param_spec_flags ("flags",
"Flags",
"The flags for the saving operation",
XEDIT_TYPE_DOCUMENT_SAVE_FLAGS,
0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
signals[SAVING] =
g_signal_new ("saving",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XeditDocumentSaverClass, saving),
NULL, NULL,
xedit_marshal_VOID__BOOLEAN_POINTER,
G_TYPE_NONE,
2,
G_TYPE_BOOLEAN,
G_TYPE_POINTER);
}
static void
xedit_document_saver_init (XeditDocumentSaver *saver)
{
saver->used = FALSE;
}
XeditDocumentSaver *
xedit_document_saver_new (XeditDocument *doc,
const gchar *uri,
const XeditEncoding *encoding,
XeditDocumentNewlineType newline_type,
XeditDocumentSaveFlags flags)
{
XeditDocumentSaver *saver;
GType saver_type;
g_return_val_if_fail (XEDIT_IS_DOCUMENT (doc), NULL);
saver_type = XEDIT_TYPE_GIO_DOCUMENT_SAVER;
if (encoding == NULL)
encoding = xedit_encoding_get_utf8 ();
saver = XEDIT_DOCUMENT_SAVER (g_object_new (saver_type,
"document", doc,
"uri", uri,
"encoding", encoding,
"newline_type", newline_type,
"flags", flags,
NULL));
return saver;
}
void
xedit_document_saver_saving (XeditDocumentSaver *saver,
gboolean completed,
GError *error)
{
/* the object will be unrefed in the callback of the saving
* signal, so we need to prevent finalization.
*/
if (completed)
{
g_object_ref (saver);
}
g_signal_emit (saver, signals[SAVING], 0, completed, error);
if (completed)
{
if (error == NULL)
xedit_debug_message (DEBUG_SAVER, "save completed");
else
xedit_debug_message (DEBUG_SAVER, "save failed");
g_object_unref (saver);
}
}
void
xedit_document_saver_save (XeditDocumentSaver *saver,
GTimeVal *old_mtime)
{
xedit_debug (DEBUG_SAVER);
g_return_if_fail (XEDIT_IS_DOCUMENT_SAVER (saver));
g_return_if_fail (saver->uri != NULL && strlen (saver->uri) > 0);
g_return_if_fail (saver->used == FALSE);
saver->used = TRUE;
// CHECK:
// - sanity check a max len for the uri?
// report async (in an idle handler) or sync (bool ret)
// async is extra work here, sync is special casing in the caller
/* never keep backup of autosaves */
if ((saver->flags & XEDIT_DOCUMENT_SAVE_PRESERVE_BACKUP) != 0)
saver->keep_backup = FALSE;
else
saver->keep_backup = xedit_prefs_manager_get_create_backup_copy ();
XEDIT_DOCUMENT_SAVER_GET_CLASS (saver)->save (saver, old_mtime);
}
XeditDocument *
xedit_document_saver_get_document (XeditDocumentSaver *saver)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_SAVER (saver), NULL);
return saver->document;
}
const gchar *
xedit_document_saver_get_uri (XeditDocumentSaver *saver)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_SAVER (saver), NULL);
return saver->uri;
}
/* Returns 0 if file size is unknown */
goffset
xedit_document_saver_get_file_size (XeditDocumentSaver *saver)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_SAVER (saver), 0);
return XEDIT_DOCUMENT_SAVER_GET_CLASS (saver)->get_file_size (saver);
}
goffset
xedit_document_saver_get_bytes_written (XeditDocumentSaver *saver)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_SAVER (saver), 0);
return XEDIT_DOCUMENT_SAVER_GET_CLASS (saver)->get_bytes_written (saver);
}
GFileInfo *
xedit_document_saver_get_info (XeditDocumentSaver *saver)
{
g_return_val_if_fail (XEDIT_IS_DOCUMENT_SAVER (saver), NULL);
return saver->info;
}

View File

@@ -0,0 +1,133 @@
/*
* xedit-document-saver.h
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
* Copyrhing (C) 2007 - Paolo Maggi, Steve Frécinaux
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_DOCUMENT_SAVER_H__
#define __XEDIT_DOCUMENT_SAVER_H__
#include <xedit/xedit-document.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_DOCUMENT_SAVER (xedit_document_saver_get_type())
#define XEDIT_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_DOCUMENT_SAVER, XeditDocumentSaver))
#define XEDIT_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_DOCUMENT_SAVER, XeditDocumentSaverClass))
#define XEDIT_IS_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_DOCUMENT_SAVER))
#define XEDIT_IS_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_DOCUMENT_SAVER))
#define XEDIT_DOCUMENT_SAVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_DOCUMENT_SAVER, XeditDocumentSaverClass))
/*
* Main object structure
*/
typedef struct _XeditDocumentSaver XeditDocumentSaver;
struct _XeditDocumentSaver
{
GObject object;
/*< private >*/
GFileInfo *info;
XeditDocument *document;
gboolean used;
gchar *uri;
const XeditEncoding *encoding;
XeditDocumentNewlineType newline_type;
XeditDocumentSaveFlags flags;
gboolean keep_backup;
};
/*
* Class definition
*/
typedef struct _XeditDocumentSaverClass XeditDocumentSaverClass;
struct _XeditDocumentSaverClass
{
GObjectClass parent_class;
/* Signals */
void (* saving) (XeditDocumentSaver *saver,
gboolean completed,
const GError *error);
/* VTable */
void (* save) (XeditDocumentSaver *saver,
GTimeVal *old_mtime);
goffset (* get_file_size) (XeditDocumentSaver *saver);
goffset (* get_bytes_written) (XeditDocumentSaver *saver);
};
/*
* Public methods
*/
GType xedit_document_saver_get_type (void) G_GNUC_CONST;
/* If enconding == NULL, the encoding will be autodetected */
XeditDocumentSaver *xedit_document_saver_new (XeditDocument *doc,
const gchar *uri,
const XeditEncoding *encoding,
XeditDocumentNewlineType newline_type,
XeditDocumentSaveFlags flags);
void xedit_document_saver_saving (XeditDocumentSaver *saver,
gboolean completed,
GError *error);
void xedit_document_saver_save (XeditDocumentSaver *saver,
GTimeVal *old_mtime);
#if 0
void xedit_document_saver_cancel (XeditDocumentSaver *saver);
#endif
XeditDocument *xedit_document_saver_get_document (XeditDocumentSaver *saver);
const gchar *xedit_document_saver_get_uri (XeditDocumentSaver *saver);
/* If backup_uri is NULL no backup will be made */
const gchar *xedit_document_saver_get_backup_uri (XeditDocumentSaver *saver);
void *xedit_document_saver_set_backup_uri (XeditDocumentSaver *saver,
const gchar *backup_uri);
/* Returns 0 if file size is unknown */
goffset xedit_document_saver_get_file_size (XeditDocumentSaver *saver);
goffset xedit_document_saver_get_bytes_written (XeditDocumentSaver *saver);
GFileInfo *xedit_document_saver_get_info (XeditDocumentSaver *saver);
G_END_DECLS
#endif /* __XEDIT_DOCUMENT_SAVER_H__ */

2901
xedit/xedit-document.c Normal file

File diff suppressed because it is too large Load Diff

333
xedit/xedit-document.h Normal file
View File

@@ -0,0 +1,333 @@
/*
* xedit-document.h
* This file is part of xedit
*
* Copyright (C) 1998, 1999 Alex Roberts, Evan Lawrence
* Copyright (C) 2000, 2001 Chema Celorio, Paolo Maggi
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 1998-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_DOCUMENT_H__
#define __XEDIT_DOCUMENT_H__
#include <gio/gio.h>
#include <gtk/gtk.h>
#include <gtksourceview/gtksourcebuffer.h>
#include <xedit/xedit-encodings.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_DOCUMENT (xedit_document_get_type())
#define XEDIT_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_DOCUMENT, XeditDocument))
#define XEDIT_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_DOCUMENT, XeditDocumentClass))
#define XEDIT_IS_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_DOCUMENT))
#define XEDIT_IS_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_DOCUMENT))
#define XEDIT_DOCUMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_DOCUMENT, XeditDocumentClass))
#define XEDIT_METADATA_ATTRIBUTE_POSITION "metadata::xedit-position"
#define XEDIT_METADATA_ATTRIBUTE_ENCODING "metadata::xedit-encoding"
#define XEDIT_METADATA_ATTRIBUTE_LANGUAGE "metadata::xedit-language"
typedef enum
{
XEDIT_DOCUMENT_NEWLINE_TYPE_LF,
XEDIT_DOCUMENT_NEWLINE_TYPE_CR,
XEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF
} XeditDocumentNewlineType;
#define XEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT XEDIT_DOCUMENT_NEWLINE_TYPE_LF
typedef enum
{
XEDIT_SEARCH_DONT_SET_FLAGS = 1 << 0,
XEDIT_SEARCH_ENTIRE_WORD = 1 << 1,
XEDIT_SEARCH_CASE_SENSITIVE = 1 << 2,
XEDIT_SEARCH_PARSE_ESCAPES = 1 << 3
} XeditSearchFlags;
/**
* XeditDocumentSaveFlags:
* @XEDIT_DOCUMENT_SAVE_IGNORE_MTIME: save file despite external modifications.
* @XEDIT_DOCUMENT_SAVE_IGNORE_BACKUP: write the file directly without attempting to backup.
* @XEDIT_DOCUMENT_SAVE_PRESERVE_BACKUP: preserve previous backup file, needed to support autosaving.
*/
typedef enum
{
XEDIT_DOCUMENT_SAVE_IGNORE_MTIME = 1 << 0,
XEDIT_DOCUMENT_SAVE_IGNORE_BACKUP = 1 << 1,
XEDIT_DOCUMENT_SAVE_PRESERVE_BACKUP = 1 << 2
} XeditDocumentSaveFlags;
/* Private structure type */
typedef struct _XeditDocumentPrivate XeditDocumentPrivate;
/*
* Main object structure
*/
typedef struct _XeditDocument XeditDocument;
struct _XeditDocument
{
GtkSourceBuffer buffer;
/*< private > */
XeditDocumentPrivate *priv;
};
/*
* Class definition
*/
typedef struct _XeditDocumentClass XeditDocumentClass;
struct _XeditDocumentClass
{
GtkSourceBufferClass parent_class;
/* Signals */ // CHECK: ancora da rivedere
void (* cursor_moved) (XeditDocument *document);
/* Document load */
void (* load) (XeditDocument *document,
const gchar *uri,
const XeditEncoding *encoding,
gint line_pos,
gboolean create);
void (* loading) (XeditDocument *document,
goffset size,
goffset total_size);
void (* loaded) (XeditDocument *document,
const GError *error);
/* Document save */
void (* save) (XeditDocument *document,
const gchar *uri,
const XeditEncoding *encoding,
XeditDocumentSaveFlags flags);
void (* saving) (XeditDocument *document,
goffset size,
goffset total_size);
void (* saved) (XeditDocument *document,
const GError *error);
void (* search_highlight_updated)
(XeditDocument *document,
GtkTextIter *start,
GtkTextIter *end);
};
#define XEDIT_DOCUMENT_ERROR xedit_document_error_quark ()
enum
{
XEDIT_DOCUMENT_ERROR_EXTERNALLY_MODIFIED,
XEDIT_DOCUMENT_ERROR_CANT_CREATE_BACKUP,
XEDIT_DOCUMENT_ERROR_TOO_BIG,
XEDIT_DOCUMENT_ERROR_ENCODING_AUTO_DETECTION_FAILED,
XEDIT_DOCUMENT_ERROR_CONVERSION_FALLBACK,
XEDIT_DOCUMENT_NUM_ERRORS
};
GQuark xedit_document_error_quark (void);
GType xedit_document_get_type (void) G_GNUC_CONST;
XeditDocument *xedit_document_new (void);
GFile *xedit_document_get_location (XeditDocument *doc);
gchar *xedit_document_get_uri (XeditDocument *doc);
void xedit_document_set_uri (XeditDocument *doc,
const gchar *uri);
gchar *xedit_document_get_uri_for_display
(XeditDocument *doc);
gchar *xedit_document_get_short_name_for_display
(XeditDocument *doc);
void xedit_document_set_short_name_for_display
(XeditDocument *doc,
const gchar *name);
gchar *xedit_document_get_content_type
(XeditDocument *doc);
void xedit_document_set_content_type
(XeditDocument *doc,
const gchar *content_type);
gchar *xedit_document_get_mime_type (XeditDocument *doc);
gboolean xedit_document_get_readonly (XeditDocument *doc);
void xedit_document_load (XeditDocument *doc,
const gchar *uri,
const XeditEncoding *encoding,
gint line_pos,
gboolean create);
gboolean xedit_document_insert_file (XeditDocument *doc,
GtkTextIter *iter,
const gchar *uri,
const XeditEncoding *encoding);
gboolean xedit_document_load_cancel (XeditDocument *doc);
void xedit_document_save (XeditDocument *doc,
XeditDocumentSaveFlags flags);
void xedit_document_save_as (XeditDocument *doc,
const gchar *uri,
const XeditEncoding *encoding,
XeditDocumentSaveFlags flags);
gboolean xedit_document_is_untouched (XeditDocument *doc);
gboolean xedit_document_is_untitled (XeditDocument *doc);
gboolean xedit_document_is_local (XeditDocument *doc);
gboolean xedit_document_get_deleted (XeditDocument *doc);
gboolean xedit_document_goto_line (XeditDocument *doc,
gint line);
gboolean xedit_document_goto_line_offset(XeditDocument *doc,
gint line,
gint line_offset);
void xedit_document_set_search_text (XeditDocument *doc,
const gchar *text,
guint flags);
gchar *xedit_document_get_search_text (XeditDocument *doc,
guint *flags);
gboolean xedit_document_get_can_search_again
(XeditDocument *doc);
gboolean xedit_document_search_forward (XeditDocument *doc,
const GtkTextIter *start,
const GtkTextIter *end,
GtkTextIter *match_start,
GtkTextIter *match_end);
gboolean xedit_document_search_backward (XeditDocument *doc,
const GtkTextIter *start,
const GtkTextIter *end,
GtkTextIter *match_start,
GtkTextIter *match_end);
gint xedit_document_replace_all (XeditDocument *doc,
const gchar *find,
const gchar *replace,
guint flags);
void xedit_document_set_language (XeditDocument *doc,
GtkSourceLanguage *lang);
GtkSourceLanguage
*xedit_document_get_language (XeditDocument *doc);
const XeditEncoding
*xedit_document_get_encoding (XeditDocument *doc);
void xedit_document_set_enable_search_highlighting
(XeditDocument *doc,
gboolean enable);
gboolean xedit_document_get_enable_search_highlighting
(XeditDocument *doc);
void xedit_document_set_newline_type (XeditDocument *doc,
XeditDocumentNewlineType newline_type);
XeditDocumentNewlineType
xedit_document_get_newline_type (XeditDocument *doc);
gchar *xedit_document_get_metadata (XeditDocument *doc,
const gchar *key);
void xedit_document_set_metadata (XeditDocument *doc,
const gchar *first_key,
...);
/*
* Non exported functions
*/
void _xedit_document_set_readonly (XeditDocument *doc,
gboolean readonly);
glong _xedit_document_get_seconds_since_last_save_or_load
(XeditDocument *doc);
/* Note: this is a sync stat: use only on local files */
gboolean _xedit_document_check_externally_modified
(XeditDocument *doc);
void _xedit_document_search_region (XeditDocument *doc,
const GtkTextIter *start,
const GtkTextIter *end);
/* Search macros */
#define XEDIT_SEARCH_IS_DONT_SET_FLAGS(sflags) ((sflags & XEDIT_SEARCH_DONT_SET_FLAGS) != 0)
#define XEDIT_SEARCH_SET_DONT_SET_FLAGS(sflags,state) ((state == TRUE) ? \
(sflags |= XEDIT_SEARCH_DONT_SET_FLAGS) : (sflags &= ~XEDIT_SEARCH_DONT_SET_FLAGS))
#define XEDIT_SEARCH_IS_ENTIRE_WORD(sflags) ((sflags & XEDIT_SEARCH_ENTIRE_WORD) != 0)
#define XEDIT_SEARCH_SET_ENTIRE_WORD(sflags,state) ((state == TRUE) ? \
(sflags |= XEDIT_SEARCH_ENTIRE_WORD) : (sflags &= ~XEDIT_SEARCH_ENTIRE_WORD))
#define XEDIT_SEARCH_IS_CASE_SENSITIVE(sflags) ((sflags & XEDIT_SEARCH_CASE_SENSITIVE) != 0)
#define XEDIT_SEARCH_SET_CASE_SENSITIVE(sflags,state) ((state == TRUE) ? \
(sflags |= XEDIT_SEARCH_CASE_SENSITIVE) : (sflags &= ~XEDIT_SEARCH_CASE_SENSITIVE))
#define XEDIT_SEARCH_IS_PARSE_ESCAPES(sflags) ((sflags & XEDIT_SEARCH_PARSE_ESCAPES) != 0)
#define XEDIT_SEARCH_SET_PARSE_ESCAPES(sflags,state) ((state == TRUE) ? \
(sflags |= XEDIT_SEARCH_PARSE_ESCAPES) : (sflags &= ~XEDIT_SEARCH_PARSE_ESCAPES))
typedef GMountOperation *(*XeditMountOperationFactory)(XeditDocument *doc,
gpointer userdata);
void _xedit_document_set_mount_operation_factory
(XeditDocument *doc,
XeditMountOperationFactory callback,
gpointer userdata);
GMountOperation
*_xedit_document_create_mount_operation
(XeditDocument *doc);
G_END_DECLS
#endif /* __XEDIT_DOCUMENT_H__ */

View File

@@ -0,0 +1,844 @@
/*
* xedit-documents-panel.c
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "xedit-documents-panel.h"
#include "xedit-utils.h"
#include "xedit-notebook.h"
#include <glib/gi18n.h>
#define XEDIT_DOCUMENTS_PANEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
XEDIT_TYPE_DOCUMENTS_PANEL, \
XeditDocumentsPanelPrivate))
struct _XeditDocumentsPanelPrivate
{
XeditWindow *window;
GtkWidget *treeview;
GtkTreeModel *model;
guint adding_tab : 1;
guint is_reodering : 1;
};
#if GTK_CHECK_VERSION (3, 0, 0)
G_DEFINE_TYPE(XeditDocumentsPanel, xedit_documents_panel, GTK_TYPE_BOX)
#else
G_DEFINE_TYPE(XeditDocumentsPanel, xedit_documents_panel, GTK_TYPE_VBOX)
#endif
enum
{
PROP_0,
PROP_WINDOW
};
enum
{
PIXBUF_COLUMN,
NAME_COLUMN,
TAB_COLUMN,
N_COLUMNS
};
#define MAX_DOC_NAME_LENGTH 60
static gchar *
tab_get_name (XeditTab *tab)
{
XeditDocument *doc;
gchar *name;
gchar *docname;
gchar *tab_name;
g_return_val_if_fail (XEDIT_IS_TAB (tab), NULL);
doc = xedit_tab_get_document (tab);
name = xedit_document_get_short_name_for_display (doc);
/* Truncate the name so it doesn't get insanely wide. */
docname = xedit_utils_str_middle_truncate (name, MAX_DOC_NAME_LENGTH);
if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)))
{
if (xedit_document_get_readonly (doc))
{
tab_name = g_markup_printf_escaped ("<i>%s</i> [<i>%s</i>]",
docname,
_("Read-Only"));
}
else
{
tab_name = g_markup_printf_escaped ("<i>%s</i>",
docname);
}
}
else
{
if (xedit_document_get_readonly (doc))
{
tab_name = g_markup_printf_escaped ("%s [<i>%s</i>]",
docname,
_("Read-Only"));
}
else
{
tab_name = g_markup_escape_text (docname, -1);
}
}
g_free (docname);
g_free (name);
return tab_name;
}
static void
get_iter_from_tab (XeditDocumentsPanel *panel, XeditTab *tab, GtkTreeIter *iter)
{
gint num;
GtkWidget *nb;
GtkTreePath *path;
nb = _xedit_window_get_notebook (panel->priv->window);
num = gtk_notebook_page_num (GTK_NOTEBOOK (nb),
GTK_WIDGET (tab));
path = gtk_tree_path_new_from_indices (num, -1);
gtk_tree_model_get_iter (panel->priv->model,
iter,
path);
gtk_tree_path_free (path);
}
static void
window_active_tab_changed (XeditWindow *window,
XeditTab *tab,
XeditDocumentsPanel *panel)
{
g_return_if_fail (tab != NULL);
if (!_xedit_window_is_removing_tabs (window))
{
GtkTreeIter iter;
GtkTreeSelection *selection;
get_iter_from_tab (panel, tab, &iter);
if (gtk_list_store_iter_is_valid (GTK_LIST_STORE (panel->priv->model),
&iter))
{
selection = gtk_tree_view_get_selection (
GTK_TREE_VIEW (panel->priv->treeview));
gtk_tree_selection_select_iter (selection, &iter);
}
}
}
static void
refresh_list (XeditDocumentsPanel *panel)
{
/* TODO: refresh the list only if the panel is visible */
GList *tabs;
GList *l;
GtkWidget *nb;
GtkListStore *list_store;
XeditTab *active_tab;
/* g_debug ("refresh_list"); */
list_store = GTK_LIST_STORE (panel->priv->model);
gtk_list_store_clear (list_store);
active_tab = xedit_window_get_active_tab (panel->priv->window);
nb = _xedit_window_get_notebook (panel->priv->window);
tabs = gtk_container_get_children (GTK_CONTAINER (nb));
l = tabs;
panel->priv->adding_tab = TRUE;
while (l != NULL)
{
GdkPixbuf *pixbuf;
gchar *name;
GtkTreeIter iter;
name = tab_get_name (XEDIT_TAB (l->data));
pixbuf = _xedit_tab_get_icon (XEDIT_TAB (l->data));
/* Add a new row to the model */
gtk_list_store_append (list_store, &iter);
gtk_list_store_set (list_store,
&iter,
PIXBUF_COLUMN, pixbuf,
NAME_COLUMN, name,
TAB_COLUMN, l->data,
-1);
g_free (name);
if (pixbuf != NULL)
g_object_unref (pixbuf);
if (l->data == active_tab)
{
GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection (
GTK_TREE_VIEW (panel->priv->treeview));
gtk_tree_selection_select_iter (selection, &iter);
}
l = g_list_next (l);
}
panel->priv->adding_tab = FALSE;
g_list_free (tabs);
}
static void
sync_name_and_icon (XeditTab *tab,
GParamSpec *pspec,
XeditDocumentsPanel *panel)
{
GdkPixbuf *pixbuf;
gchar *name;
GtkTreeIter iter;
get_iter_from_tab (panel, tab, &iter);
name = tab_get_name (tab);
pixbuf = _xedit_tab_get_icon (tab);
gtk_list_store_set (GTK_LIST_STORE (panel->priv->model),
&iter,
PIXBUF_COLUMN, pixbuf,
NAME_COLUMN, name,
TAB_COLUMN, tab,
-1);
g_free (name);
if (pixbuf != NULL)
g_object_unref (pixbuf);
}
static void
window_tab_removed (XeditWindow *window,
XeditTab *tab,
XeditDocumentsPanel *panel)
{
g_signal_handlers_disconnect_by_func (tab,
G_CALLBACK (sync_name_and_icon),
panel);
if (_xedit_window_is_removing_tabs (window))
gtk_list_store_clear (GTK_LIST_STORE (panel->priv->model));
else
refresh_list (panel);
}
static void
window_tab_added (XeditWindow *window,
XeditTab *tab,
XeditDocumentsPanel *panel)
{
GtkTreeIter iter;
GtkTreeIter sibling;
GdkPixbuf *pixbuf;
gchar *name;
g_signal_connect (tab,
"notify::name",
G_CALLBACK (sync_name_and_icon),
panel);
g_signal_connect (tab,
"notify::state",
G_CALLBACK (sync_name_and_icon),
panel);
get_iter_from_tab (panel, tab, &sibling);
panel->priv->adding_tab = TRUE;
if (gtk_list_store_iter_is_valid (GTK_LIST_STORE (panel->priv->model),
&sibling))
{
gtk_list_store_insert_after (GTK_LIST_STORE (panel->priv->model),
&iter,
&sibling);
}
else
{
XeditTab *active_tab;
gtk_list_store_append (GTK_LIST_STORE (panel->priv->model),
&iter);
active_tab = xedit_window_get_active_tab (panel->priv->window);
if (tab == active_tab)
{
GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection (
GTK_TREE_VIEW (panel->priv->treeview));
gtk_tree_selection_select_iter (selection, &iter);
}
}
name = tab_get_name (tab);
pixbuf = _xedit_tab_get_icon (tab);
gtk_list_store_set (GTK_LIST_STORE (panel->priv->model),
&iter,
PIXBUF_COLUMN, pixbuf,
NAME_COLUMN, name,
TAB_COLUMN, tab,
-1);
g_free (name);
if (pixbuf != NULL)
g_object_unref (pixbuf);
panel->priv->adding_tab = FALSE;
}
static void
window_tabs_reordered (XeditWindow *window,
XeditDocumentsPanel *panel)
{
if (panel->priv->is_reodering)
return;
refresh_list (panel);
}
static void
set_window (XeditDocumentsPanel *panel,
XeditWindow *window)
{
g_return_if_fail (panel->priv->window == NULL);
g_return_if_fail (XEDIT_IS_WINDOW (window));
panel->priv->window = g_object_ref (window);
g_signal_connect (window,
"tab_added",
G_CALLBACK (window_tab_added),
panel);
g_signal_connect (window,
"tab_removed",
G_CALLBACK (window_tab_removed),
panel);
g_signal_connect (window,
"tabs_reordered",
G_CALLBACK (window_tabs_reordered),
panel);
g_signal_connect (window,
"active_tab_changed",
G_CALLBACK (window_active_tab_changed),
panel);
}
static void
treeview_cursor_changed (GtkTreeView *view,
XeditDocumentsPanel *panel)
{
GtkTreeIter iter;
GtkTreeSelection *selection;
gpointer tab;
selection = gtk_tree_view_get_selection (
GTK_TREE_VIEW (panel->priv->treeview));
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
{
gtk_tree_model_get (panel->priv->model,
&iter,
TAB_COLUMN,
&tab,
-1);
if (xedit_window_get_active_tab (panel->priv->window) != tab)
{
xedit_window_set_active_tab (panel->priv->window,
XEDIT_TAB (tab));
}
}
}
static void
xedit_documents_panel_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XeditDocumentsPanel *panel = XEDIT_DOCUMENTS_PANEL (object);
switch (prop_id)
{
case PROP_WINDOW:
set_window (panel, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_documents_panel_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XeditDocumentsPanel *panel = XEDIT_DOCUMENTS_PANEL (object);
switch (prop_id)
{
case PROP_WINDOW:
g_value_set_object (value,
XEDIT_DOCUMENTS_PANEL_GET_PRIVATE (panel)->window);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_documents_panel_finalize (GObject *object)
{
/* XeditDocumentsPanel *tab = XEDIT_DOCUMENTS_PANEL (object); */
/* TODO: disconnect signal with window */
G_OBJECT_CLASS (xedit_documents_panel_parent_class)->finalize (object);
}
static void
xedit_documents_panel_dispose (GObject *object)
{
XeditDocumentsPanel *panel = XEDIT_DOCUMENTS_PANEL (object);
if (panel->priv->window != NULL)
{
g_object_unref (panel->priv->window);
panel->priv->window = NULL;
}
G_OBJECT_CLASS (xedit_documents_panel_parent_class)->dispose (object);
}
static void
xedit_documents_panel_class_init (XeditDocumentsPanelClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = xedit_documents_panel_finalize;
object_class->dispose = xedit_documents_panel_dispose;
object_class->get_property = xedit_documents_panel_get_property;
object_class->set_property = xedit_documents_panel_set_property;
g_object_class_install_property (object_class,
PROP_WINDOW,
g_param_spec_object ("window",
"Window",
"The XeditWindow this XeditDocumentsPanel is associated with",
XEDIT_TYPE_WINDOW,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_type_class_add_private (object_class, sizeof (XeditDocumentsPanelPrivate));
}
static GtkTreePath *
get_current_path (XeditDocumentsPanel *panel)
{
gint num;
GtkWidget *nb;
GtkTreePath *path;
nb = _xedit_window_get_notebook (panel->priv->window);
num = gtk_notebook_get_current_page (GTK_NOTEBOOK (nb));
path = gtk_tree_path_new_from_indices (num, -1);
return path;
}
static void
menu_position (GtkMenu *menu,
gint *x,
gint *y,
gboolean *push_in,
XeditDocumentsPanel *panel)
{
GtkTreePath *path;
GdkRectangle rect;
gint wx, wy;
GtkAllocation allocation;
GtkRequisition requisition;
GtkWidget *w;
w = panel->priv->treeview;
gtk_widget_get_allocation(w, &allocation);
path = get_current_path (panel);
gtk_tree_view_get_cell_area (GTK_TREE_VIEW (w),
path,
NULL,
&rect);
wx = rect.x;
wy = rect.y;
gdk_window_get_origin (gtk_widget_get_window (w), x, y);
#if GTK_CHECK_VERSION (3, 0, 0)
gtk_widget_get_preferred_size (GTK_WIDGET (menu), NULL, &requisition);
#else
gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
#endif
if (gtk_widget_get_direction (w) == GTK_TEXT_DIR_RTL)
{
*x += allocation.x + allocation.width - requisition.width - 10;
}
else
{
*x += allocation.x + 10;
}
wy = MAX (*y + 5, *y + wy + 5);
wy = MIN (wy, *y + allocation.height - requisition.height - 5);
*y = wy;
*push_in = TRUE;
}
static gboolean
show_popup_menu (XeditDocumentsPanel *panel,
GdkEventButton *event)
{
GtkWidget *menu;
menu = gtk_ui_manager_get_widget (xedit_window_get_ui_manager (panel->priv->window),
"/NotebookPopup");
g_return_val_if_fail (menu != NULL, FALSE);
if (event != NULL)
{
gtk_menu_popup (GTK_MENU (menu),
NULL,
NULL,
NULL,
NULL,
event->button,
event->time);
}
else
{
gtk_menu_popup (GTK_MENU (menu),
NULL,
NULL,
(GtkMenuPositionFunc) menu_position,
panel,
0,
gtk_get_current_event_time ());
gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
}
return TRUE;
}
static gboolean
panel_button_press_event (GtkTreeView *treeview,
GdkEventButton *event,
XeditDocumentsPanel *panel)
{
if ((GDK_BUTTON_PRESS == event->type) && (3 == event->button))
{
GtkTreePath* path = NULL;
if (event->window == gtk_tree_view_get_bin_window (treeview))
{
/* Change the cursor position */
if (gtk_tree_view_get_path_at_pos (treeview,
event->x,
event->y,
&path,
NULL,
NULL,
NULL))
{
gtk_tree_view_set_cursor (treeview,
path,
NULL,
FALSE);
gtk_tree_path_free (path);
/* A row exists at mouse position */
return show_popup_menu (panel, event);
}
}
}
return FALSE;
}
static gboolean
panel_popup_menu (GtkWidget *treeview,
XeditDocumentsPanel *panel)
{
/* Only respond if the treeview is the actual focus */
if (gtk_window_get_focus (GTK_WINDOW (panel->priv->window)) == treeview)
{
return show_popup_menu (panel, NULL);
}
return FALSE;
}
static gboolean
treeview_query_tooltip (GtkWidget *widget,
gint x,
gint y,
gboolean keyboard_tip,
GtkTooltip *tooltip,
gpointer data)
{
GtkTreeIter iter;
GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
GtkTreePath *path = NULL;
gpointer *tab;
gchar *tip;
if (keyboard_tip)
{
gtk_tree_view_get_cursor (tree_view, &path, NULL);
if (path == NULL)
{
return FALSE;
}
}
else
{
gint bin_x, bin_y;
gtk_tree_view_convert_widget_to_bin_window_coords (tree_view,
x, y,
&bin_x, &bin_y);
if (!gtk_tree_view_get_path_at_pos (tree_view,
bin_x, bin_y,
&path,
NULL, NULL, NULL))
{
return FALSE;
}
}
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model,
&iter,
TAB_COLUMN,
&tab,
-1);
tip = _xedit_tab_get_tooltips (XEDIT_TAB (tab));
gtk_tooltip_set_markup (tooltip, tip);
g_free (tip);
gtk_tree_path_free (path);
return TRUE;
}
static void
treeview_row_inserted (GtkTreeModel *tree_model,
GtkTreePath *path,
GtkTreeIter *iter,
XeditDocumentsPanel *panel)
{
XeditTab *tab;
gint *indeces;
GtkWidget *nb;
gint old_position;
gint new_position;
if (panel->priv->adding_tab)
return;
tab = xedit_window_get_active_tab (panel->priv->window);
g_return_if_fail (tab != NULL);
panel->priv->is_reodering = TRUE;
indeces = gtk_tree_path_get_indices (path);
/* g_debug ("New Index: %d (path: %s)", indeces[0], gtk_tree_path_to_string (path));*/
nb = _xedit_window_get_notebook (panel->priv->window);
new_position = indeces[0];
old_position = gtk_notebook_page_num (GTK_NOTEBOOK (nb),
GTK_WIDGET (tab));
if (new_position > old_position)
new_position = MAX (0, new_position - 1);
xedit_notebook_reorder_tab (XEDIT_NOTEBOOK (nb),
tab,
new_position);
panel->priv->is_reodering = FALSE;
}
static void
xedit_documents_panel_init (XeditDocumentsPanel *panel)
{
GtkWidget *sw;
GtkTreeViewColumn *column;
GtkCellRenderer *cell;
GtkTreeSelection *selection;
panel->priv = XEDIT_DOCUMENTS_PANEL_GET_PRIVATE (panel);
panel->priv->adding_tab = FALSE;
panel->priv->is_reodering = FALSE;
#if GTK_CHECK_VERSION (3, 0, 0)
gtk_orientable_set_orientation (GTK_ORIENTABLE (panel),
GTK_ORIENTATION_VERTICAL);
#endif
/* Create the scrolled window */
sw = gtk_scrolled_window_new (NULL, NULL);
g_return_if_fail (sw != NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
GTK_SHADOW_IN);
gtk_widget_show (sw);
gtk_box_pack_start (GTK_BOX (panel), sw, TRUE, TRUE, 0);
/* Create the empty model */
panel->priv->model = GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS,
GDK_TYPE_PIXBUF,
G_TYPE_STRING,
G_TYPE_POINTER));
/* Create the treeview */
panel->priv->treeview = gtk_tree_view_new_with_model (panel->priv->model);
g_object_unref (G_OBJECT (panel->priv->model));
gtk_container_add (GTK_CONTAINER (sw), panel->priv->treeview);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (panel->priv->treeview), FALSE);
gtk_tree_view_set_reorderable (GTK_TREE_VIEW (panel->priv->treeview), TRUE);
g_object_set (panel->priv->treeview, "has-tooltip", TRUE, NULL);
gtk_widget_show (panel->priv->treeview);
column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_title (column, _("Documents"));
cell = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (column, cell, FALSE);
gtk_tree_view_column_add_attribute (column, cell, "pixbuf", PIXBUF_COLUMN);
cell = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, cell, TRUE);
gtk_tree_view_column_add_attribute (column, cell, "markup", NAME_COLUMN);
gtk_tree_view_append_column (GTK_TREE_VIEW (panel->priv->treeview),
column);
selection = gtk_tree_view_get_selection (
GTK_TREE_VIEW (panel->priv->treeview));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
g_signal_connect (panel->priv->treeview,
"cursor_changed",
G_CALLBACK (treeview_cursor_changed),
panel);
g_signal_connect (panel->priv->treeview,
"button-press-event",
G_CALLBACK (panel_button_press_event),
panel);
g_signal_connect (panel->priv->treeview,
"popup-menu",
G_CALLBACK (panel_popup_menu),
panel);
g_signal_connect (panel->priv->treeview,
"query-tooltip",
G_CALLBACK (treeview_query_tooltip),
NULL);
g_signal_connect (panel->priv->model,
"row-inserted",
G_CALLBACK (treeview_row_inserted),
panel);
}
GtkWidget *
xedit_documents_panel_new (XeditWindow *window)
{
g_return_val_if_fail (XEDIT_IS_WINDOW (window), NULL);
return GTK_WIDGET (g_object_new (XEDIT_TYPE_DOCUMENTS_PANEL,
"window", window,
NULL));
}

View File

@@ -0,0 +1,93 @@
/*
* xedit-documents-panel.h
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_DOCUMENTS_PANEL_H__
#define __XEDIT_DOCUMENTS_PANEL_H__
#include <gtk/gtk.h>
#include <xedit/xedit-window.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_DOCUMENTS_PANEL (xedit_documents_panel_get_type())
#define XEDIT_DOCUMENTS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_DOCUMENTS_PANEL, XeditDocumentsPanel))
#define XEDIT_DOCUMENTS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_DOCUMENTS_PANEL, XeditDocumentsPanelClass))
#define XEDIT_IS_DOCUMENTS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_DOCUMENTS_PANEL))
#define XEDIT_IS_DOCUMENTS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_DOCUMENTS_PANEL))
#define XEDIT_DOCUMENTS_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_DOCUMENTS_PANEL, XeditDocumentsPanelClass))
/* Private structure type */
typedef struct _XeditDocumentsPanelPrivate XeditDocumentsPanelPrivate;
/*
* Main object structure
*/
typedef struct _XeditDocumentsPanel XeditDocumentsPanel;
struct _XeditDocumentsPanel
{
#if GTK_CHECK_VERSION (3, 0, 0)
GtkBox vbox;
#else
GtkVBox vbox;
#endif
/*< private > */
XeditDocumentsPanelPrivate *priv;
};
/*
* Class definition
*/
typedef struct _XeditDocumentsPanelClass XeditDocumentsPanelClass;
struct _XeditDocumentsPanelClass
{
#if GTK_CHECK_VERSION (3, 0, 0)
GtkBoxClass parent_class;
#else
GtkVBoxClass parent_class;
#endif
};
/*
* Public methods
*/
GType xedit_documents_panel_get_type (void) G_GNUC_CONST;
GtkWidget *xedit_documents_panel_new (XeditWindow *window);
G_END_DECLS
#endif /* __XEDIT_DOCUMENTS_PANEL_H__ */

View File

@@ -0,0 +1,469 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xedit-encodings-combo-box.c
* This file is part of xedit
*
* Copyright (C) 2003-2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2003-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id: xedit-encodings-combo-box.c 6112 2008-01-23 08:26:24Z sfre $
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <xedit/xedit-encodings-combo-box.h>
#include <xedit/xedit-prefs-manager.h>
#include <xedit/dialogs/xedit-encodings-dialog.h>
#define ENCODING_KEY "Enconding"
#define XEDIT_ENCODINGS_COMBO_BOX_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
XEDIT_TYPE_ENCODINGS_COMBO_BOX, \
XeditEncodingsComboBoxPrivate))
struct _XeditEncodingsComboBoxPrivate
{
GtkListStore *store;
glong changed_id;
guint activated_item;
guint save_mode : 1;
};
enum
{
NAME_COLUMN,
ENCODING_COLUMN,
ADD_COLUMN,
N_COLUMNS
};
/* Properties */
enum
{
PROP_0,
PROP_SAVE_MODE
};
G_DEFINE_TYPE(XeditEncodingsComboBox, xedit_encodings_combo_box, GTK_TYPE_COMBO_BOX)
static void update_menu (XeditEncodingsComboBox *combo_box);
static void
xedit_encodings_combo_box_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XeditEncodingsComboBox *combo;
combo = XEDIT_ENCODINGS_COMBO_BOX (object);
switch (prop_id)
{
case PROP_SAVE_MODE:
combo->priv->save_mode = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_encodings_combo_box_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XeditEncodingsComboBox *combo;
combo = XEDIT_ENCODINGS_COMBO_BOX (object);
switch (prop_id)
{
case PROP_SAVE_MODE:
g_value_set_boolean (value, combo->priv->save_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_encodings_combo_box_dispose (GObject *object)
{
XeditEncodingsComboBox *combo = XEDIT_ENCODINGS_COMBO_BOX (object);
if (combo->priv->store != NULL)
{
g_object_unref (combo->priv->store);
combo->priv->store = NULL;
}
G_OBJECT_CLASS (xedit_encodings_combo_box_parent_class)->dispose (object);
}
static void
xedit_encodings_combo_box_class_init (XeditEncodingsComboBoxClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = xedit_encodings_combo_box_set_property;
object_class->get_property = xedit_encodings_combo_box_get_property;
object_class->dispose = xedit_encodings_combo_box_dispose;
g_object_class_install_property (object_class,
PROP_SAVE_MODE,
g_param_spec_boolean ("save-mode",
"Save Mode",
"Save Mode",
FALSE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
g_type_class_add_private (object_class, sizeof (XeditEncodingsComboBoxPrivate));
}
static void
dialog_response_cb (GtkDialog *dialog,
gint response_id,
XeditEncodingsComboBox *menu)
{
if (response_id == GTK_RESPONSE_OK)
{
update_menu (menu);
}
gtk_widget_destroy (GTK_WIDGET (dialog));
}
static void
add_or_remove (XeditEncodingsComboBox *menu,
GtkTreeModel *model)
{
GtkTreeIter iter;
gboolean add_item = FALSE;
if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (menu), &iter))
{
gtk_tree_model_get (model, &iter,
ADD_COLUMN, &add_item,
-1);
}
if (!add_item)
{
menu->priv->activated_item = gtk_combo_box_get_active (GTK_COMBO_BOX (menu));
}
else
{
GtkWidget *dialog;
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu));
if (!gtk_widget_is_toplevel (toplevel))
toplevel = NULL;
g_signal_handler_block (menu, menu->priv->changed_id);
gtk_combo_box_set_active (GTK_COMBO_BOX (menu),
menu->priv->activated_item);
g_signal_handler_unblock (menu, menu->priv->changed_id);
dialog = xedit_encodings_dialog_new();
if (toplevel != NULL)
{
GtkWindowGroup *wg;
gtk_window_set_transient_for (GTK_WINDOW (dialog),
GTK_WINDOW (toplevel));
wg = gtk_window_get_group (GTK_WINDOW (toplevel));
if (wg == NULL)
{
wg = gtk_window_group_new ();
gtk_window_group_add_window (wg,
GTK_WINDOW (toplevel));
}
gtk_window_group_add_window (wg,
GTK_WINDOW (dialog));
}
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
g_signal_connect (dialog,
"response",
G_CALLBACK (dialog_response_cb),
menu);
gtk_widget_show (dialog);
}
}
static gboolean
separator_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
{
gchar *str;
gboolean ret;
gtk_tree_model_get (model, iter, NAME_COLUMN, &str, -1);
ret = (str == NULL || *str == '\0');
g_free (str);
return ret;
}
static void
update_menu (XeditEncodingsComboBox *menu)
{
GtkListStore *store;
GtkTreeIter iter;
GSList *encodings, *l;
gchar *str;
const XeditEncoding *utf8_encoding;
const XeditEncoding *current_encoding;
store = menu->priv->store;
/* Unset the previous model */
g_signal_handler_block (menu, menu->priv->changed_id);
gtk_list_store_clear (store);
gtk_combo_box_set_model (GTK_COMBO_BOX (menu),
NULL);
utf8_encoding = xedit_encoding_get_utf8 ();
current_encoding = xedit_encoding_get_current ();
if (!menu->priv->save_mode)
{
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
NAME_COLUMN, _("Automatically Detected"),
ENCODING_COLUMN, NULL,
ADD_COLUMN, FALSE,
-1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
NAME_COLUMN, "",
ENCODING_COLUMN, NULL,
ADD_COLUMN, FALSE,
-1);
}
if (current_encoding != utf8_encoding)
str = xedit_encoding_to_string (utf8_encoding);
else
str = g_strdup_printf (_("Current Locale (%s)"),
xedit_encoding_get_charset (utf8_encoding));
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
NAME_COLUMN, str,
ENCODING_COLUMN, utf8_encoding,
ADD_COLUMN, FALSE,
-1);
g_free (str);
if ((utf8_encoding != current_encoding) &&
(current_encoding != NULL))
{
str = g_strdup_printf (_("Current Locale (%s)"),
xedit_encoding_get_charset (current_encoding));
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
NAME_COLUMN, str,
ENCODING_COLUMN, current_encoding,
ADD_COLUMN, FALSE,
-1);
g_free (str);
}
encodings = xedit_prefs_manager_get_shown_in_menu_encodings ();
for (l = encodings; l != NULL; l = g_slist_next (l))
{
const XeditEncoding *enc = (const XeditEncoding *)l->data;
if ((enc != current_encoding) &&
(enc != utf8_encoding) &&
(enc != NULL))
{
str = xedit_encoding_to_string (enc);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
NAME_COLUMN, str,
ENCODING_COLUMN, enc,
ADD_COLUMN, FALSE,
-1);
g_free (str);
}
}
g_slist_free (encodings);
if (xedit_prefs_manager_shown_in_menu_encodings_can_set ())
{
gtk_list_store_append (store, &iter);
/* separator */
gtk_list_store_set (store, &iter,
NAME_COLUMN, "",
ENCODING_COLUMN, NULL,
ADD_COLUMN, FALSE,
-1);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
NAME_COLUMN, _("Add or Remove..."),
ENCODING_COLUMN, NULL,
ADD_COLUMN, TRUE,
-1);
}
/* set the model back */
gtk_combo_box_set_model (GTK_COMBO_BOX (menu),
GTK_TREE_MODEL (menu->priv->store));
gtk_combo_box_set_active (GTK_COMBO_BOX (menu), 0);
g_signal_handler_unblock (menu, menu->priv->changed_id);
}
static void
xedit_encodings_combo_box_init (XeditEncodingsComboBox *menu)
{
GtkCellRenderer *text_renderer;
menu->priv = XEDIT_ENCODINGS_COMBO_BOX_GET_PRIVATE (menu);
menu->priv->store = gtk_list_store_new (N_COLUMNS,
G_TYPE_STRING,
G_TYPE_POINTER,
G_TYPE_BOOLEAN);
/* Setup up the cells */
text_renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (menu),
text_renderer, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (menu),
text_renderer,
"text",
NAME_COLUMN,
NULL);
gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (menu),
separator_func, NULL,
NULL);
menu->priv->changed_id = g_signal_connect (menu, "changed",
G_CALLBACK (add_or_remove),
menu->priv->store);
update_menu (menu);
}
GtkWidget *
xedit_encodings_combo_box_new (gboolean save_mode)
{
return g_object_new (XEDIT_TYPE_ENCODINGS_COMBO_BOX,
"save_mode", save_mode,
NULL);
}
const XeditEncoding *
xedit_encodings_combo_box_get_selected_encoding (XeditEncodingsComboBox *menu)
{
GtkTreeIter iter;
g_return_val_if_fail (XEDIT_IS_ENCODINGS_COMBO_BOX (menu), NULL);
if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (menu), &iter))
{
const XeditEncoding *ret;
GtkTreeModel *model;
model = gtk_combo_box_get_model (GTK_COMBO_BOX (menu));
gtk_tree_model_get (model, &iter,
ENCODING_COLUMN, &ret,
-1);
return ret;
}
return NULL;
}
/**
* xedit_encodings_combo_box_set_selected_encoding:
* @menu:
* @encoding: (allow-none):
**/
void
xedit_encodings_combo_box_set_selected_encoding (XeditEncodingsComboBox *menu,
const XeditEncoding *encoding)
{
GtkTreeIter iter;
GtkTreeModel *model;
gboolean b;
g_return_if_fail (XEDIT_IS_ENCODINGS_COMBO_BOX (menu));
g_return_if_fail (GTK_IS_COMBO_BOX (menu));
model = gtk_combo_box_get_model (GTK_COMBO_BOX (menu));
b = gtk_tree_model_get_iter_first (model, &iter);
while (b)
{
const XeditEncoding *enc;
gtk_tree_model_get (model, &iter,
ENCODING_COLUMN, &enc,
-1);
if (enc == encoding)
{
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (menu),
&iter);
return;
}
b = gtk_tree_model_iter_next (model, &iter);
}
}

View File

@@ -0,0 +1,78 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xedit-encodings-combo-box.h
* This file is part of xedit
*
* Copyright (C) 2003-2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2003-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id: xedit-encodings-option-menu.h 4429 2005-12-12 17:28:04Z pborelli $
*/
#ifndef __XEDIT_ENCODINGS_COMBO_BOX_H__
#define __XEDIT_ENCODINGS_COMBO_BOX_H__
#include <gtk/gtk.h>
#include <xedit/xedit-encodings.h>
G_BEGIN_DECLS
#define XEDIT_TYPE_ENCODINGS_COMBO_BOX (xedit_encodings_combo_box_get_type ())
#define XEDIT_ENCODINGS_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_ENCODINGS_COMBO_BOX, XeditEncodingsComboBox))
#define XEDIT_ENCODINGS_COMBO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XEDIT_TYPE_ENCODINGS_COMBO_BOX, XeditEncodingsComboBoxClass))
#define XEDIT_IS_ENCODINGS_COMBO_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XEDIT_TYPE_ENCODINGS_COMBO_BOX))
#define XEDIT_IS_ENCODINGS_COMBO_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_ENCODINGS_COMBO_BOX))
#define XEDIT_ENCODINGS_COMBO_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XEDIT_TYPE_ENCODINGS_COMBO_BOX, XeditEncodingsComboBoxClass))
typedef struct _XeditEncodingsComboBox XeditEncodingsComboBox;
typedef struct _XeditEncodingsComboBoxClass XeditEncodingsComboBoxClass;
typedef struct _XeditEncodingsComboBoxPrivate XeditEncodingsComboBoxPrivate;
struct _XeditEncodingsComboBox
{
GtkComboBox parent;
XeditEncodingsComboBoxPrivate *priv;
};
struct _XeditEncodingsComboBoxClass
{
GtkComboBoxClass parent_class;
};
GType xedit_encodings_combo_box_get_type (void) G_GNUC_CONST;
/* Constructor */
GtkWidget *xedit_encodings_combo_box_new (gboolean save_mode);
const XeditEncoding *xedit_encodings_combo_box_get_selected_encoding (XeditEncodingsComboBox *menu);
void xedit_encodings_combo_box_set_selected_encoding (XeditEncodingsComboBox *menu,
const XeditEncoding *encoding);
G_END_DECLS
#endif /* __XEDIT_ENCODINGS_COMBO_BOX_H__ */

473
xedit/xedit-encodings.c Normal file
View File

@@ -0,0 +1,473 @@
/*
* xedit-encodings.c
* This file is part of xedit
*
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib/gi18n.h>
#include "xedit-encodings.h"
struct _XeditEncoding
{
gint index;
const gchar *charset;
const gchar *name;
};
/*
* The original versions of the following tables are taken from profterm
*
* Copyright (C) 2002 Red Hat, Inc.
*/
typedef enum
{
XEDIT_ENCODING_ISO_8859_1,
XEDIT_ENCODING_ISO_8859_2,
XEDIT_ENCODING_ISO_8859_3,
XEDIT_ENCODING_ISO_8859_4,
XEDIT_ENCODING_ISO_8859_5,
XEDIT_ENCODING_ISO_8859_6,
XEDIT_ENCODING_ISO_8859_7,
XEDIT_ENCODING_ISO_8859_8,
XEDIT_ENCODING_ISO_8859_9,
XEDIT_ENCODING_ISO_8859_10,
XEDIT_ENCODING_ISO_8859_13,
XEDIT_ENCODING_ISO_8859_14,
XEDIT_ENCODING_ISO_8859_15,
XEDIT_ENCODING_ISO_8859_16,
XEDIT_ENCODING_UTF_7,
XEDIT_ENCODING_UTF_16,
XEDIT_ENCODING_UTF_16_BE,
XEDIT_ENCODING_UTF_16_LE,
XEDIT_ENCODING_UTF_32,
XEDIT_ENCODING_UCS_2,
XEDIT_ENCODING_UCS_4,
XEDIT_ENCODING_ARMSCII_8,
XEDIT_ENCODING_BIG5,
XEDIT_ENCODING_BIG5_HKSCS,
XEDIT_ENCODING_CP_866,
XEDIT_ENCODING_EUC_JP,
XEDIT_ENCODING_EUC_JP_MS,
XEDIT_ENCODING_CP932,
XEDIT_ENCODING_EUC_KR,
XEDIT_ENCODING_EUC_TW,
XEDIT_ENCODING_GB18030,
XEDIT_ENCODING_GB2312,
XEDIT_ENCODING_GBK,
XEDIT_ENCODING_GEOSTD8,
XEDIT_ENCODING_IBM_850,
XEDIT_ENCODING_IBM_852,
XEDIT_ENCODING_IBM_855,
XEDIT_ENCODING_IBM_857,
XEDIT_ENCODING_IBM_862,
XEDIT_ENCODING_IBM_864,
XEDIT_ENCODING_ISO_2022_JP,
XEDIT_ENCODING_ISO_2022_KR,
XEDIT_ENCODING_ISO_IR_111,
XEDIT_ENCODING_JOHAB,
XEDIT_ENCODING_KOI8_R,
XEDIT_ENCODING_KOI8__R,
XEDIT_ENCODING_KOI8_U,
XEDIT_ENCODING_SHIFT_JIS,
XEDIT_ENCODING_TCVN,
XEDIT_ENCODING_TIS_620,
XEDIT_ENCODING_UHC,
XEDIT_ENCODING_VISCII,
XEDIT_ENCODING_WINDOWS_1250,
XEDIT_ENCODING_WINDOWS_1251,
XEDIT_ENCODING_WINDOWS_1252,
XEDIT_ENCODING_WINDOWS_1253,
XEDIT_ENCODING_WINDOWS_1254,
XEDIT_ENCODING_WINDOWS_1255,
XEDIT_ENCODING_WINDOWS_1256,
XEDIT_ENCODING_WINDOWS_1257,
XEDIT_ENCODING_WINDOWS_1258,
XEDIT_ENCODING_LAST,
XEDIT_ENCODING_UTF_8,
XEDIT_ENCODING_UNKNOWN
} XeditEncodingIndex;
static const XeditEncoding utf8_encoding = {
XEDIT_ENCODING_UTF_8,
"UTF-8",
N_("Unicode")
};
/* initialized in xedit_encoding_lazy_init() */
static XeditEncoding unknown_encoding = {
XEDIT_ENCODING_UNKNOWN,
NULL,
NULL
};
static const XeditEncoding encodings [] = {
{ XEDIT_ENCODING_ISO_8859_1,
"ISO-8859-1", N_("Western") },
{ XEDIT_ENCODING_ISO_8859_2,
"ISO-8859-2", N_("Central European") },
{ XEDIT_ENCODING_ISO_8859_3,
"ISO-8859-3", N_("South European") },
{ XEDIT_ENCODING_ISO_8859_4,
"ISO-8859-4", N_("Baltic") },
{ XEDIT_ENCODING_ISO_8859_5,
"ISO-8859-5", N_("Cyrillic") },
{ XEDIT_ENCODING_ISO_8859_6,
"ISO-8859-6", N_("Arabic") },
{ XEDIT_ENCODING_ISO_8859_7,
"ISO-8859-7", N_("Greek") },
{ XEDIT_ENCODING_ISO_8859_8,
"ISO-8859-8", N_("Hebrew Visual") },
{ XEDIT_ENCODING_ISO_8859_9,
"ISO-8859-9", N_("Turkish") },
{ XEDIT_ENCODING_ISO_8859_10,
"ISO-8859-10", N_("Nordic") },
{ XEDIT_ENCODING_ISO_8859_13,
"ISO-8859-13", N_("Baltic") },
{ XEDIT_ENCODING_ISO_8859_14,
"ISO-8859-14", N_("Celtic") },
{ XEDIT_ENCODING_ISO_8859_15,
"ISO-8859-15", N_("Western") },
{ XEDIT_ENCODING_ISO_8859_16,
"ISO-8859-16", N_("Romanian") },
{ XEDIT_ENCODING_UTF_7,
"UTF-7", N_("Unicode") },
{ XEDIT_ENCODING_UTF_16,
"UTF-16", N_("Unicode") },
{ XEDIT_ENCODING_UTF_16_BE,
"UTF-16BE", N_("Unicode") },
{ XEDIT_ENCODING_UTF_16_LE,
"UTF-16LE", N_("Unicode") },
{ XEDIT_ENCODING_UTF_32,
"UTF-32", N_("Unicode") },
{ XEDIT_ENCODING_UCS_2,
"UCS-2", N_("Unicode") },
{ XEDIT_ENCODING_UCS_4,
"UCS-4", N_("Unicode") },
{ XEDIT_ENCODING_ARMSCII_8,
"ARMSCII-8", N_("Armenian") },
{ XEDIT_ENCODING_BIG5,
"BIG5", N_("Chinese Traditional") },
{ XEDIT_ENCODING_BIG5_HKSCS,
"BIG5-HKSCS", N_("Chinese Traditional") },
{ XEDIT_ENCODING_CP_866,
"CP866", N_("Cyrillic/Russian") },
{ XEDIT_ENCODING_EUC_JP,
"EUC-JP", N_("Japanese") },
{ XEDIT_ENCODING_EUC_JP_MS,
"EUC-JP-MS", N_("Japanese") },
{ XEDIT_ENCODING_CP932,
"CP932", N_("Japanese") },
{ XEDIT_ENCODING_EUC_KR,
"EUC-KR", N_("Korean") },
{ XEDIT_ENCODING_EUC_TW,
"EUC-TW", N_("Chinese Traditional") },
{ XEDIT_ENCODING_GB18030,
"GB18030", N_("Chinese Simplified") },
{ XEDIT_ENCODING_GB2312,
"GB2312", N_("Chinese Simplified") },
{ XEDIT_ENCODING_GBK,
"GBK", N_("Chinese Simplified") },
{ XEDIT_ENCODING_GEOSTD8,
"GEORGIAN-ACADEMY", N_("Georgian") }, /* FIXME GEOSTD8 ? */
{ XEDIT_ENCODING_IBM_850,
"IBM850", N_("Western") },
{ XEDIT_ENCODING_IBM_852,
"IBM852", N_("Central European") },
{ XEDIT_ENCODING_IBM_855,
"IBM855", N_("Cyrillic") },
{ XEDIT_ENCODING_IBM_857,
"IBM857", N_("Turkish") },
{ XEDIT_ENCODING_IBM_862,
"IBM862", N_("Hebrew") },
{ XEDIT_ENCODING_IBM_864,
"IBM864", N_("Arabic") },
{ XEDIT_ENCODING_ISO_2022_JP,
"ISO-2022-JP", N_("Japanese") },
{ XEDIT_ENCODING_ISO_2022_KR,
"ISO-2022-KR", N_("Korean") },
{ XEDIT_ENCODING_ISO_IR_111,
"ISO-IR-111", N_("Cyrillic") },
{ XEDIT_ENCODING_JOHAB,
"JOHAB", N_("Korean") },
{ XEDIT_ENCODING_KOI8_R,
"KOI8R", N_("Cyrillic") },
{ XEDIT_ENCODING_KOI8__R,
"KOI8-R", N_("Cyrillic") },
{ XEDIT_ENCODING_KOI8_U,
"KOI8U", N_("Cyrillic/Ukrainian") },
{ XEDIT_ENCODING_SHIFT_JIS,
"SHIFT_JIS", N_("Japanese") },
{ XEDIT_ENCODING_TCVN,
"TCVN", N_("Vietnamese") },
{ XEDIT_ENCODING_TIS_620,
"TIS-620", N_("Thai") },
{ XEDIT_ENCODING_UHC,
"UHC", N_("Korean") },
{ XEDIT_ENCODING_VISCII,
"VISCII", N_("Vietnamese") },
{ XEDIT_ENCODING_WINDOWS_1250,
"WINDOWS-1250", N_("Central European") },
{ XEDIT_ENCODING_WINDOWS_1251,
"WINDOWS-1251", N_("Cyrillic") },
{ XEDIT_ENCODING_WINDOWS_1252,
"WINDOWS-1252", N_("Western") },
{ XEDIT_ENCODING_WINDOWS_1253,
"WINDOWS-1253", N_("Greek") },
{ XEDIT_ENCODING_WINDOWS_1254,
"WINDOWS-1254", N_("Turkish") },
{ XEDIT_ENCODING_WINDOWS_1255,
"WINDOWS-1255", N_("Hebrew") },
{ XEDIT_ENCODING_WINDOWS_1256,
"WINDOWS-1256", N_("Arabic") },
{ XEDIT_ENCODING_WINDOWS_1257,
"WINDOWS-1257", N_("Baltic") },
{ XEDIT_ENCODING_WINDOWS_1258,
"WINDOWS-1258", N_("Vietnamese") }
};
static void
xedit_encoding_lazy_init (void)
{
static gboolean initialized = FALSE;
const gchar *locale_charset;
if (initialized)
return;
if (g_get_charset (&locale_charset) == FALSE)
{
unknown_encoding.charset = g_strdup (locale_charset);
}
initialized = TRUE;
}
const XeditEncoding *
xedit_encoding_get_from_charset (const gchar *charset)
{
gint i;
g_return_val_if_fail (charset != NULL, NULL);
xedit_encoding_lazy_init ();
if (charset == NULL)
return NULL;
if (g_ascii_strcasecmp (charset, "UTF-8") == 0)
return xedit_encoding_get_utf8 ();
i = 0;
while (i < XEDIT_ENCODING_LAST)
{
if (g_ascii_strcasecmp (charset, encodings[i].charset) == 0)
return &encodings[i];
++i;
}
if (unknown_encoding.charset != NULL)
{
if (g_ascii_strcasecmp (charset, unknown_encoding.charset) == 0)
return &unknown_encoding;
}
return NULL;
}
const XeditEncoding *
xedit_encoding_get_from_index (gint idx)
{
g_return_val_if_fail (idx >= 0, NULL);
if (idx >= XEDIT_ENCODING_LAST)
return NULL;
xedit_encoding_lazy_init ();
return &encodings[idx];
}
const XeditEncoding *
xedit_encoding_get_utf8 (void)
{
xedit_encoding_lazy_init ();
return &utf8_encoding;
}
const XeditEncoding *
xedit_encoding_get_current (void)
{
static gboolean initialized = FALSE;
static const XeditEncoding *locale_encoding = NULL;
const gchar *locale_charset;
xedit_encoding_lazy_init ();
if (initialized != FALSE)
return locale_encoding;
if (g_get_charset (&locale_charset) == FALSE)
{
g_return_val_if_fail (locale_charset != NULL, &utf8_encoding);
locale_encoding = xedit_encoding_get_from_charset (locale_charset);
}
else
{
locale_encoding = &utf8_encoding;
}
if (locale_encoding == NULL)
{
locale_encoding = &unknown_encoding;
}
g_return_val_if_fail (locale_encoding != NULL, NULL);
initialized = TRUE;
return locale_encoding;
}
gchar *
xedit_encoding_to_string (const XeditEncoding* enc)
{
g_return_val_if_fail (enc != NULL, NULL);
xedit_encoding_lazy_init ();
g_return_val_if_fail (enc->charset != NULL, NULL);
if (enc->name != NULL)
{
return g_strdup_printf ("%s (%s)", _(enc->name), enc->charset);
}
else
{
if (g_ascii_strcasecmp (enc->charset, "ANSI_X3.4-1968") == 0)
return g_strdup_printf ("US-ASCII (%s)", enc->charset);
else
return g_strdup (enc->charset);
}
}
const gchar *
xedit_encoding_get_charset (const XeditEncoding* enc)
{
g_return_val_if_fail (enc != NULL, NULL);
xedit_encoding_lazy_init ();
g_return_val_if_fail (enc->charset != NULL, NULL);
return enc->charset;
}
const gchar *
xedit_encoding_get_name (const XeditEncoding* enc)
{
g_return_val_if_fail (enc != NULL, NULL);
xedit_encoding_lazy_init ();
return (enc->name == NULL) ? _("Unknown") : _(enc->name);
}
/* These are to make language bindings happy. Since Encodings are
* const, copy() just returns the same pointer and fres() doesn't
* do nothing */
XeditEncoding *
xedit_encoding_copy (const XeditEncoding *enc)
{
g_return_val_if_fail (enc != NULL, NULL);
return (XeditEncoding *) enc;
}
void
xedit_encoding_free (XeditEncoding *enc)
{
g_return_if_fail (enc != NULL);
}
/**
* xedit_encoding_get_type:
*
* Retrieves the GType object which is associated with the
* #XeditEncoding class.
*
* Return value: the GType associated with #XeditEncoding.
**/
GType
xedit_encoding_get_type (void)
{
static GType our_type = 0;
if (!our_type)
our_type = g_boxed_type_register_static (
"XeditEncoding",
(GBoxedCopyFunc) xedit_encoding_copy,
(GBoxedFreeFunc) xedit_encoding_free);
return our_type;
}

62
xedit/xedit-encodings.h Normal file
View File

@@ -0,0 +1,62 @@
/*
* xedit-encodings.h
* This file is part of xedit
*
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_ENCODINGS_H__
#define __XEDIT_ENCODINGS_H__
#include <glib.h>
#include <glib-object.h>
G_BEGIN_DECLS
typedef struct _XeditEncoding XeditEncoding;
#define XEDIT_TYPE_ENCODING (xedit_encoding_get_type ())
GType xedit_encoding_get_type (void) G_GNUC_CONST;
const XeditEncoding *xedit_encoding_get_from_charset (const gchar *charset);
const XeditEncoding *xedit_encoding_get_from_index (gint index);
gchar *xedit_encoding_to_string (const XeditEncoding *enc);
const gchar *xedit_encoding_get_name (const XeditEncoding *enc);
const gchar *xedit_encoding_get_charset (const XeditEncoding *enc);
const XeditEncoding *xedit_encoding_get_utf8 (void);
const XeditEncoding *xedit_encoding_get_current (void);
/* These should not be used, they are just to make python bindings happy */
XeditEncoding *xedit_encoding_copy (const XeditEncoding *enc);
void xedit_encoding_free (XeditEncoding *enc);
G_END_DECLS
#endif /* __XEDIT_ENCODINGS_H__ */

View File

@@ -0,0 +1,39 @@
/*** BEGIN file-header ***/
#include "xedit-enum-types.h"
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@filename@" */
#include "@filename@"
/*** END file-production ***/
/*** BEGIN value-header ***/
GType
@enum_name@_get_type (void)
{
static GType the_type = 0;
if (the_type == 0)
{
static const G@Type@Value values[] = {
/*** END value-header ***/
/*** BEGIN value-production ***/
{ @VALUENAME@,
"@VALUENAME@",
"@valuenick@" },
/*** END value-production ***/
/*** BEGIN value-tail ***/
{ 0, NULL, NULL }
};
the_type = g_@type@_register_static (
g_intern_static_string ("@EnumName@"),
values);
}
return the_type;
}
/*** END value-tail ***/

View File

@@ -0,0 +1,27 @@
/*** BEGIN file-header ***/
#ifndef __XEDIT_ENUM_TYPES_H__
#define __XEDIT_ENUM_TYPES_H__
#include <glib-object.h>
G_BEGIN_DECLS
/*** END file-header ***/
/*** BEGIN file-production ***/
/* Enumerations from "@filename@" */
/*** END file-production ***/
/*** BEGIN enumeration-production ***/
#define XEDIT_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
GType @enum_name@_get_type (void) G_GNUC_CONST;
/*** END enumeration-production ***/
/*** BEGIN file-tail ***/
G_END_DECLS
#endif /* __XEDIT_ENUM_TYPES_H__ */
/*** END file-tail ***/

View File

@@ -0,0 +1,586 @@
/*
* xedit-file-chooser-dialog.c
* This file is part of xedit
*
* Copyright (C) 2005-2007 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005-2007. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
/* TODO: Override set_extra_widget */
/* TODO: add encoding property */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#if GTK_CHECK_VERSION (3, 0, 0)
#include <gtksourceview/gtksource.h>
#endif
#include "xedit-file-chooser-dialog.h"
#include "xedit-encodings-combo-box.h"
#include "xedit-language-manager.h"
#include "xedit-prefs-manager-app.h"
#include "xedit-debug.h"
#include "xedit-enum-types.h"
#define XEDIT_FILE_CHOOSER_DIALOG_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), XEDIT_TYPE_FILE_CHOOSER_DIALOG, XeditFileChooserDialogPrivate))
#define ALL_FILES _("All Files")
#define ALL_TEXT_FILES _("All Text Files")
#if GTK_CHECK_VERSION (3, 0, 0)
#define gtk_hbox_new(X,Y) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,Y)
#endif
struct _XeditFileChooserDialogPrivate
{
GtkWidget *option_menu;
GtkWidget *extra_widget;
GtkWidget *newline_label;
GtkWidget *newline_combo;
GtkListStore *newline_store;
};
G_DEFINE_TYPE(XeditFileChooserDialog, xedit_file_chooser_dialog, GTK_TYPE_FILE_CHOOSER_DIALOG)
static void
xedit_file_chooser_dialog_class_init (XeditFileChooserDialogClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (object_class, sizeof(XeditFileChooserDialogPrivate));
}
static void
create_option_menu (XeditFileChooserDialog *dialog)
{
GtkWidget *label;
GtkWidget *menu;
label = gtk_label_new_with_mnemonic (_("C_haracter Encoding:"));
#if GTK_CHECK_VERSION (3, 16, 0)
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
#else
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
#endif
menu = xedit_encodings_combo_box_new (
gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), menu);
gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
label,
FALSE,
TRUE,
0);
gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
menu,
TRUE,
TRUE,
0);
gtk_widget_show (label);
gtk_widget_show (menu);
dialog->priv->option_menu = menu;
}
static void
update_newline_visibility (XeditFileChooserDialog *dialog)
{
if (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE)
{
gtk_widget_show (dialog->priv->newline_label);
gtk_widget_show (dialog->priv->newline_combo);
}
else
{
gtk_widget_hide (dialog->priv->newline_label);
gtk_widget_hide (dialog->priv->newline_combo);
}
}
static void
newline_combo_append (GtkComboBox *combo,
GtkListStore *store,
GtkTreeIter *iter,
const gchar *label,
XeditDocumentNewlineType newline_type)
{
gtk_list_store_append (store, iter);
gtk_list_store_set (store, iter, 0, label, 1, newline_type, -1);
if (newline_type == XEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT)
{
gtk_combo_box_set_active_iter (combo, iter);
}
}
static void
create_newline_combo (XeditFileChooserDialog *dialog)
{
GtkWidget *label, *combo;
GtkListStore *store;
GtkCellRenderer *renderer;
GtkTreeIter iter;
label = gtk_label_new_with_mnemonic (_("L_ine Ending:"));
#if GTK_CHECK_VERSION (3, 16, 0)
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
#else
gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
#endif
store = gtk_list_store_new (2, G_TYPE_STRING, XEDIT_TYPE_DOCUMENT_NEWLINE_TYPE);
combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo),
renderer,
TRUE);
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo),
renderer,
"text",
0);
newline_combo_append (GTK_COMBO_BOX (combo),
store,
&iter,
_("Unix/Linux"),
XEDIT_DOCUMENT_NEWLINE_TYPE_LF);
newline_combo_append (GTK_COMBO_BOX (combo),
store,
&iter,
_("Mac OS Classic"),
XEDIT_DOCUMENT_NEWLINE_TYPE_CR);
newline_combo_append (GTK_COMBO_BOX (combo),
store,
&iter,
_("Windows"),
XEDIT_DOCUMENT_NEWLINE_TYPE_CR_LF);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
label,
FALSE,
TRUE,
0);
gtk_box_pack_start (GTK_BOX (dialog->priv->extra_widget),
combo,
TRUE,
TRUE,
0);
dialog->priv->newline_combo = combo;
dialog->priv->newline_label = label;
dialog->priv->newline_store = store;
update_newline_visibility (dialog);
}
static void
create_extra_widget (XeditFileChooserDialog *dialog)
{
dialog->priv->extra_widget = gtk_hbox_new (FALSE, 6);
gtk_widget_show (dialog->priv->extra_widget);
create_option_menu (dialog);
create_newline_combo (dialog);
gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog),
dialog->priv->extra_widget);
}
static void
action_changed (XeditFileChooserDialog *dialog,
GParamSpec *pspec,
gpointer data)
{
GtkFileChooserAction action;
action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog));
switch (action)
{
case GTK_FILE_CHOOSER_ACTION_OPEN:
g_object_set (dialog->priv->option_menu,
"save_mode", FALSE,
NULL);
gtk_widget_show (dialog->priv->option_menu);
break;
case GTK_FILE_CHOOSER_ACTION_SAVE:
g_object_set (dialog->priv->option_menu,
"save_mode", TRUE,
NULL);
gtk_widget_show (dialog->priv->option_menu);
break;
default:
gtk_widget_hide (dialog->priv->option_menu);
}
update_newline_visibility (dialog);
}
static void
filter_changed (XeditFileChooserDialog *dialog,
GParamSpec *pspec,
gpointer data)
{
GtkFileFilter *filter;
if (!xedit_prefs_manager_active_file_filter_can_set ())
return;
filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog));
if (filter != NULL)
{
const gchar *name;
gint id = 0;
name = gtk_file_filter_get_name (filter);
g_return_if_fail (name != NULL);
if (strcmp (name, ALL_TEXT_FILES) == 0)
id = 1;
xedit_debug_message (DEBUG_COMMANDS, "Active filter: %s (%d)", name, id);
xedit_prefs_manager_set_active_file_filter (id);
}
}
/* FIXME: use globs too - Paolo (Aug. 27, 2007) */
static gboolean
all_text_files_filter (const GtkFileFilterInfo *filter_info,
gpointer data)
{
static GSList *known_mime_types = NULL;
GSList *mime_types;
if (known_mime_types == NULL)
{
GtkSourceLanguageManager *lm;
const gchar * const *languages;
lm = xedit_get_language_manager ();
languages = gtk_source_language_manager_get_language_ids (lm);
while ((languages != NULL) && (*languages != NULL))
{
gchar **mime_types;
gint i;
GtkSourceLanguage *lang;
lang = gtk_source_language_manager_get_language (lm, *languages);
#if GTK_CHECK_VERSION (3, 0, 0)
g_return_val_if_fail (GTK_SOURCE_IS_LANGUAGE (lang), FALSE);
#else
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (lang), FALSE);
#endif
++languages;
mime_types = gtk_source_language_get_mime_types (lang);
if (mime_types == NULL)
continue;
for (i = 0; mime_types[i] != NULL; i++)
{
if (!g_content_type_is_a (mime_types[i], "text/plain"))
{
xedit_debug_message (DEBUG_COMMANDS,
"Mime-type %s is not related to text/plain",
mime_types[i]);
known_mime_types = g_slist_prepend (known_mime_types,
g_strdup (mime_types[i]));
}
}
g_strfreev (mime_types);
}
/* known_mime_types always has "text/plain" as first item" */
known_mime_types = g_slist_prepend (known_mime_types, g_strdup ("text/plain"));
}
/* known mime_types contains "text/plain" and then the list of mime-types unrelated to "text/plain"
* that xedit recognizes */
if (filter_info->mime_type == NULL)
return FALSE;
/*
* The filter is matching:
* - the mime-types beginning with "text/"
* - the mime-types inheriting from a known mime-type (note the text/plain is
* the first known mime-type)
*/
if (strncmp (filter_info->mime_type, "text/", 5) == 0)
return TRUE;
mime_types = known_mime_types;
while (mime_types != NULL)
{
if (g_content_type_is_a (filter_info->mime_type, (const gchar*)mime_types->data))
return TRUE;
mime_types = g_slist_next (mime_types);
}
return FALSE;
}
static void
xedit_file_chooser_dialog_init (XeditFileChooserDialog *dialog)
{
dialog->priv = XEDIT_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
}
static GtkWidget *
xedit_file_chooser_dialog_new_valist (const gchar *title,
GtkWindow *parent,
GtkFileChooserAction action,
const XeditEncoding *encoding,
const gchar *first_button_text,
va_list varargs)
{
GtkWidget *result;
const char *button_text = first_button_text;
gint response_id;
GtkFileFilter *filter;
gint active_filter;
g_return_val_if_fail (parent != NULL, NULL);
result = g_object_new (XEDIT_TYPE_FILE_CHOOSER_DIALOG,
"title", title,
#if !GTK_CHECK_VERSION (3, 0, 0)
"file-system-backend", NULL,
#endif
"local-only", FALSE,
"action", action,
"select-multiple", action == GTK_FILE_CHOOSER_ACTION_OPEN,
NULL);
create_extra_widget (XEDIT_FILE_CHOOSER_DIALOG (result));
g_signal_connect (result,
"notify::action",
G_CALLBACK (action_changed),
NULL);
if (encoding != NULL)
xedit_encodings_combo_box_set_selected_encoding (
XEDIT_ENCODINGS_COMBO_BOX (XEDIT_FILE_CHOOSER_DIALOG (result)->priv->option_menu),
encoding);
active_filter = xedit_prefs_manager_get_active_file_filter ();
xedit_debug_message (DEBUG_COMMANDS, "Active filter: %d", active_filter);
/* Filters */
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, ALL_FILES);
gtk_file_filter_add_pattern (filter, "*");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (result), filter);
#if GTK_CHECK_VERSION (3, 0, 0)
gtk_file_chooser_set_action (GTK_FILE_CHOOSER (result), action);
#endif
if (active_filter != 1)
{
/* Make this filter the default */
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (result), filter);
}
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, ALL_TEXT_FILES);
gtk_file_filter_add_custom (filter,
GTK_FILE_FILTER_MIME_TYPE,
all_text_files_filter,
NULL,
NULL);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (result), filter);
if (active_filter == 1)
{
/* Make this filter the default */
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (result), filter);
}
g_signal_connect (result,
"notify::filter",
G_CALLBACK (filter_changed),
NULL);
gtk_window_set_transient_for (GTK_WINDOW (result), parent);
gtk_window_set_destroy_with_parent (GTK_WINDOW (result), TRUE);
while (button_text)
{
response_id = va_arg (varargs, gint);
gtk_dialog_add_button (GTK_DIALOG (result), button_text, response_id);
if ((response_id == GTK_RESPONSE_OK) ||
(response_id == GTK_RESPONSE_ACCEPT) ||
(response_id == GTK_RESPONSE_YES) ||
(response_id == GTK_RESPONSE_APPLY))
gtk_dialog_set_default_response (GTK_DIALOG (result), response_id);
button_text = va_arg (varargs, const gchar *);
}
return result;
}
/**
* xedit_file_chooser_dialog_new:
* @title: (allow-none): Title of the dialog, or %NULL
* @parent: (allow-none): Transient parent of the dialog, or %NULL
* @action: Open or save mode for the dialog
* @first_button_text: (allow-none): stock ID or text to go in
* the first button, or %NULL
* @Varargs: (allow-none): response ID for the first button, then
* additional (button, id) pairs, ending with %NULL
*
* Creates a new #XeditFileChooserDialog. This function is analogous to
* gtk_dialog_new_with_buttons().
*
* Return value: a new #XeditFileChooserDialog
*
**/
GtkWidget *
xedit_file_chooser_dialog_new (const gchar *title,
GtkWindow *parent,
GtkFileChooserAction action,
const XeditEncoding *encoding,
const gchar *first_button_text,
...)
{
GtkWidget *result;
va_list varargs;
va_start (varargs, first_button_text);
result = xedit_file_chooser_dialog_new_valist (title, parent, action,
encoding, first_button_text,
varargs);
va_end (varargs);
return result;
}
void
xedit_file_chooser_dialog_set_encoding (XeditFileChooserDialog *dialog,
const XeditEncoding *encoding)
{
g_return_if_fail (XEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
g_return_if_fail (XEDIT_IS_ENCODINGS_COMBO_BOX (dialog->priv->option_menu));
xedit_encodings_combo_box_set_selected_encoding (
XEDIT_ENCODINGS_COMBO_BOX (dialog->priv->option_menu),
encoding);
}
const XeditEncoding *
xedit_file_chooser_dialog_get_encoding (XeditFileChooserDialog *dialog)
{
g_return_val_if_fail (XEDIT_IS_FILE_CHOOSER_DIALOG (dialog), NULL);
g_return_val_if_fail (XEDIT_IS_ENCODINGS_COMBO_BOX (dialog->priv->option_menu), NULL);
g_return_val_if_fail ((gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_OPEN ||
gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE), NULL);
return xedit_encodings_combo_box_get_selected_encoding (
XEDIT_ENCODINGS_COMBO_BOX (dialog->priv->option_menu));
}
void
xedit_file_chooser_dialog_set_newline_type (XeditFileChooserDialog *dialog,
XeditDocumentNewlineType newline_type)
{
GtkTreeIter iter;
GtkTreeModel *model;
g_return_if_fail (XEDIT_IS_FILE_CHOOSER_DIALOG (dialog));
g_return_if_fail (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE);
model = GTK_TREE_MODEL (dialog->priv->newline_store);
if (!gtk_tree_model_get_iter_first (model, &iter))
{
return;
}
do
{
XeditDocumentNewlineType nt;
gtk_tree_model_get (model, &iter, 1, &nt, -1);
if (newline_type == nt)
{
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (dialog->priv->newline_combo),
&iter);
break;
}
} while (gtk_tree_model_iter_next (model, &iter));
}
XeditDocumentNewlineType
xedit_file_chooser_dialog_get_newline_type (XeditFileChooserDialog *dialog)
{
GtkTreeIter iter;
XeditDocumentNewlineType newline_type;
g_return_val_if_fail (XEDIT_IS_FILE_CHOOSER_DIALOG (dialog), XEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT);
g_return_val_if_fail (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) == GTK_FILE_CHOOSER_ACTION_SAVE,
XEDIT_DOCUMENT_NEWLINE_TYPE_DEFAULT);
gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->priv->newline_combo),
&iter);
gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->newline_store),
&iter,
1,
&newline_type,
-1);
return newline_type;
}

View File

@@ -0,0 +1,89 @@
/*
* xedit-file-chooser-dialog.h
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_FILE_CHOOSER_DIALOG_H__
#define __XEDIT_FILE_CHOOSER_DIALOG_H__
#include <gtk/gtk.h>
#include <xedit/xedit-encodings.h>
#include <xedit/xedit-enum-types.h>
#include <xedit/xedit-document.h>
G_BEGIN_DECLS
#define XEDIT_TYPE_FILE_CHOOSER_DIALOG (xedit_file_chooser_dialog_get_type ())
#define XEDIT_FILE_CHOOSER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_FILE_CHOOSER_DIALOG, XeditFileChooserDialog))
#define XEDIT_FILE_CHOOSER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XEDIT_TYPE_FILE_CHOOSER_DIALOG, XeditFileChooserDialogClass))
#define XEDIT_IS_FILE_CHOOSER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XEDIT_TYPE_FILE_CHOOSER_DIALOG))
#define XEDIT_IS_FILE_CHOOSER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_FILE_CHOOSER_DIALOG))
#define XEDIT_FILE_CHOOSER_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XEDIT_TYPE_FILE_CHOOSER_DIALOG, XeditFileChooserDialogClass))
typedef struct _XeditFileChooserDialog XeditFileChooserDialog;
typedef struct _XeditFileChooserDialogClass XeditFileChooserDialogClass;
typedef struct _XeditFileChooserDialogPrivate XeditFileChooserDialogPrivate;
struct _XeditFileChooserDialogClass
{
GtkFileChooserDialogClass parent_class;
};
struct _XeditFileChooserDialog
{
GtkFileChooserDialog parent_instance;
XeditFileChooserDialogPrivate *priv;
};
GType xedit_file_chooser_dialog_get_type (void) G_GNUC_CONST;
GtkWidget *xedit_file_chooser_dialog_new (const gchar *title,
GtkWindow *parent,
GtkFileChooserAction action,
const XeditEncoding *encoding,
const gchar *first_button_text,
...);
void xedit_file_chooser_dialog_set_encoding (XeditFileChooserDialog *dialog,
const XeditEncoding *encoding);
const XeditEncoding
*xedit_file_chooser_dialog_get_encoding (XeditFileChooserDialog *dialog);
void xedit_file_chooser_dialog_set_newline_type (XeditFileChooserDialog *dialog,
XeditDocumentNewlineType newline_type);
XeditDocumentNewlineType
xedit_file_chooser_dialog_get_newline_type (XeditFileChooserDialog *dialog);
G_END_DECLS
#endif /* __XEDIT_FILE_CHOOSER_DIALOG_H__ */

View File

@@ -0,0 +1,712 @@
/*
* xedit-gio-document-loader.c
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
* Copyright (C) 2008 - Jesse van den Kieboom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005-2008. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <gio/gio.h>
#include "xedit-gio-document-loader.h"
#include "xedit-document-output-stream.h"
#include "xedit-smart-charset-converter.h"
#include "xedit-prefs-manager.h"
#include "xedit-debug.h"
#include "xedit-utils.h"
#ifndef ENABLE_GVFS_METADATA
#include "xedit-metadata-manager.h"
#endif
typedef struct
{
XeditGioDocumentLoader *loader;
GCancellable *cancellable;
gssize read;
gboolean tried_mount;
} AsyncData;
#define READ_CHUNK_SIZE 8192
#define REMOTE_QUERY_ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \
G_FILE_ATTRIBUTE_STANDARD_TYPE "," \
G_FILE_ATTRIBUTE_TIME_MODIFIED "," \
G_FILE_ATTRIBUTE_STANDARD_SIZE "," \
G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE "," \
XEDIT_METADATA_ATTRIBUTE_ENCODING
#define XEDIT_GIO_DOCUMENT_LOADER_GET_PRIVATE(object) \
(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
XEDIT_TYPE_GIO_DOCUMENT_LOADER, \
XeditGioDocumentLoaderPrivate))
static void xedit_gio_document_loader_load (XeditDocumentLoader *loader);
static gboolean xedit_gio_document_loader_cancel (XeditDocumentLoader *loader);
static goffset xedit_gio_document_loader_get_bytes_read (XeditDocumentLoader *loader);
static void open_async_read (AsyncData *async);
struct _XeditGioDocumentLoaderPrivate
{
/* Info on the current file */
GFile *gfile;
goffset bytes_read;
/* Handle for remote files */
GCancellable *cancellable;
GInputStream *stream;
GOutputStream *output;
XeditSmartCharsetConverter *converter;
gchar buffer[READ_CHUNK_SIZE];
GError *error;
};
G_DEFINE_TYPE(XeditGioDocumentLoader, xedit_gio_document_loader, XEDIT_TYPE_DOCUMENT_LOADER)
static void
xedit_gio_document_loader_dispose (GObject *object)
{
XeditGioDocumentLoaderPrivate *priv;
priv = XEDIT_GIO_DOCUMENT_LOADER (object)->priv;
if (priv->cancellable != NULL)
{
g_cancellable_cancel (priv->cancellable);
g_object_unref (priv->cancellable);
priv->cancellable = NULL;
}
if (priv->stream != NULL)
{
g_object_unref (priv->stream);
priv->stream = NULL;
}
if (priv->output != NULL)
{
g_object_unref (priv->output);
priv->output = NULL;
}
if (priv->converter != NULL)
{
g_object_unref (priv->converter);
priv->converter = NULL;
}
if (priv->gfile != NULL)
{
g_object_unref (priv->gfile);
priv->gfile = NULL;
}
if (priv->error != NULL)
{
g_error_free (priv->error);
priv->error = NULL;
}
G_OBJECT_CLASS (xedit_gio_document_loader_parent_class)->dispose (object);
}
static void
xedit_gio_document_loader_class_init (XeditGioDocumentLoaderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
XeditDocumentLoaderClass *loader_class = XEDIT_DOCUMENT_LOADER_CLASS (klass);
object_class->dispose = xedit_gio_document_loader_dispose;
loader_class->load = xedit_gio_document_loader_load;
loader_class->cancel = xedit_gio_document_loader_cancel;
loader_class->get_bytes_read = xedit_gio_document_loader_get_bytes_read;
g_type_class_add_private (object_class, sizeof(XeditGioDocumentLoaderPrivate));
}
static void
xedit_gio_document_loader_init (XeditGioDocumentLoader *gvloader)
{
gvloader->priv = XEDIT_GIO_DOCUMENT_LOADER_GET_PRIVATE (gvloader);
gvloader->priv->converter = NULL;
gvloader->priv->error = NULL;
}
static AsyncData *
async_data_new (XeditGioDocumentLoader *gvloader)
{
AsyncData *async;
async = g_slice_new (AsyncData);
async->loader = gvloader;
async->cancellable = g_object_ref (gvloader->priv->cancellable);
async->tried_mount = FALSE;
return async;
}
static void
async_data_free (AsyncData *async)
{
g_object_unref (async->cancellable);
g_slice_free (AsyncData, async);
}
static const XeditEncoding *
get_metadata_encoding (XeditDocumentLoader *loader)
{
const XeditEncoding *enc = NULL;
#ifndef ENABLE_GVFS_METADATA
gchar *charset;
const gchar *uri;
uri = xedit_document_loader_get_uri (loader);
charset = xedit_metadata_manager_get (uri, "encoding");
if (charset == NULL)
return NULL;
enc = xedit_encoding_get_from_charset (charset);
g_free (charset);
#else
GFileInfo *info;
info = xedit_document_loader_get_info (loader);
/* check if the encoding was set in the metadata */
if (g_file_info_has_attribute (info, XEDIT_METADATA_ATTRIBUTE_ENCODING))
{
const gchar *charset;
charset = g_file_info_get_attribute_string (info,
XEDIT_METADATA_ATTRIBUTE_ENCODING);
if (charset == NULL)
return NULL;
enc = xedit_encoding_get_from_charset (charset);
}
#endif
return enc;
}
static void
remote_load_completed_or_failed (XeditGioDocumentLoader *loader, AsyncData *async)
{
xedit_document_loader_loading (XEDIT_DOCUMENT_LOADER (loader),
TRUE,
loader->priv->error);
if (async)
async_data_free (async);
}
static void
async_failed (AsyncData *async, GError *error)
{
g_propagate_error (&async->loader->priv->error, error);
remote_load_completed_or_failed (async->loader, async);
}
static void
close_input_stream_ready_cb (GInputStream *stream,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
xedit_debug (DEBUG_LOADER);
/* check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
xedit_debug_message (DEBUG_SAVER, "Finished closing input stream");
if (!g_input_stream_close_finish (stream, res, &error))
{
xedit_debug_message (DEBUG_SAVER, "Closing input stream error: %s", error->message);
async_failed (async, error);
return;
}
xedit_debug_message (DEBUG_SAVER, "Close output stream");
if (!g_output_stream_close (async->loader->priv->output,
async->cancellable, &error))
{
async_failed (async, error);
return;
}
remote_load_completed_or_failed (async->loader, async);
}
static void
write_complete (AsyncData *async)
{
XeditDocumentLoader *loader;
loader = XEDIT_DOCUMENT_LOADER (async->loader);
if (async->loader->priv->stream)
g_input_stream_close_async (G_INPUT_STREAM (async->loader->priv->stream),
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback)close_input_stream_ready_cb,
async);
}
/* prototype, because they call each other... isn't C lovely */
static void read_file_chunk (AsyncData *async);
static void
write_file_chunk (AsyncData *async)
{
XeditGioDocumentLoader *gvloader;
gssize bytes_written;
GError *error = NULL;
gvloader = async->loader;
/* we use sync methods on doc stream since it is in memory. Using async
would be racy and we can endup with invalidated iters */
bytes_written = g_output_stream_write (G_OUTPUT_STREAM (gvloader->priv->output),
gvloader->priv->buffer,
async->read,
async->cancellable,
&error);
xedit_debug_message (DEBUG_SAVER, "Written: %" G_GSSIZE_FORMAT, bytes_written);
if (bytes_written == -1)
{
xedit_debug_message (DEBUG_SAVER, "Write error: %s", error->message);
async_failed (async, error);
return;
}
/* note that this signal blocks the read... check if it isn't
* a performance problem
*/
xedit_document_loader_loading (XEDIT_DOCUMENT_LOADER (gvloader),
FALSE,
NULL);
read_file_chunk (async);
}
static void
async_read_cb (GInputStream *stream,
GAsyncResult *res,
AsyncData *async)
{
xedit_debug (DEBUG_LOADER);
XeditGioDocumentLoader *gvloader;
GError *error = NULL;
xedit_debug (DEBUG_LOADER);
/* manually check cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
gvloader = async->loader;
async->read = g_input_stream_read_finish (stream, res, &error);
/* error occurred */
if (async->read == -1)
{
async_failed (async, error);
return;
}
/* Check for the extremely unlikely case where the file size overflows. */
if (gvloader->priv->bytes_read + async->read < gvloader->priv->bytes_read)
{
g_set_error (&gvloader->priv->error,
XEDIT_DOCUMENT_ERROR,
XEDIT_DOCUMENT_ERROR_TOO_BIG,
"File too big");
async_failed (async, gvloader->priv->error);
return;
}
/* Bump the size. */
gvloader->priv->bytes_read += async->read;
/* end of the file, we are done! */
if (async->read == 0)
{
XeditDocumentLoader *loader;
loader = XEDIT_DOCUMENT_LOADER (gvloader);
g_output_stream_flush (gvloader->priv->output,
NULL,
&gvloader->priv->error);
loader->auto_detected_encoding =
xedit_smart_charset_converter_get_guessed (gvloader->priv->converter);
loader->auto_detected_newline_type =
xedit_document_output_stream_detect_newline_type (XEDIT_DOCUMENT_OUTPUT_STREAM (gvloader->priv->output));
/* Check if we needed some fallback char, if so, check if there was
a previous error and if not set a fallback used error */
/* FIXME Uncomment this when we want to manage conversion fallback */
/*if ((xedit_smart_charset_converter_get_num_fallbacks (gvloader->priv->converter) != 0) &&
gvloader->priv->error == NULL)
{
g_set_error_literal (&gvloader->priv->error,
XEDIT_DOCUMENT_ERROR,
XEDIT_DOCUMENT_ERROR_CONVERSION_FALLBACK,
"There was a conversion error and it was "
"needed to use a fallback char");
}*/
write_complete (async);
return;
}
write_file_chunk (async);
}
static void
read_file_chunk (AsyncData *async)
{
XeditGioDocumentLoader *gvloader;
gvloader = async->loader;
g_input_stream_read_async (G_INPUT_STREAM (gvloader->priv->stream),
gvloader->priv->buffer,
READ_CHUNK_SIZE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) async_read_cb,
async);
}
static GSList *
get_candidate_encodings (XeditGioDocumentLoader *gvloader)
{
const XeditEncoding *metadata;
GSList *encodings = NULL;
encodings = xedit_prefs_manager_get_auto_detected_encodings ();
metadata = get_metadata_encoding (XEDIT_DOCUMENT_LOADER (gvloader));
if (metadata != NULL)
{
encodings = g_slist_prepend (encodings, (gpointer)metadata);
}
return encodings;
}
static void
finish_query_info (AsyncData *async)
{
XeditGioDocumentLoader *gvloader;
XeditDocumentLoader *loader;
GInputStream *conv_stream;
GFileInfo *info;
GSList *candidate_encodings;
gvloader = async->loader;
loader = XEDIT_DOCUMENT_LOADER (gvloader);
info = loader->info;
/* if it's not a regular file, error out... */
if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_TYPE) &&
g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR)
{
g_set_error (&gvloader->priv->error,
G_IO_ERROR,
G_IO_ERROR_NOT_REGULAR_FILE,
"Not a regular file");
remote_load_completed_or_failed (gvloader, async);
return;
}
/* Get the candidate encodings */
if (loader->encoding == NULL)
{
candidate_encodings = get_candidate_encodings (gvloader);
}
else
{
candidate_encodings = g_slist_prepend (NULL, (gpointer) loader->encoding);
}
gvloader->priv->converter = xedit_smart_charset_converter_new (candidate_encodings);
g_slist_free (candidate_encodings);
conv_stream = g_converter_input_stream_new (gvloader->priv->stream,
G_CONVERTER (gvloader->priv->converter));
g_object_unref (gvloader->priv->stream);
gvloader->priv->stream = conv_stream;
/* Output stream */
gvloader->priv->output = xedit_document_output_stream_new (loader->document);
/* start reading */
read_file_chunk (async);
}
static void
query_info_cb (GFile *source,
GAsyncResult *res,
AsyncData *async)
{
XeditGioDocumentLoader *gvloader;
GFileInfo *info;
GError *error = NULL;
xedit_debug (DEBUG_LOADER);
/* manually check the cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
gvloader = async->loader;
/* finish the info query */
info = g_file_query_info_finish (gvloader->priv->gfile,
res,
&error);
if (info == NULL)
{
/* propagate the error and clean up */
async_failed (async, error);
return;
}
XEDIT_DOCUMENT_LOADER (gvloader)->info = info;
finish_query_info (async);
}
static void
mount_ready_callback (GFile *file,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
gboolean mounted;
xedit_debug (DEBUG_LOADER);
/* manual check for cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
if (!mounted)
{
async_failed (async, error);
}
else
{
/* try again to open the file for reading */
open_async_read (async);
}
}
static void
recover_not_mounted (AsyncData *async)
{
XeditDocument *doc;
GMountOperation *mount_operation;
xedit_debug (DEBUG_LOADER);
doc = xedit_document_loader_get_document (XEDIT_DOCUMENT_LOADER (async->loader));
mount_operation = _xedit_document_create_mount_operation (doc);
async->tried_mount = TRUE;
g_file_mount_enclosing_volume (async->loader->priv->gfile,
G_MOUNT_MOUNT_NONE,
mount_operation,
async->cancellable,
(GAsyncReadyCallback) mount_ready_callback,
async);
g_object_unref (mount_operation);
}
static void
async_read_ready_callback (GObject *source,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
XeditGioDocumentLoader *gvloader;
xedit_debug (DEBUG_LOADER);
/* manual check for cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
gvloader = async->loader;
gvloader->priv->stream = G_INPUT_STREAM (g_file_read_finish (gvloader->priv->gfile,
res, &error));
if (!gvloader->priv->stream)
{
if (error->code == G_IO_ERROR_NOT_MOUNTED && !async->tried_mount)
{
recover_not_mounted (async);
g_error_free (error);
return;
}
/* Propagate error */
g_propagate_error (&gvloader->priv->error, error);
xedit_document_loader_loading (XEDIT_DOCUMENT_LOADER (gvloader),
TRUE,
gvloader->priv->error);
async_data_free (async);
return;
}
/* get the file info: note we cannot use
* g_file_input_stream_query_info_async since it is not able to get the
* content type etc, beside it is not supported by gvfs.
* Using the file instead of the stream is slightly racy, but for
* loading this is not too bad...
*/
g_file_query_info_async (gvloader->priv->gfile,
REMOTE_QUERY_ATTRIBUTES,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) query_info_cb,
async);
}
static void
open_async_read (AsyncData *async)
{
g_file_read_async (async->loader->priv->gfile,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) async_read_ready_callback,
async);
}
static void
xedit_gio_document_loader_load (XeditDocumentLoader *loader)
{
XeditGioDocumentLoader *gvloader = XEDIT_GIO_DOCUMENT_LOADER (loader);
AsyncData *async;
xedit_debug (DEBUG_LOADER);
/* make sure no load operation is currently running */
g_return_if_fail (gvloader->priv->cancellable == NULL);
gvloader->priv->gfile = g_file_new_for_uri (loader->uri);
/* loading start */
xedit_document_loader_loading (XEDIT_DOCUMENT_LOADER (gvloader),
FALSE,
NULL);
gvloader->priv->cancellable = g_cancellable_new ();
async = async_data_new (gvloader);
open_async_read (async);
}
static goffset
xedit_gio_document_loader_get_bytes_read (XeditDocumentLoader *loader)
{
return XEDIT_GIO_DOCUMENT_LOADER (loader)->priv->bytes_read;
}
static gboolean
xedit_gio_document_loader_cancel (XeditDocumentLoader *loader)
{
XeditGioDocumentLoader *gvloader = XEDIT_GIO_DOCUMENT_LOADER (loader);
if (gvloader->priv->cancellable == NULL)
return FALSE;
g_cancellable_cancel (gvloader->priv->cancellable);
g_set_error (&gvloader->priv->error,
G_IO_ERROR,
G_IO_ERROR_CANCELLED,
"Operation cancelled");
remote_load_completed_or_failed (gvloader, NULL);
return TRUE;
}

View File

@@ -0,0 +1,79 @@
/*
* xedit-gio-document-loader.h
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
* Copyright (C) 2008 - Jesse van den Kieboom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005-2008. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_GIO_DOCUMENT_LOADER_H__
#define __XEDIT_GIO_DOCUMENT_LOADER_H__
#include <xedit/xedit-document.h>
#include "xedit-document-loader.h"
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_GIO_DOCUMENT_LOADER (xedit_gio_document_loader_get_type())
#define XEDIT_GIO_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_GIO_DOCUMENT_LOADER, XeditGioDocumentLoader))
#define XEDIT_GIO_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_GIO_DOCUMENT_LOADER, XeditGioDocumentLoaderClass))
#define XEDIT_IS_GIO_DOCUMENT_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_GIO_DOCUMENT_LOADER))
#define XEDIT_IS_GIO_DOCUMENT_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_GIO_DOCUMENT_LOADER))
#define XEDIT_GIO_DOCUMENT_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_GIO_DOCUMENT_LOADER, XeditGioDocumentLoaderClass))
/* Private structure type */
typedef struct _XeditGioDocumentLoaderPrivate XeditGioDocumentLoaderPrivate;
/*
* Main object structure
*/
typedef struct _XeditGioDocumentLoader XeditGioDocumentLoader;
struct _XeditGioDocumentLoader
{
XeditDocumentLoader loader;
/*< private > */
XeditGioDocumentLoaderPrivate *priv;
};
/*
* Class definition
*/
typedef XeditDocumentLoaderClass XeditGioDocumentLoaderClass;
/*
* Public methods
*/
GType xedit_gio_document_loader_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __XEDIT_GIO_DOCUMENT_LOADER_H__ */

View File

@@ -0,0 +1,775 @@
/*
* xedit-gio-document-saver.c
* This file is part of xedit
*
* Copyright (C) 2005-2006 - Paolo Borelli and Paolo Maggi
* Copyright (C) 2007 - Paolo Borelli, Paolo Maggi, Steve Frécinaux
* Copyright (C) 2008 - Jesse van den Kieboom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005-2006. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n.h>
#include <glib.h>
#include <gio/gio.h>
#include <string.h>
#include "xedit-gio-document-saver.h"
#include "xedit-document-input-stream.h"
#include "xedit-debug.h"
#define WRITE_CHUNK_SIZE 8192
typedef struct
{
XeditGioDocumentSaver *saver;
gchar buffer[WRITE_CHUNK_SIZE];
GCancellable *cancellable;
gboolean tried_mount;
gssize written;
gssize read;
GError *error;
} AsyncData;
#define REMOTE_QUERY_ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," \
G_FILE_ATTRIBUTE_TIME_MODIFIED
#define XEDIT_GIO_DOCUMENT_SAVER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
XEDIT_TYPE_GIO_DOCUMENT_SAVER, \
XeditGioDocumentSaverPrivate))
static void xedit_gio_document_saver_save (XeditDocumentSaver *saver,
GTimeVal *old_mtime);
static goffset xedit_gio_document_saver_get_file_size (XeditDocumentSaver *saver);
static goffset xedit_gio_document_saver_get_bytes_written (XeditDocumentSaver *saver);
static void check_modified_async (AsyncData *async);
struct _XeditGioDocumentSaverPrivate
{
GTimeVal old_mtime;
goffset size;
goffset bytes_written;
GFile *gfile;
GCancellable *cancellable;
GOutputStream *stream;
GInputStream *input;
GError *error;
};
G_DEFINE_TYPE(XeditGioDocumentSaver, xedit_gio_document_saver, XEDIT_TYPE_DOCUMENT_SAVER)
static void
xedit_gio_document_saver_dispose (GObject *object)
{
XeditGioDocumentSaverPrivate *priv = XEDIT_GIO_DOCUMENT_SAVER (object)->priv;
if (priv->cancellable != NULL)
{
g_cancellable_cancel (priv->cancellable);
g_object_unref (priv->cancellable);
priv->cancellable = NULL;
}
if (priv->gfile != NULL)
{
g_object_unref (priv->gfile);
priv->gfile = NULL;
}
if (priv->error != NULL)
{
g_error_free (priv->error);
priv->error = NULL;
}
if (priv->stream != NULL)
{
g_object_unref (priv->stream);
priv->stream = NULL;
}
if (priv->input != NULL)
{
g_object_unref (priv->input);
priv->input = NULL;
}
G_OBJECT_CLASS (xedit_gio_document_saver_parent_class)->dispose (object);
}
static AsyncData *
async_data_new (XeditGioDocumentSaver *gvsaver)
{
AsyncData *async;
async = g_slice_new (AsyncData);
async->saver = gvsaver;
async->cancellable = g_object_ref (gvsaver->priv->cancellable);
async->tried_mount = FALSE;
async->written = 0;
async->read = 0;
async->error = NULL;
return async;
}
static void
async_data_free (AsyncData *async)
{
g_object_unref (async->cancellable);
if (async->error)
{
g_error_free (async->error);
}
g_slice_free (AsyncData, async);
}
static void
xedit_gio_document_saver_class_init (XeditGioDocumentSaverClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
XeditDocumentSaverClass *saver_class = XEDIT_DOCUMENT_SAVER_CLASS (klass);
object_class->dispose = xedit_gio_document_saver_dispose;
saver_class->save = xedit_gio_document_saver_save;
saver_class->get_file_size = xedit_gio_document_saver_get_file_size;
saver_class->get_bytes_written = xedit_gio_document_saver_get_bytes_written;
g_type_class_add_private (object_class, sizeof(XeditGioDocumentSaverPrivate));
}
static void
xedit_gio_document_saver_init (XeditGioDocumentSaver *gvsaver)
{
gvsaver->priv = XEDIT_GIO_DOCUMENT_SAVER_GET_PRIVATE (gvsaver);
gvsaver->priv->cancellable = g_cancellable_new ();
gvsaver->priv->error = NULL;
}
static void
remote_save_completed_or_failed (XeditGioDocumentSaver *gvsaver,
AsyncData *async)
{
xedit_document_saver_saving (XEDIT_DOCUMENT_SAVER (gvsaver),
TRUE,
gvsaver->priv->error);
if (async)
async_data_free (async);
}
static void
async_failed (AsyncData *async,
GError *error)
{
g_propagate_error (&async->saver->priv->error, error);
remote_save_completed_or_failed (async->saver, async);
}
/* BEGIN NOTE:
*
* This fixes an issue in GOutputStream that applies the atomic replace
* save strategy. The stream moves the written file to the original file
* when the stream is closed. However, there is no way currently to tell
* the stream that the save should be aborted (there could be a
* conversion error). The patch explicitly closes the output stream
* in all these cases with a GCancellable in the cancelled state, causing
* the output stream to close, but not move the file. This makes use
* of an implementation detail in the local gio file stream and should be
* properly fixed by adding the appropriate API in gio. Until then, at least
* we prevent data corruption for now.
*
* Relevant bug reports:
*
* Bug 615110 - write file ignore encoding errors (xedit)
* https://bugzilla.gnome.org/show_bug.cgi?id=615110
*
* Bug 602412 - g_file_replace does not restore original file when there is
* errors while writing (glib/gio)
* https://bugzilla.gnome.org/show_bug.cgi?id=602412
*/
static void
cancel_output_stream_ready_cb (GOutputStream *stream,
GAsyncResult *result,
AsyncData *async)
{
GError *error;
g_output_stream_close_finish (stream, result, NULL);
/* check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable) || async->error == NULL)
{
async_data_free (async);
return;
}
error = async->error;
async->error = NULL;
async_failed (async, error);
}
static void
cancel_output_stream (AsyncData *async)
{
GCancellable *cancellable;
xedit_debug_message (DEBUG_SAVER, "Cancel output stream");
cancellable = g_cancellable_new ();
g_cancellable_cancel (cancellable);
g_output_stream_close_async (async->saver->priv->stream,
G_PRIORITY_HIGH,
cancellable,
(GAsyncReadyCallback)cancel_output_stream_ready_cb,
async);
g_object_unref (cancellable);
}
static void
cancel_output_stream_and_fail (AsyncData *async,
GError *error)
{
xedit_debug_message (DEBUG_SAVER, "Cancel output stream and fail");
g_propagate_error (&async->error, error);
cancel_output_stream (async);
}
/*
* END NOTE
*/
static void
remote_get_info_cb (GFile *source,
GAsyncResult *res,
AsyncData *async)
{
XeditGioDocumentSaver *saver;
GFileInfo *info;
GError *error = NULL;
xedit_debug (DEBUG_SAVER);
/* check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
saver = async->saver;
xedit_debug_message (DEBUG_SAVER, "Finished query info on file");
info = g_file_query_info_finish (source, res, &error);
if (info != NULL)
{
if (XEDIT_DOCUMENT_SAVER (saver)->info != NULL)
g_object_unref (XEDIT_DOCUMENT_SAVER (saver)->info);
XEDIT_DOCUMENT_SAVER (saver)->info = info;
}
else
{
xedit_debug_message (DEBUG_SAVER, "Query info failed: %s", error->message);
g_propagate_error (&saver->priv->error, error);
}
remote_save_completed_or_failed (saver, async);
}
static void
close_async_ready_get_info_cb (GOutputStream *stream,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
xedit_debug (DEBUG_SAVER);
/* check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
xedit_debug_message (DEBUG_SAVER, "Finished closing stream");
if (!g_output_stream_close_finish (stream, res, &error))
{
xedit_debug_message (DEBUG_SAVER, "Closing stream error: %s", error->message);
async_failed (async, error);
return;
}
/* get the file info: note we cannot use
* g_file_output_stream_query_info_async since it is not able to get the
* content type etc, beside it is not supported by gvfs.
* I'm not sure this is actually necessary, can't we just use
* g_content_type_guess (since we have the file name and the data)
*/
xedit_debug_message (DEBUG_SAVER, "Query info on file");
g_file_query_info_async (async->saver->priv->gfile,
REMOTE_QUERY_ATTRIBUTES,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) remote_get_info_cb,
async);
}
static void
write_complete (AsyncData *async)
{
GError *error = NULL;
/* first we close the input stream */
xedit_debug_message (DEBUG_SAVER, "Close input stream");
if (!g_input_stream_close (async->saver->priv->input,
async->cancellable, &error))
{
xedit_debug_message (DEBUG_SAVER, "Closing input stream error: %s", error->message);
cancel_output_stream_and_fail (async, error);
return;
}
/* now we close the output stream */
xedit_debug_message (DEBUG_SAVER, "Close output stream");
g_output_stream_close_async (async->saver->priv->stream,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback)close_async_ready_get_info_cb,
async);
}
/* prototype, because they call each other... isn't C lovely */
static void read_file_chunk (AsyncData *async);
static void write_file_chunk (AsyncData *async);
static void
async_write_cb (GOutputStream *stream,
GAsyncResult *res,
AsyncData *async)
{
XeditGioDocumentSaver *gvsaver;
gssize bytes_written;
GError *error = NULL;
xedit_debug (DEBUG_SAVER);
/* Check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
cancel_output_stream (async);
return;
}
bytes_written = g_output_stream_write_finish (stream, res, &error);
xedit_debug_message (DEBUG_SAVER, "Written: %" G_GSSIZE_FORMAT, bytes_written);
if (bytes_written == -1)
{
xedit_debug_message (DEBUG_SAVER, "Write error: %s", error->message);
cancel_output_stream_and_fail (async, error);
return;
}
gvsaver = async->saver;
async->written += bytes_written;
/* write again */
if (async->written != async->read)
{
write_file_chunk (async);
return;
}
/* note that this signal blocks the write... check if it isn't
* a performance problem
*/
xedit_document_saver_saving (XEDIT_DOCUMENT_SAVER (gvsaver),
FALSE,
NULL);
read_file_chunk (async);
}
static void
write_file_chunk (AsyncData *async)
{
XeditGioDocumentSaver *gvsaver;
xedit_debug (DEBUG_SAVER);
gvsaver = async->saver;
g_output_stream_write_async (G_OUTPUT_STREAM (gvsaver->priv->stream),
async->buffer + async->written,
async->read - async->written,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) async_write_cb,
async);
}
static void
read_file_chunk (AsyncData *async)
{
XeditGioDocumentSaver *gvsaver;
XeditDocumentInputStream *dstream;
GError *error = NULL;
xedit_debug (DEBUG_SAVER);
gvsaver = async->saver;
async->written = 0;
/* we use sync methods on doc stream since it is in memory. Using async
would be racy and we can endup with invalidated iters */
async->read = g_input_stream_read (gvsaver->priv->input,
async->buffer,
WRITE_CHUNK_SIZE,
async->cancellable,
&error);
if (error != NULL)
{
cancel_output_stream_and_fail (async, error);
return;
}
/* Check if we finished reading and writing */
if (async->read == 0)
{
write_complete (async);
return;
}
/* Get how many chars have been read */
dstream = XEDIT_DOCUMENT_INPUT_STREAM (gvsaver->priv->input);
gvsaver->priv->bytes_written = xedit_document_input_stream_tell (dstream);
write_file_chunk (async);
}
static void
async_replace_ready_callback (GFile *source,
GAsyncResult *res,
AsyncData *async)
{
XeditGioDocumentSaver *gvsaver;
XeditDocumentSaver *saver;
GCharsetConverter *converter;
GFileOutputStream *file_stream;
GError *error = NULL;
xedit_debug (DEBUG_SAVER);
/* Check cancelled state manually */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
gvsaver = async->saver;
saver = XEDIT_DOCUMENT_SAVER (gvsaver);
file_stream = g_file_replace_finish (source, res, &error);
/* handle any error that might occur */
if (!file_stream)
{
xedit_debug_message (DEBUG_SAVER, "Opening file failed: %s", error->message);
async_failed (async, error);
return;
}
/* FIXME: manage converter error? */
xedit_debug_message (DEBUG_SAVER, "Encoding charset: %s",
xedit_encoding_get_charset (saver->encoding));
if (saver->encoding != xedit_encoding_get_utf8 ())
{
converter = g_charset_converter_new (xedit_encoding_get_charset (saver->encoding),
"UTF-8",
NULL);
gvsaver->priv->stream = g_converter_output_stream_new (G_OUTPUT_STREAM (file_stream),
G_CONVERTER (converter));
g_object_unref (file_stream);
g_object_unref (converter);
}
else
{
gvsaver->priv->stream = G_OUTPUT_STREAM (file_stream);
}
gvsaver->priv->input = xedit_document_input_stream_new (GTK_TEXT_BUFFER (saver->document),
saver->newline_type);
gvsaver->priv->size = xedit_document_input_stream_get_total_size (XEDIT_DOCUMENT_INPUT_STREAM (gvsaver->priv->input));
read_file_chunk (async);
}
static void
begin_write (AsyncData *async)
{
XeditGioDocumentSaver *gvsaver;
XeditDocumentSaver *saver;
gboolean backup;
xedit_debug_message (DEBUG_SAVER, "Start replacing file contents");
/* For remote files we simply use g_file_replace_async. There is no
* backup as of yet
*/
gvsaver = async->saver;
saver = XEDIT_DOCUMENT_SAVER (gvsaver);
/* Do not make backups for remote files so they do not clutter remote systems */
backup = (saver->keep_backup && xedit_document_is_local (saver->document));
xedit_debug_message (DEBUG_SAVER, "File contents size: %" G_GINT64_FORMAT, gvsaver->priv->size);
xedit_debug_message (DEBUG_SAVER, "Calling replace_async");
xedit_debug_message (DEBUG_SAVER, backup ? "Keep backup" : "Discard backup");
g_file_replace_async (gvsaver->priv->gfile,
NULL,
backup,
G_FILE_CREATE_NONE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) async_replace_ready_callback,
async);
}
static void
mount_ready_callback (GFile *file,
GAsyncResult *res,
AsyncData *async)
{
GError *error = NULL;
gboolean mounted;
xedit_debug (DEBUG_SAVER);
/* manual check for cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
if (!mounted)
{
async_failed (async, error);
}
else
{
/* try again to get the modified state */
check_modified_async (async);
}
}
static void
recover_not_mounted (AsyncData *async)
{
XeditDocument *doc;
GMountOperation *mount_operation;
xedit_debug (DEBUG_LOADER);
doc = xedit_document_saver_get_document (XEDIT_DOCUMENT_SAVER (async->saver));
mount_operation = _xedit_document_create_mount_operation (doc);
async->tried_mount = TRUE;
g_file_mount_enclosing_volume (async->saver->priv->gfile,
G_MOUNT_MOUNT_NONE,
mount_operation,
async->cancellable,
(GAsyncReadyCallback) mount_ready_callback,
async);
g_object_unref (mount_operation);
}
static void
check_modification_callback (GFile *source,
GAsyncResult *res,
AsyncData *async)
{
XeditGioDocumentSaver *gvsaver;
GError *error = NULL;
GFileInfo *info;
xedit_debug (DEBUG_SAVER);
/* manually check cancelled state */
if (g_cancellable_is_cancelled (async->cancellable))
{
async_data_free (async);
return;
}
gvsaver = async->saver;
info = g_file_query_info_finish (source, res, &error);
if (info == NULL)
{
if (error->code == G_IO_ERROR_NOT_MOUNTED && !async->tried_mount)
{
recover_not_mounted (async);
g_error_free (error);
return;
}
/* it's perfectly fine if the file doesn't exist yet */
if (error->code != G_IO_ERROR_NOT_FOUND)
{
xedit_debug_message (DEBUG_SAVER, "Error getting modification: %s", error->message);
async_failed (async, error);
return;
}
}
/* check if the mtime is > what we know about it (if we have it) */
if (info != NULL && g_file_info_has_attribute (info,
G_FILE_ATTRIBUTE_TIME_MODIFIED))
{
GTimeVal mtime;
GTimeVal old_mtime;
g_file_info_get_modification_time (info, &mtime);
old_mtime = gvsaver->priv->old_mtime;
if ((old_mtime.tv_sec > 0 || old_mtime.tv_usec > 0) &&
(mtime.tv_sec != old_mtime.tv_sec || mtime.tv_usec != old_mtime.tv_usec) &&
(XEDIT_DOCUMENT_SAVER (gvsaver)->flags & XEDIT_DOCUMENT_SAVE_IGNORE_MTIME) == 0)
{
xedit_debug_message (DEBUG_SAVER, "File is externally modified");
g_set_error (&gvsaver->priv->error,
XEDIT_DOCUMENT_ERROR,
XEDIT_DOCUMENT_ERROR_EXTERNALLY_MODIFIED,
"Externally modified");
remote_save_completed_or_failed (gvsaver, async);
g_object_unref (info);
return;
}
}
if (info != NULL)
g_object_unref (info);
/* modification check passed, start write */
begin_write (async);
}
static void
check_modified_async (AsyncData *async)
{
xedit_debug_message (DEBUG_SAVER, "Check externally modified");
g_file_query_info_async (async->saver->priv->gfile,
G_FILE_ATTRIBUTE_TIME_MODIFIED,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_HIGH,
async->cancellable,
(GAsyncReadyCallback) check_modification_callback,
async);
}
static gboolean
save_remote_file_real (XeditGioDocumentSaver *gvsaver)
{
AsyncData *async;
xedit_debug_message (DEBUG_SAVER, "Starting gio save");
/* First find out if the file is modified externally. This requires
* a stat, but I don't think we can do this any other way
*/
async = async_data_new (gvsaver);
check_modified_async (async);
/* return false to stop timeout */
return FALSE;
}
static void
xedit_gio_document_saver_save (XeditDocumentSaver *saver,
GTimeVal *old_mtime)
{
XeditGioDocumentSaver *gvsaver = XEDIT_GIO_DOCUMENT_SAVER (saver);
gvsaver->priv->old_mtime = *old_mtime;
gvsaver->priv->gfile = g_file_new_for_uri (saver->uri);
/* saving start */
xedit_document_saver_saving (saver, FALSE, NULL);
g_timeout_add_full (G_PRIORITY_HIGH,
0,
(GSourceFunc) save_remote_file_real,
gvsaver,
NULL);
}
static goffset
xedit_gio_document_saver_get_file_size (XeditDocumentSaver *saver)
{
return XEDIT_GIO_DOCUMENT_SAVER (saver)->priv->size;
}
static goffset
xedit_gio_document_saver_get_bytes_written (XeditDocumentSaver *saver)
{
return XEDIT_GIO_DOCUMENT_SAVER (saver)->priv->bytes_written;
}

View File

@@ -0,0 +1,76 @@
/*
* xedit-gio-document-saver.h
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
* Copyrhing (C) 2007 - Paolo Maggi, Steve Frécinaux
* Copyright (C) 2008 - Jesse van den Kieboom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005-2007. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*/
#ifndef __XEDIT_GIO_DOCUMENT_SAVER_H__
#define __XEDIT_GIO_DOCUMENT_SAVER_H__
#include <xedit/xedit-document-saver.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_GIO_DOCUMENT_SAVER (xedit_gio_document_saver_get_type())
#define XEDIT_GIO_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_GIO_DOCUMENT_SAVER, XeditGioDocumentSaver))
#define XEDIT_GIO_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_GIO_DOCUMENT_SAVER, XeditGioDocumentSaverClass))
#define XEDIT_IS_GIO_DOCUMENT_SAVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_GIO_DOCUMENT_SAVER))
#define XEDIT_IS_GIO_DOCUMENT_SAVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_GIO_DOCUMENT_SAVER))
#define XEDIT_GIO_DOCUMENT_SAVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_GIO_DOCUMENT_SAVER, XeditGioDocumentSaverClass))
/* Private structure type */
typedef struct _XeditGioDocumentSaverPrivate XeditGioDocumentSaverPrivate;
/*
* Main object structure
*/
typedef struct _XeditGioDocumentSaver XeditGioDocumentSaver;
struct _XeditGioDocumentSaver
{
XeditDocumentSaver saver;
/*< private > */
XeditGioDocumentSaverPrivate *priv;
};
/*
* Class definition
*/
typedef XeditDocumentSaverClass XeditGioDocumentSaverClass;
/*
* Public methods
*/
GType xedit_gio_document_saver_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __XEDIT_GIO_DOCUMENT_SAVER_H__ */

99
xedit/xedit-help.c Normal file
View File

@@ -0,0 +1,99 @@
/*
* xedit-help.c
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "xedit-help.h"
#include <glib/gi18n.h>
#include <string.h>
#include <gtk/gtk.h>
gboolean
xedit_help_display (GtkWindow *parent,
const gchar *name, /* "xedit" if NULL */
const gchar *link_id)
{
GError *error = NULL;
gboolean ret;
gchar *link;
g_return_val_if_fail ((parent == NULL) || GTK_IS_WINDOW (parent), FALSE);
if (name == NULL)
name = "xedit";
else if (strcmp (name, "xedit.xml") == 0)
{
g_warning ("%s: Using \"xedit.xml\" for the help name is deprecated, use \"xedit\" or simply NULL instead", G_STRFUNC);
name = "xedit";
}
if (link_id)
link = g_strdup_printf ("help:%s/%s", name, link_id);
else
link = g_strdup_printf ("help:%s", name);
ret = gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (parent)),
link,
GDK_CURRENT_TIME,
&error);
g_free (link);
if (error != NULL)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (parent,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
_("There was an error displaying the help."));
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", error->message);
g_signal_connect (G_OBJECT (dialog),
"response",
G_CALLBACK (gtk_widget_destroy),
NULL);
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
gtk_widget_show (dialog);
g_error_free (error);
}
return ret;
}

44
xedit/xedit-help.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* xedit-help.h
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_HELP_H__
#define __XEDIT_HELP_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
gboolean xedit_help_display (GtkWindow *parent,
const gchar *name, /* "xedit" if NULL */
const gchar *link_id);
G_END_DECLS
#endif /* __XEDIT_HELP_H__ */

599
xedit/xedit-history-entry.c Normal file
View File

@@ -0,0 +1,599 @@
/*
* xedit-history-entry.c
* This file is part of xedit
*
* Copyright (C) 2006 - Paolo Borelli
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2006. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <gio/gio.h>
#include "xedit-history-entry.h"
#include "xedit-prefs-manager.h"
enum {
PROP_0,
PROP_HISTORY_ID,
PROP_HISTORY_LENGTH
};
#define MIN_ITEM_LEN 3
#define XEDIT_HISTORY_ENTRY_HISTORY_LENGTH_DEFAULT 10
#define XEDIT_HISTORY_ENTRY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
XEDIT_TYPE_HISTORY_ENTRY, \
XeditHistoryEntryPrivate))
struct _XeditHistoryEntryPrivate
{
gchar *history_id;
guint history_length;
GtkEntryCompletion *completion;
GSettings *settings;
};
G_DEFINE_TYPE(XeditHistoryEntry, xedit_history_entry, GTK_TYPE_COMBO_BOX_TEXT)
static void
xedit_history_entry_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *spec)
{
XeditHistoryEntry *entry;
g_return_if_fail (XEDIT_IS_HISTORY_ENTRY (object));
entry = XEDIT_HISTORY_ENTRY (object);
switch (prop_id) {
case PROP_HISTORY_ID:
entry->priv->history_id = g_value_dup_string (value);
break;
case PROP_HISTORY_LENGTH:
xedit_history_entry_set_history_length (entry,
g_value_get_uint (value));
break;
default:
break;
}
}
static void
xedit_history_entry_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *spec)
{
XeditHistoryEntryPrivate *priv;
g_return_if_fail (XEDIT_IS_HISTORY_ENTRY (object));
priv = XEDIT_HISTORY_ENTRY (object)->priv;
switch (prop_id) {
case PROP_HISTORY_ID:
g_value_set_string (value, priv->history_id);
break;
case PROP_HISTORY_LENGTH:
g_value_set_uint (value, priv->history_length);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec);
}
}
static void
xedit_history_entry_dispose (GObject *object)
{
xedit_history_entry_set_enable_completion (XEDIT_HISTORY_ENTRY (object),
FALSE);
G_OBJECT_CLASS (xedit_history_entry_parent_class)->dispose (object);
}
static void
xedit_history_entry_finalize (GObject *object)
{
XeditHistoryEntryPrivate *priv;
priv = XEDIT_HISTORY_ENTRY (object)->priv;
g_free (priv->history_id);
if (priv->settings != NULL)
{
g_object_unref (G_OBJECT (priv->settings));
priv->settings = NULL;
}
G_OBJECT_CLASS (xedit_history_entry_parent_class)->finalize (object);
}
static void
xedit_history_entry_class_init (XeditHistoryEntryClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = xedit_history_entry_set_property;
object_class->get_property = xedit_history_entry_get_property;
object_class->finalize = xedit_history_entry_finalize;
object_class->dispose = xedit_history_entry_dispose;
g_object_class_install_property (object_class,
PROP_HISTORY_ID,
g_param_spec_string ("history-id",
"History ID",
"History ID",
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
PROP_HISTORY_LENGTH,
g_param_spec_uint ("history-length",
"Max History Length",
"Max History Length",
0,
G_MAXUINT,
XEDIT_HISTORY_ENTRY_HISTORY_LENGTH_DEFAULT,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
/* TODO: Add enable-completion property */
g_type_class_add_private (object_class, sizeof(XeditHistoryEntryPrivate));
}
static GtkListStore *
get_history_store (XeditHistoryEntry *entry)
{
GtkTreeModel *store;
store = gtk_combo_box_get_model (GTK_COMBO_BOX (entry));
g_return_val_if_fail (GTK_IS_LIST_STORE (store), NULL);
return (GtkListStore *) store;
}
static GSList *
get_history_list (XeditHistoryEntry *entry)
{
GtkListStore *store;
GtkTreeIter iter;
gboolean valid;
GSList *list = NULL;
store = get_history_store (entry);
valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store),
&iter);
while (valid)
{
gchar *str;
gtk_tree_model_get (GTK_TREE_MODEL (store),
&iter,
0, &str,
-1);
list = g_slist_prepend (list, str);
valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store),
&iter);
}
return g_slist_reverse (list);
}
static void
xedit_history_entry_save_history (XeditHistoryEntry *entry)
{
GSList *settings_items;
g_return_if_fail (XEDIT_IS_HISTORY_ENTRY (entry));
settings_items = get_history_list (entry);
xedit_prefs_manager_set_gslist (entry->priv->settings,
entry->priv->history_id,
settings_items);
g_slist_foreach (settings_items, (GFunc) g_free, NULL);
g_slist_free (settings_items);
}
static gboolean
remove_item (GtkListStore *store,
const gchar *text)
{
GtkTreeIter iter;
g_return_val_if_fail (text != NULL, FALSE);
if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
return FALSE;
do
{
gchar *item_text;
gtk_tree_model_get (GTK_TREE_MODEL (store),
&iter,
0,
&item_text,
-1);
if (item_text != NULL &&
strcmp (item_text, text) == 0)
{
gtk_list_store_remove (store, &iter);
g_free (item_text);
return TRUE;
}
g_free (item_text);
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
return FALSE;
}
static void
clamp_list_store (GtkListStore *store,
guint max)
{
GtkTreePath *path;
GtkTreeIter iter;
/* -1 because TreePath counts from 0 */
path = gtk_tree_path_new_from_indices (max - 1, -1);
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path))
{
while (1)
{
if (!gtk_list_store_remove (store, &iter))
break;
}
}
gtk_tree_path_free (path);
}
static void
insert_history_item (XeditHistoryEntry *entry,
const gchar *text,
gboolean prepend)
{
GtkListStore *store;
GtkTreeIter iter;
if (g_utf8_strlen (text, -1) <= MIN_ITEM_LEN)
return;
store = get_history_store (entry);
/* remove the text from the store if it was already
* present. If it wasn't, clamp to max history - 1
* before inserting the new row, otherwise appending
* would not work */
if (!remove_item (store, text))
clamp_list_store (store,
entry->priv->history_length - 1);
if (prepend)
gtk_list_store_insert (store, &iter, 0);
else
gtk_list_store_append (store, &iter);
gtk_list_store_set (store,
&iter,
0,
text,
-1);
xedit_history_entry_save_history (entry);
}
void
xedit_history_entry_prepend_text (XeditHistoryEntry *entry,
const gchar *text)
{
g_return_if_fail (XEDIT_IS_HISTORY_ENTRY (entry));
g_return_if_fail (text != NULL);
insert_history_item (entry, text, TRUE);
}
void
xedit_history_entry_append_text (XeditHistoryEntry *entry,
const gchar *text)
{
g_return_if_fail (XEDIT_IS_HISTORY_ENTRY (entry));
g_return_if_fail (text != NULL);
insert_history_item (entry, text, FALSE);
}
static void
xedit_history_entry_load_history (XeditHistoryEntry *entry)
{
GSList *settings_items, *l;
GtkListStore *store;
GtkTreeIter iter;
guint i;
g_return_if_fail (XEDIT_IS_HISTORY_ENTRY (entry));
store = get_history_store (entry);
settings_items = xedit_prefs_manager_get_gslist (entry->priv->settings,
entry->priv->history_id);
gtk_list_store_clear (store);
for (l = settings_items, i = 0;
l != NULL && i < entry->priv->history_length;
l = l->next, i++)
{
gtk_list_store_append (store, &iter);
gtk_list_store_set (store,
&iter,
0,
l->data,
-1);
}
g_slist_foreach (settings_items, (GFunc) g_free, NULL);
g_slist_free (settings_items);
}
void
xedit_history_entry_clear (XeditHistoryEntry *entry)
{
GtkListStore *store;
g_return_if_fail (XEDIT_IS_HISTORY_ENTRY (entry));
store = get_history_store (entry);
gtk_list_store_clear (store);
xedit_history_entry_save_history (entry);
}
static void
xedit_history_entry_init (XeditHistoryEntry *entry)
{
XeditHistoryEntryPrivate *priv;
priv = XEDIT_HISTORY_ENTRY_GET_PRIVATE (entry);
entry->priv = priv;
priv->history_id = NULL;
priv->history_length = XEDIT_HISTORY_ENTRY_HISTORY_LENGTH_DEFAULT;
priv->completion = NULL;
priv->settings = g_settings_new (XEDIT_SCHEMA);
}
void
xedit_history_entry_set_history_length (XeditHistoryEntry *entry,
guint history_length)
{
g_return_if_fail (XEDIT_IS_HISTORY_ENTRY (entry));
g_return_if_fail (history_length > 0);
entry->priv->history_length = history_length;
/* TODO: update if we currently have more items than max */
}
guint
xedit_history_entry_get_history_length (XeditHistoryEntry *entry)
{
g_return_val_if_fail (XEDIT_IS_HISTORY_ENTRY (entry), 0);
return entry->priv->history_length;
}
gchar *
xedit_history_entry_get_history_id (XeditHistoryEntry *entry)
{
g_return_val_if_fail (XEDIT_IS_HISTORY_ENTRY (entry), NULL);
return g_strdup (entry->priv->history_id);
}
void
xedit_history_entry_set_enable_completion (XeditHistoryEntry *entry,
gboolean enable)
{
g_return_if_fail (XEDIT_IS_HISTORY_ENTRY (entry));
if (enable)
{
if (entry->priv->completion != NULL)
return;
entry->priv->completion = gtk_entry_completion_new ();
gtk_entry_completion_set_model (entry->priv->completion,
GTK_TREE_MODEL (get_history_store (entry)));
/* Use model column 0 as the text column */
gtk_entry_completion_set_text_column (entry->priv->completion, 0);
gtk_entry_completion_set_minimum_key_length (entry->priv->completion,
MIN_ITEM_LEN);
gtk_entry_completion_set_popup_completion (entry->priv->completion, FALSE);
gtk_entry_completion_set_inline_completion (entry->priv->completion, TRUE);
/* Assign the completion to the entry */
gtk_entry_set_completion (GTK_ENTRY (xedit_history_entry_get_entry(entry)),
entry->priv->completion);
}
else
{
if (entry->priv->completion == NULL)
return;
gtk_entry_set_completion (GTK_ENTRY (xedit_history_entry_get_entry (entry)),
NULL);
g_object_unref (entry->priv->completion);
entry->priv->completion = NULL;
}
}
gboolean
xedit_history_entry_get_enable_completion (XeditHistoryEntry *entry)
{
g_return_val_if_fail (XEDIT_IS_HISTORY_ENTRY (entry), FALSE);
return entry->priv->completion != NULL;
}
GtkWidget *
xedit_history_entry_new (const gchar *history_id,
gboolean enable_completion)
{
GtkWidget *ret;
GtkListStore *store;
g_return_val_if_fail (history_id != NULL, NULL);
/* Note that we are setting the model, so
* user must be careful to always manipulate
* data in the history through xedit_history_entry_
* functions.
*/
store = gtk_list_store_new (1, G_TYPE_STRING);
ret = g_object_new (XEDIT_TYPE_HISTORY_ENTRY,
"history-id", history_id,
"model", store,
"has-entry", TRUE,
"entry-text-column", 0,
NULL);
g_object_unref (store);
/* loading has to happen after the model
* has been set. However the model is not a
* G_PARAM_CONSTRUCT property of GtkComboBox
* so we cannot do this in the constructor.
* For now we simply do here since this widget is
* not bound to other programming languages.
* A maybe better alternative is to override the
* model property of combobox and mark CONTRUCT_ONLY.
* This would also ensure that the model cannot be
* set explicitely at a later time.
*/
xedit_history_entry_load_history (XEDIT_HISTORY_ENTRY (ret));
xedit_history_entry_set_enable_completion (XEDIT_HISTORY_ENTRY (ret),
enable_completion);
return ret;
}
/*
* Utility function to get the editable text entry internal widget.
* I would prefer to not expose this implementation detail and
* simply make the XeditHistoryEntry widget implement the
* GtkEditable interface. Unfortunately both GtkEditable and
* GtkComboBox have a "changed" signal and I am not sure how to
* handle the conflict.
*/
GtkWidget *
xedit_history_entry_get_entry (XeditHistoryEntry *entry)
{
g_return_val_if_fail (XEDIT_IS_HISTORY_ENTRY (entry), NULL);
return gtk_bin_get_child (GTK_BIN (entry));
}
static void
escape_cell_data_func (GtkTreeViewColumn *col,
GtkCellRenderer *renderer,
GtkTreeModel *model,
GtkTreeIter *iter,
XeditHistoryEntryEscapeFunc escape_func)
{
gchar *str;
gchar *escaped;
gtk_tree_model_get (model, iter, 0, &str, -1);
escaped = escape_func (str);
g_object_set (renderer, "text", escaped, NULL);
g_free (str);
g_free (escaped);
}
void
xedit_history_entry_set_escape_func (XeditHistoryEntry *entry,
XeditHistoryEntryEscapeFunc escape_func)
{
GList *cells;
g_return_if_fail (XEDIT_IS_HISTORY_ENTRY (entry));
cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (entry));
/* We only have one cell renderer */
g_return_if_fail (cells->data != NULL && cells->next == NULL);
if (escape_func != NULL)
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (entry),
GTK_CELL_RENDERER (cells->data),
(GtkCellLayoutDataFunc) escape_cell_data_func,
escape_func,
NULL);
else
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (entry),
GTK_CELL_RENDERER (cells->data),
NULL,
NULL,
NULL);
g_list_free (cells);
}

View File

@@ -0,0 +1,96 @@
/*
* xedit-history-entry.h
* This file is part of xedit
*
* Copyright (C) 2006 - Paolo Borelli
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2006. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_HISTORY_ENTRY_H__
#define __XEDIT_HISTORY_ENTRY_H__
G_BEGIN_DECLS
#define XEDIT_TYPE_HISTORY_ENTRY (xedit_history_entry_get_type ())
#define XEDIT_HISTORY_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_HISTORY_ENTRY, XeditHistoryEntry))
#define XEDIT_HISTORY_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XEDIT_TYPE_HISTORY_ENTRY, XeditHistoryEntryClass))
#define XEDIT_IS_HISTORY_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XEDIT_TYPE_HISTORY_ENTRY))
#define XEDIT_IS_HISTORY_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_HISTORY_ENTRY))
#define XEDIT_HISTORY_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XEDIT_TYPE_HISTORY_ENTRY, XeditHistoryEntryClass))
typedef struct _XeditHistoryEntry XeditHistoryEntry;
typedef struct _XeditHistoryEntryClass XeditHistoryEntryClass;
typedef struct _XeditHistoryEntryPrivate XeditHistoryEntryPrivate;
struct _XeditHistoryEntryClass
{
GtkComboBoxTextClass parent_class;
};
struct _XeditHistoryEntry
{
GtkComboBoxText parent_instance;
XeditHistoryEntryPrivate *priv;
};
GType xedit_history_entry_get_type (void) G_GNUC_CONST;
GtkWidget *xedit_history_entry_new (const gchar *history_id,
gboolean enable_completion);
void xedit_history_entry_prepend_text (XeditHistoryEntry *entry,
const gchar *text);
void xedit_history_entry_append_text (XeditHistoryEntry *entry,
const gchar *text);
void xedit_history_entry_clear (XeditHistoryEntry *entry);
void xedit_history_entry_set_history_length (XeditHistoryEntry *entry,
guint max_saved);
guint xedit_history_entry_get_history_length (XeditHistoryEntry *gentry);
gchar *xedit_history_entry_get_history_id (XeditHistoryEntry *entry);
void xedit_history_entry_set_enable_completion
(XeditHistoryEntry *entry,
gboolean enable);
gboolean xedit_history_entry_get_enable_completion
(XeditHistoryEntry *entry);
GtkWidget *xedit_history_entry_get_entry (XeditHistoryEntry *entry);
typedef gchar * (* XeditHistoryEntryEscapeFunc) (const gchar *str);
void xedit_history_entry_set_escape_func (XeditHistoryEntry *entry,
XeditHistoryEntryEscapeFunc escape_func);
G_END_DECLS
#endif /* __XEDIT_HISTORY_ENTRY_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,68 @@
/*
* xedit-io-error-message-area.h
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_IO_ERROR_MESSAGE_AREA_H__
#define __XEDIT_IO_ERROR_MESSAGE_AREA_H__
#include <glib.h>
G_BEGIN_DECLS
GtkWidget *xedit_io_loading_error_message_area_new (const gchar *uri,
const XeditEncoding *encoding,
const GError *error);
GtkWidget *xedit_unrecoverable_reverting_error_message_area_new (const gchar *uri,
const GError *error);
GtkWidget *xedit_conversion_error_while_saving_message_area_new (const gchar *uri,
const XeditEncoding *encoding,
const GError *error);
const XeditEncoding
*xedit_conversion_error_message_area_get_encoding (GtkWidget *message_area);
GtkWidget *xedit_file_already_open_warning_message_area_new (const gchar *uri);
GtkWidget *xedit_externally_modified_saving_error_message_area_new (const gchar *uri,
const GError *error);
GtkWidget *xedit_no_backup_saving_error_message_area_new (const gchar *uri,
const GError *error);
GtkWidget *xedit_unrecoverable_saving_error_message_area_new (const gchar *uri,
const GError *error);
GtkWidget *xedit_externally_modified_message_area_new (const gchar *uri,
gboolean document_modified);
G_END_DECLS
#endif /* __XEDIT_IO_ERROR_MESSAGE_AREA_H__ */

View File

@@ -0,0 +1,97 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xedit-languages-manager.c
* This file is part of xedit
*
* Copyright (C) 2003-2006 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2003-2006. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#include <string.h>
#include <gtk/gtk.h>
#if GTK_CHECK_VERSION (3, 0, 0)
#include <gtksourceview/gtksource.h>
#endif
#include "xedit-language-manager.h"
#include "xedit-prefs-manager.h"
#include "xedit-utils.h"
#include "xedit-debug.h"
static GtkSourceLanguageManager *language_manager = NULL;
GtkSourceLanguageManager *
xedit_get_language_manager (void)
{
if (language_manager == NULL)
{
language_manager = gtk_source_language_manager_new ();
}
return language_manager;
}
static gint
language_compare (gconstpointer a, gconstpointer b)
{
GtkSourceLanguage *lang_a = (GtkSourceLanguage *)a;
GtkSourceLanguage *lang_b = (GtkSourceLanguage *)b;
const gchar *name_a = gtk_source_language_get_name (lang_a);
const gchar *name_b = gtk_source_language_get_name (lang_b);
return g_utf8_collate (name_a, name_b);
}
GSList *
xedit_language_manager_list_languages_sorted (GtkSourceLanguageManager *lm,
gboolean include_hidden)
{
GSList *languages = NULL;
const gchar * const *ids;
ids = gtk_source_language_manager_get_language_ids (lm);
if (ids == NULL)
return NULL;
while (*ids != NULL)
{
GtkSourceLanguage *lang;
lang = gtk_source_language_manager_get_language (lm, *ids);
#if GTK_CHECK_VERSION (3, 0, 0)
g_return_val_if_fail (GTK_SOURCE_IS_LANGUAGE (lang), NULL);
#else
g_return_val_if_fail (GTK_IS_SOURCE_LANGUAGE (lang), NULL);
#endif
++ids;
if (include_hidden || !gtk_source_language_get_hidden (lang))
{
languages = g_slist_prepend (languages, lang);
}
}
return g_slist_sort (languages, (GCompareFunc)language_compare);
}

View File

@@ -0,0 +1,48 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xedit-languages-manager.h
* This file is part of xedit
*
* Copyright (C) 2003-2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2003-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_LANGUAGES_MANAGER_H__
#define __XEDIT_LANGUAGES_MANAGER_H__
#include <glib-object.h>
#include <gtksourceview/gtksourcelanguagemanager.h>
G_BEGIN_DECLS
GtkSourceLanguageManager *xedit_get_language_manager (void);
GSList *xedit_language_manager_list_languages_sorted
(GtkSourceLanguageManager *lm,
gboolean include_hidden);
G_END_DECLS
#endif /* __XEDIT_LANGUAGES_MANAGER_H__ */

13
xedit/xedit-marshal.list Normal file
View File

@@ -0,0 +1,13 @@
BOOLEAN:NONE
BOOLEAN:OBJECT
VOID:BOOLEAN
VOID:BOOLEAN,POINTER
VOID:BOXED,BOXED
VOID:OBJECT
VOID:POINTER
VOID:STRING,BOXED,FLAGS
VOID:STRING,BOXED,INT,BOOLEAN
VOID:UINT,POINTER
VOID:UINT64,UINT64
VOID:VOID
VOID:INT,INT

1158
xedit/xedit-message-bus.c Normal file

File diff suppressed because it is too large Load Diff

129
xedit/xedit-message-bus.h Normal file
View File

@@ -0,0 +1,129 @@
#ifndef __XEDIT_MESSAGE_BUS_H__
#define __XEDIT_MESSAGE_BUS_H__
#include <glib-object.h>
#include <xedit/xedit-message.h>
#include <xedit/xedit-message-type.h>
G_BEGIN_DECLS
#define XEDIT_TYPE_MESSAGE_BUS (xedit_message_bus_get_type ())
#define XEDIT_MESSAGE_BUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_MESSAGE_BUS, XeditMessageBus))
#define XEDIT_MESSAGE_BUS_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_MESSAGE_BUS, XeditMessageBus const))
#define XEDIT_MESSAGE_BUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XEDIT_TYPE_MESSAGE_BUS, XeditMessageBusClass))
#define XEDIT_IS_MESSAGE_BUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XEDIT_TYPE_MESSAGE_BUS))
#define XEDIT_IS_MESSAGE_BUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_MESSAGE_BUS))
#define XEDIT_MESSAGE_BUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XEDIT_TYPE_MESSAGE_BUS, XeditMessageBusClass))
typedef struct _XeditMessageBus XeditMessageBus;
typedef struct _XeditMessageBusClass XeditMessageBusClass;
typedef struct _XeditMessageBusPrivate XeditMessageBusPrivate;
struct _XeditMessageBus {
GObject parent;
XeditMessageBusPrivate *priv;
};
struct _XeditMessageBusClass {
GObjectClass parent_class;
void (*dispatch) (XeditMessageBus *bus,
XeditMessage *message);
void (*registered) (XeditMessageBus *bus,
XeditMessageType *message_type);
void (*unregistered) (XeditMessageBus *bus,
XeditMessageType *message_type);
};
typedef void (* XeditMessageCallback) (XeditMessageBus *bus,
XeditMessage *message,
gpointer userdata);
typedef void (* XeditMessageBusForeach) (XeditMessageType *message_type,
gpointer userdata);
GType xedit_message_bus_get_type (void) G_GNUC_CONST;
XeditMessageBus *xedit_message_bus_get_default (void);
XeditMessageBus *xedit_message_bus_new (void);
/* registering messages */
XeditMessageType *xedit_message_bus_lookup (XeditMessageBus *bus,
const gchar *object_path,
const gchar *method);
XeditMessageType *xedit_message_bus_register (XeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
guint num_optional,
...) G_GNUC_NULL_TERMINATED;
void xedit_message_bus_unregister (XeditMessageBus *bus,
XeditMessageType *message_type);
void xedit_message_bus_unregister_all (XeditMessageBus *bus,
const gchar *object_path);
gboolean xedit_message_bus_is_registered (XeditMessageBus *bus,
const gchar *object_path,
const gchar *method);
void xedit_message_bus_foreach (XeditMessageBus *bus,
XeditMessageBusForeach func,
gpointer userdata);
/* connecting to message events */
guint xedit_message_bus_connect (XeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
XeditMessageCallback callback,
gpointer userdata,
GDestroyNotify destroy_data);
void xedit_message_bus_disconnect (XeditMessageBus *bus,
guint id);
void xedit_message_bus_disconnect_by_func (XeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
XeditMessageCallback callback,
gpointer userdata);
/* blocking message event callbacks */
void xedit_message_bus_block (XeditMessageBus *bus,
guint id);
void xedit_message_bus_block_by_func (XeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
XeditMessageCallback callback,
gpointer userdata);
void xedit_message_bus_unblock (XeditMessageBus *bus,
guint id);
void xedit_message_bus_unblock_by_func (XeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
XeditMessageCallback callback,
gpointer userdata);
/* sending messages */
void xedit_message_bus_send_message (XeditMessageBus *bus,
XeditMessage *message);
void xedit_message_bus_send_message_sync (XeditMessageBus *bus,
XeditMessage *message);
void xedit_message_bus_send (XeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
...) G_GNUC_NULL_TERMINATED;
XeditMessage *xedit_message_bus_send_sync (XeditMessageBus *bus,
const gchar *object_path,
const gchar *method,
...) G_GNUC_NULL_TERMINATED;
G_END_DECLS
#endif /* __XEDIT_MESSAGE_BUS_H__ */
// ex:ts=8:noet:

527
xedit/xedit-message-type.c Normal file
View File

@@ -0,0 +1,527 @@
#include "xedit-message-type.h"
/**
* SECTION:xedit-message-type
* @short_description: message type description
* @include: xedit/xedit-message-type.h
*
* A message type is a prototype description for a #XeditMessage used to
* transmit messages on a #XeditMessageBus. The message type describes
* the Object Path, Method and Arguments of the message.
*
* A message type can contain any number of required and optional arguments.
* To instantiate a #XeditMessage from a #XeditMessageType, use
* xedit_message_type_instantiate().
*
* Registering a new message type on a #XeditMessageBus with
* xedit_message_bus_register() internally creates a new #XeditMessageType. When
* then using xedit_message_bus_send(), an actual instantiation of the
* registered type is internally created and send over the bus.
*
* <example>
* <programlisting>
* // Defining a new message type
* XeditMessageType *message_type = xedit_message_type_new ("/plugins/example",
* "method",
* 0,
* "arg1", G_TYPE_STRING,
* NULL);
*
* // Instantiating an actual message from the type
* XeditMessage *message = xedit_message_type_instantiate (message_type,
* "arg1", "Hello World",
* NULL);
* </programlisting>
* </example>
*
* Since: 2.25.3
*
*/
typedef struct
{
GType type;
gboolean required;
} ArgumentInfo;
struct _XeditMessageType
{
/* FIXME this is an issue for introspection */
gint ref_count;
gchar *object_path;
gchar *method;
guint num_arguments;
guint num_required;
GHashTable *arguments; // mapping of key -> ArgumentInfo
};
/**
* xedit_message_type_ref:
* @message_type: the #XeditMessageType
*
* Increases the reference count on @message_type.
*
* Return value: @message_type
*
*/
XeditMessageType *
xedit_message_type_ref (XeditMessageType *message_type)
{
g_return_val_if_fail (message_type != NULL, NULL);
g_atomic_int_inc (&message_type->ref_count);
return message_type;
}
/**
* xedit_message_type_unref:
* @message_type: the #XeditMessageType
*
* Decreases the reference count on @message_type. When the reference count
* drops to 0, @message_type is destroyed.
*
*/
void
xedit_message_type_unref (XeditMessageType *message_type)
{
g_return_if_fail (message_type != NULL);
if (!g_atomic_int_dec_and_test (&message_type->ref_count))
return;
g_free (message_type->object_path);
g_free (message_type->method);
g_hash_table_destroy (message_type->arguments);
g_free (message_type);
}
/**
* xedit_message_type_get_type:
*
* Retrieves the GType object which is associated with the
* #XeditMessageType class.
*
* Return value: the GType associated with #XeditMessageType.
**/
GType
xedit_message_type_get_type (void)
{
static GType our_type = 0;
if (!our_type)
our_type = g_boxed_type_register_static (
"XeditMessageType",
(GBoxedCopyFunc) xedit_message_type_ref,
(GBoxedFreeFunc) xedit_message_type_unref);
return our_type;
}
/**
* xedit_message_type_identifier:
* @object_path: (allow-none): the object path
* @method: (allow-none): the method
*
* Get the string identifier for @method at @object_path.
*
* Return value: the identifier for @method at @object_path
*
*/
gchar *
xedit_message_type_identifier (const gchar *object_path,
const gchar *method)
{
return g_strconcat (object_path, ".", method, NULL);
}
/**
* xedit_message_type_is_valid_object_path:
* @object_path: (allow-none): the object path
*
* Returns whether @object_path is a valid object path
*
* Return value: %TRUE if @object_path is a valid object path
*
*/
gboolean
xedit_message_type_is_valid_object_path (const gchar *object_path)
{
if (!object_path)
return FALSE;
/* needs to start with / */
if (*object_path != '/')
return FALSE;
while (*object_path)
{
if (*object_path == '/')
{
++object_path;
if (!*object_path || !(g_ascii_isalpha (*object_path) || *object_path == '_'))
return FALSE;
}
else if (!(g_ascii_isalnum (*object_path) || *object_path == '_'))
{
return FALSE;
}
++object_path;
}
return TRUE;
}
/**
* xedit_message_type_is_supported:
* @type: the #GType
*
* Returns if @type is #GType supported by the message system.
*
* Return value: %TRUE if @type is a supported #GType
*
*/
gboolean
xedit_message_type_is_supported (GType type)
{
gint i = 0;
static const GType type_list[] =
{
G_TYPE_BOOLEAN,
G_TYPE_CHAR,
G_TYPE_UCHAR,
G_TYPE_INT,
G_TYPE_UINT,
G_TYPE_LONG,
G_TYPE_ULONG,
G_TYPE_INT64,
G_TYPE_UINT64,
G_TYPE_ENUM,
G_TYPE_FLAGS,
G_TYPE_FLOAT,
G_TYPE_DOUBLE,
G_TYPE_STRING,
G_TYPE_POINTER,
G_TYPE_BOXED,
G_TYPE_OBJECT,
G_TYPE_INVALID
};
if (!G_TYPE_IS_VALUE_TYPE (type))
return FALSE;
while (type_list[i] != G_TYPE_INVALID)
{
if (g_type_is_a (type, type_list[i]))
return TRUE;
i++;
}
return FALSE;
}
/**
* xedit_message_type_new_valist:
* @object_path: (allow-none): the object path
* @method: (allow-none): the method
* @num_optional: number of optional arguments
* @var_args: key/gtype pair variable argument list
*
* Create a new #XeditMessageType for @method at @object_path. Argument names
* and values are supplied by the NULL terminated variable argument list.
* The last @num_optional provided arguments are considered optional.
*
* Return value: the newly constructed #XeditMessageType
*
*/
XeditMessageType *
xedit_message_type_new_valist (const gchar *object_path,
const gchar *method,
guint num_optional,
va_list var_args)
{
XeditMessageType *message_type;
g_return_val_if_fail (object_path != NULL, NULL);
g_return_val_if_fail (method != NULL, NULL);
g_return_val_if_fail (xedit_message_type_is_valid_object_path (object_path), NULL);
message_type = g_new0(XeditMessageType, 1);
message_type->ref_count = 1;
message_type->object_path = g_strdup(object_path);
message_type->method = g_strdup(method);
message_type->num_arguments = 0;
message_type->arguments = g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)g_free);
xedit_message_type_set_valist (message_type, num_optional, var_args);
return message_type;
}
/**
* xedit_message_type_new:
* @object_path: (allow-none): the object path
* @method: (allow-none): the method
* @num_optional: number of optional arguments
* @...: key/gtype pair variable argument list
*
* Create a new #XeditMessageType for @method at @object_path. Argument names
* and values are supplied by the NULL terminated variable argument list.
* The last @num_optional provided arguments are considered optional.
*
* Return value: the newly constructed #XeditMessageType
*
*/
XeditMessageType *
xedit_message_type_new (const gchar *object_path,
const gchar *method,
guint num_optional,
...)
{
XeditMessageType *message_type;
va_list var_args;
va_start(var_args, num_optional);
message_type = xedit_message_type_new_valist (object_path, method, num_optional, var_args);
va_end(var_args);
return message_type;
}
/**
* xedit_message_type_set:
* @message_type: the #XeditMessageType
* @num_optional: number of optional arguments
* @...: key/gtype pair variable argument list
*
* Sets argument names/types supplied by the NULL terminated variable
* argument list. The last @num_optional provided arguments are considered
* optional.
*
*/
void
xedit_message_type_set (XeditMessageType *message_type,
guint num_optional,
...)
{
va_list va_args;
va_start (va_args, num_optional);
xedit_message_type_set_valist (message_type, num_optional, va_args);
va_end (va_args);
}
/**
* xedit_message_type_set_valist:
* @message_type: the #XeditMessageType
* @num_optional: number of optional arguments
* @var_args: key/gtype pair variable argument list
*
* Sets argument names/types supplied by the NULL terminated variable
* argument list @var_args. The last @num_optional provided arguments are
* considered optional.
*
*/
void
xedit_message_type_set_valist (XeditMessageType *message_type,
guint num_optional,
va_list var_args)
{
const gchar *key;
ArgumentInfo **optional = g_new0(ArgumentInfo *, num_optional);
guint i;
guint added = 0;
// parse key -> gtype pair arguments
while ((key = va_arg (var_args, const gchar *)) != NULL)
{
// get corresponding GType
GType gtype = va_arg (var_args, GType);
ArgumentInfo *info;
if (!xedit_message_type_is_supported (gtype))
{
g_error ("Message type '%s' is not supported", g_type_name (gtype));
xedit_message_type_unref (message_type);
g_free (optional);
return;
}
info = g_new(ArgumentInfo, 1);
info->type = gtype;
info->required = TRUE;
g_hash_table_insert (message_type->arguments, g_strdup (key), info);
++message_type->num_arguments;
++added;
if (num_optional > 0)
{
for (i = num_optional - 1; i > 0; --i)
optional[i] = optional[i - 1];
*optional = info;
}
}
message_type->num_required += added;
// set required for last num_optional arguments
for (i = 0; i < num_optional; ++i)
{
if (optional[i])
{
optional[i]->required = FALSE;
--message_type->num_required;
}
}
g_free (optional);
}
/**
* xedit_message_type_instantiate_valist:
* @message_type: the #XeditMessageType
* @va_args: NULL terminated variable list of key/value pairs
*
* Instantiate a new message from the message type with specific values
* for the message arguments.
*
* Return value: the newly created message
*
*/
XeditMessage *
xedit_message_type_instantiate_valist (XeditMessageType *message_type,
va_list va_args)
{
XeditMessage *message;
g_return_val_if_fail (message_type != NULL, NULL);
message = XEDIT_MESSAGE (g_object_new (XEDIT_TYPE_MESSAGE, "type", message_type, NULL));
xedit_message_set_valist (message, va_args);
return message;
}
/**
* xedit_message_type_instantiate:
* @message_type: the #XeditMessageType
* @...: NULL terminated variable list of key/value pairs
*
* Instantiate a new message from the message type with specific values
* for the message arguments.
*
* Return value: the newly created message
*
*/
XeditMessage *
xedit_message_type_instantiate (XeditMessageType *message_type,
...)
{
XeditMessage *message;
va_list va_args;
va_start (va_args, message_type);
message = xedit_message_type_instantiate_valist (message_type, va_args);
va_end (va_args);
return message;
}
/**
* xedit_message_type_get_object_path:
* @message_type: the #XeditMessageType
*
* Get the message type object path.
*
* Return value: the message type object path
*
*/
const gchar *
xedit_message_type_get_object_path (XeditMessageType *message_type)
{
return message_type->object_path;
}
/**
* xedit_message_type_get_method:
* @message_type: the #XeditMessageType
*
* Get the message type method.
*
* Return value: the message type method
*
*/
const gchar *
xedit_message_type_get_method (XeditMessageType *message_type)
{
return message_type->method;
}
/**
* xedit_message_type_lookup:
* @message_type: the #XeditMessageType
* @key: the argument key
*
* Get the argument key #GType.
*
* Return value: the #GType of @key
*
*/
GType
xedit_message_type_lookup (XeditMessageType *message_type,
const gchar *key)
{
ArgumentInfo *info = g_hash_table_lookup (message_type->arguments, key);
if (!info)
return G_TYPE_INVALID;
return info->type;
}
typedef struct
{
XeditMessageTypeForeach func;
gpointer user_data;
} ForeachInfo;
static void
foreach_gtype (const gchar *key,
ArgumentInfo *info,
ForeachInfo *finfo)
{
finfo->func (key, info->type, info->required, finfo->user_data);
}
/**
* xedit_message_type_foreach:
* @message_type: the #XeditMessageType
* @func: the callback function
* @user_data: user data supplied to the callback function
*
* Calls @func for each argument in the message type.
*
*/
void
xedit_message_type_foreach (XeditMessageType *message_type,
XeditMessageTypeForeach func,
gpointer user_data)
{
ForeachInfo info = {func, user_data};
g_hash_table_foreach (message_type->arguments, (GHFunc)foreach_gtype, &info);
}
// ex:ts=8:noet:

View File

@@ -0,0 +1,67 @@
#ifndef __XEDIT_MESSAGE_TYPE_H__
#define __XEDIT_MESSAGE_TYPE_H__
#include <glib-object.h>
#include <stdarg.h>
#include "xedit-message.h"
G_BEGIN_DECLS
#define XEDIT_TYPE_MESSAGE_TYPE (xedit_message_type_get_type ())
#define XEDIT_MESSAGE_TYPE(x) ((XeditMessageType *)(x))
typedef void (*XeditMessageTypeForeach) (const gchar *key,
GType type,
gboolean required,
gpointer user_data);
typedef struct _XeditMessageType XeditMessageType;
GType xedit_message_type_get_type (void) G_GNUC_CONST;
gboolean xedit_message_type_is_supported (GType type);
gchar *xedit_message_type_identifier (const gchar *object_path,
const gchar *method);
gboolean xedit_message_type_is_valid_object_path (const gchar *object_path);
XeditMessageType *xedit_message_type_new (const gchar *object_path,
const gchar *method,
guint num_optional,
...) G_GNUC_NULL_TERMINATED;
XeditMessageType *xedit_message_type_new_valist (const gchar *object_path,
const gchar *method,
guint num_optional,
va_list va_args);
void xedit_message_type_set (XeditMessageType *message_type,
guint num_optional,
...) G_GNUC_NULL_TERMINATED;
void xedit_message_type_set_valist (XeditMessageType *message_type,
guint num_optional,
va_list va_args);
XeditMessageType *xedit_message_type_ref (XeditMessageType *message_type);
void xedit_message_type_unref (XeditMessageType *message_type);
XeditMessage *xedit_message_type_instantiate_valist (XeditMessageType *message_type,
va_list va_args);
XeditMessage *xedit_message_type_instantiate (XeditMessageType *message_type,
...) G_GNUC_NULL_TERMINATED;
const gchar *xedit_message_type_get_object_path (XeditMessageType *message_type);
const gchar *xedit_message_type_get_method (XeditMessageType *message_type);
GType xedit_message_type_lookup (XeditMessageType *message_type,
const gchar *key);
void xedit_message_type_foreach (XeditMessageType *message_type,
XeditMessageTypeForeach func,
gpointer user_data);
G_END_DECLS
#endif /* __XEDIT_MESSAGE_TYPE_H__ */
// ex:ts=8:noet:

594
xedit/xedit-message.c Normal file
View File

@@ -0,0 +1,594 @@
#include "xedit-message.h"
#include "xedit-message-type.h"
#include <string.h>
#include <gobject/gvaluecollector.h>
/**
* SECTION:xedit-message
* @short_description: message bus message object
* @include: xedit/xedit-message.h
*
* Communication on a #XeditMessageBus is done through messages. Messages are
* sent over the bus and received by connecting callbacks on the message bus.
* A #XeditMessage is an instantiation of a #XeditMessageType, containing
* values for the arguments as specified in the message type.
*
* A message can be seen as a method call, or signal emission depending on
* who is the sender and who is the receiver. There is no explicit distinction
* between methods and signals.
*
* Since: 2.25.3
*
*/
#define XEDIT_MESSAGE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), XEDIT_TYPE_MESSAGE, XeditMessagePrivate))
enum {
PROP_0,
PROP_OBJECT_PATH,
PROP_METHOD,
PROP_TYPE
};
struct _XeditMessagePrivate
{
XeditMessageType *type;
gboolean valid;
GHashTable *values;
};
G_DEFINE_TYPE (XeditMessage, xedit_message, G_TYPE_OBJECT)
static void
xedit_message_finalize (GObject *object)
{
XeditMessage *message = XEDIT_MESSAGE (object);
xedit_message_type_unref (message->priv->type);
g_hash_table_destroy (message->priv->values);
G_OBJECT_CLASS (xedit_message_parent_class)->finalize (object);
}
static void
xedit_message_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XeditMessage *msg = XEDIT_MESSAGE (object);
switch (prop_id)
{
case PROP_OBJECT_PATH:
g_value_set_string (value, xedit_message_type_get_object_path (msg->priv->type));
break;
case PROP_METHOD:
g_value_set_string (value, xedit_message_type_get_method (msg->priv->type));
break;
case PROP_TYPE:
g_value_set_boxed (value, msg->priv->type);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_message_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XeditMessage *msg = XEDIT_MESSAGE (object);
switch (prop_id)
{
case PROP_TYPE:
msg->priv->type = XEDIT_MESSAGE_TYPE (g_value_dup_boxed (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GValue *
add_value (XeditMessage *message,
const gchar *key)
{
GValue *value;
GType type = xedit_message_type_lookup (message->priv->type, key);
if (type == G_TYPE_INVALID)
return NULL;
value = g_new0 (GValue, 1);
g_value_init (value, type);
g_value_reset (value);
g_hash_table_insert (message->priv->values, g_strdup (key), value);
return value;
}
static void
xedit_message_class_init (XeditMessageClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->finalize = xedit_message_finalize;
object_class->get_property = xedit_message_get_property;
object_class->set_property = xedit_message_set_property;
/**
* XeditMessage:object_path:
*
* The messages object path (e.g. /xedit/object/path).
*
*/
g_object_class_install_property (object_class, PROP_OBJECT_PATH,
g_param_spec_string ("object-path",
"OBJECT_PATH",
"The message object path",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* XeditMessage:method:
*
* The messages method.
*
*/
g_object_class_install_property (object_class, PROP_METHOD,
g_param_spec_string ("method",
"METHOD",
"The message method",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* XeditMEssage:type:
*
* The message type.
*
*/
g_object_class_install_property (object_class, PROP_TYPE,
g_param_spec_boxed ("type",
"TYPE",
"The message type",
XEDIT_TYPE_MESSAGE_TYPE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
g_type_class_add_private (object_class, sizeof(XeditMessagePrivate));
}
static void
destroy_value (GValue *value)
{
g_value_unset (value);
g_free (value);
}
static void
xedit_message_init (XeditMessage *self)
{
self->priv = XEDIT_MESSAGE_GET_PRIVATE (self);
self->priv->values = g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)destroy_value);
}
static gboolean
set_value_real (GValue *to,
const GValue *from)
{
GType from_type;
GType to_type;
from_type = G_VALUE_TYPE (from);
to_type = G_VALUE_TYPE (to);
if (!g_type_is_a (from_type, to_type))
{
if (!g_value_transform (from, to))
{
g_warning ("%s: Unable to make conversion from %s to %s",
G_STRLOC,
g_type_name (from_type),
g_type_name (to_type));
return FALSE;
}
return TRUE;
}
g_value_copy (from, to);
return TRUE;
}
inline static GValue *
value_lookup (XeditMessage *message,
const gchar *key,
gboolean create)
{
GValue *ret = (GValue *)g_hash_table_lookup (message->priv->values, key);
if (!ret && create)
ret = add_value (message, key);
return ret;
}
/**
* xedit_message_get_method:
* @message: the #XeditMessage
*
* Get the message method.
*
* Return value: the message method
*
*/
const gchar *
xedit_message_get_method (XeditMessage *message)
{
g_return_val_if_fail (XEDIT_IS_MESSAGE (message), NULL);
return xedit_message_type_get_method (message->priv->type);
}
/**
* xedit_message_get_object_path:
* @message: the #XeditMessage
*
* Get the message object path.
*
* Return value: the message object path
*
*/
const gchar *
xedit_message_get_object_path (XeditMessage *message)
{
g_return_val_if_fail (XEDIT_IS_MESSAGE (message), NULL);
return xedit_message_type_get_object_path (message->priv->type);
}
/**
* xedit_message_set:
* @message: the #XeditMessage
* @...: a %NULL terminated variable list of key/value pairs
*
* Set values of message arguments. The supplied @var_args should contain
* pairs of keys and argument values.
*
*/
void
xedit_message_set (XeditMessage *message,
...)
{
va_list ap;
g_return_if_fail (XEDIT_IS_MESSAGE (message));
va_start (ap, message);
xedit_message_set_valist (message, ap);
va_end (ap);
}
/**
* xedit_message_set_valist:
* @message: the #XeditMessage
* @var_args: a %NULL terminated variable list of key/value pairs
*
* Set values of message arguments. The supplied @var_args should contain
* pairs of keys and argument values.
*
*/
void
xedit_message_set_valist (XeditMessage *message,
va_list var_args)
{
const gchar *key;
g_return_if_fail (XEDIT_IS_MESSAGE (message));
while ((key = va_arg (var_args, const gchar *)) != NULL)
{
/* lookup the key */
GValue *container = value_lookup (message, key, TRUE);
GValue value = {0,};
gchar *error = NULL;
if (!container)
{
g_warning ("%s: Cannot set value for %s, does not exist",
G_STRLOC,
key);
/* skip value */
va_arg (var_args, gpointer);
continue;
}
g_value_init (&value, G_VALUE_TYPE (container));
G_VALUE_COLLECT (&value, var_args, 0, &error);
if (error)
{
g_warning ("%s: %s", G_STRLOC, error);
continue;
}
set_value_real (container, &value);
g_value_unset (&value);
}
}
/**
* xedit_message_set_value:
* @message: the #XeditMessage
* @key: the argument key
* @value: (out): the argument value
*
* Set value of message argument @key to @value.
*
*/
void
xedit_message_set_value (XeditMessage *message,
const gchar *key,
GValue *value)
{
GValue *container;
g_return_if_fail (XEDIT_IS_MESSAGE (message));
container = value_lookup (message, key, TRUE);
if (!container)
{
g_warning ("%s: Cannot set value for %s, does not exist",
G_STRLOC,
key);
return;
}
set_value_real (container, value);
}
/**
* xedit_message_set_valuesv:
* @message: the #XeditMessage
* @keys: (array-length=n_values): keys to set values for
* @values: (array-length=n_values): values to set
* @n_values: number of arguments to set values for
*
* Set message argument values.
*
*/
void
xedit_message_set_valuesv (XeditMessage *message,
const gchar **keys,
GValue *values,
gint n_values)
{
gint i;
g_return_if_fail (XEDIT_IS_MESSAGE (message));
for (i = 0; i < n_values; i++)
{
xedit_message_set_value (message, keys[i], &values[i]);
}
}
/* FIXME this is an issue for introspection */
/**
* xedit_message_get:
* @message: the #XeditMessage
* @...: a %NULL variable argument list of key/value container pairs
*
* Get values of message arguments. The supplied @var_args should contain
* pairs of keys and pointers to variables which are set to the argument
* value for the specified key.
*
*/
void
xedit_message_get (XeditMessage *message,
...)
{
va_list ap;
g_return_if_fail (XEDIT_IS_MESSAGE (message));
va_start (ap, message);
xedit_message_get_valist (message, ap);
va_end (ap);
}
/**
* xedit_message_get_valist:
* @message: the #XeditMessage
* @var_args: a %NULL variable argument list of key/value container pairs
*
* Get values of message arguments. The supplied @var_args should contain
* pairs of keys and pointers to variables which are set to the argument
* value for the specified key.
*
*/
void
xedit_message_get_valist (XeditMessage *message,
va_list var_args)
{
const gchar *key;
g_return_if_fail (XEDIT_IS_MESSAGE (message));
while ((key = va_arg (var_args, const gchar *)) != NULL)
{
GValue *container;
GValue copy = {0,};
gchar *error = NULL;
container = value_lookup (message, key, FALSE);
if (!container)
{
/* skip value */
va_arg (var_args, gpointer);
continue;
}
/* copy the value here, to be sure it isn't tainted */
g_value_init (&copy, G_VALUE_TYPE (container));
g_value_copy (container, &copy);
G_VALUE_LCOPY (&copy, var_args, 0, &error);
if (error)
{
g_warning ("%s: %s", G_STRLOC, error);
g_free (error);
/* purposely leak the value here, because it might
be in a bad state */
continue;
}
g_value_unset (&copy);
}
}
/**
* xedit_message_get_value:
* @message: the #XeditMessage
* @key: the argument key
* @value: (out): value return container
*
* Get the value of a specific message argument. @value will be initialized
* with the correct type.
*
*/
void
xedit_message_get_value (XeditMessage *message,
const gchar *key,
GValue *value)
{
GValue *container;
g_return_if_fail (XEDIT_IS_MESSAGE (message));
container = value_lookup (message, key, FALSE);
if (!container)
{
g_warning ("%s: Invalid key `%s'",
G_STRLOC,
key);
return;
}
g_value_init (value, G_VALUE_TYPE (container));
set_value_real (value, container);
}
/**
* xedit_message_get_key_type:
* @message: the #XeditMessage
* @key: the argument key
*
* Get the type of a message argument.
*
* Return value: the type of @key
*
*/
GType
xedit_message_get_key_type (XeditMessage *message,
const gchar *key)
{
g_return_val_if_fail (XEDIT_IS_MESSAGE (message), G_TYPE_INVALID);
g_return_val_if_fail (message->priv->type != NULL, G_TYPE_INVALID);
return xedit_message_type_lookup (message->priv->type, key);
}
/**
* xedit_message_has_key:
* @message: the #XeditMessage
* @key: the argument key
*
* Check whether the message has a specific key.
*
* Return value: %TRUE if @message has argument @key
*
*/
gboolean
xedit_message_has_key (XeditMessage *message,
const gchar *key)
{
g_return_val_if_fail (XEDIT_IS_MESSAGE (message), FALSE);
return value_lookup (message, key, FALSE) != NULL;
}
typedef struct
{
XeditMessage *message;
gboolean valid;
} ValidateInfo;
static void
validate_key (const gchar *key,
GType type,
gboolean required,
ValidateInfo *info)
{
GValue *value;
if (!info->valid || !required)
return;
value = value_lookup (info->message, key, FALSE);
if (!value)
info->valid = FALSE;
}
/**
* xedit_message_validate:
* @message: the #XeditMessage
*
* Validates the message arguments according to the message type.
*
* Return value: %TRUE if the message is valid
*
*/
gboolean
xedit_message_validate (XeditMessage *message)
{
ValidateInfo info = {message, TRUE};
g_return_val_if_fail (XEDIT_IS_MESSAGE (message), FALSE);
g_return_val_if_fail (message->priv->type != NULL, FALSE);
if (!message->priv->valid)
{
xedit_message_type_foreach (message->priv->type,
(XeditMessageTypeForeach)validate_key,
&info);
message->priv->valid = info.valid;
}
return message->priv->valid;
}
// ex:ts=8:noet:

71
xedit/xedit-message.h Normal file
View File

@@ -0,0 +1,71 @@
#ifndef __XEDIT_MESSAGE_H__
#define __XEDIT_MESSAGE_H__
#include <glib-object.h>
#include <stdarg.h>
G_BEGIN_DECLS
#define XEDIT_TYPE_MESSAGE (xedit_message_get_type ())
#define XEDIT_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_MESSAGE, XeditMessage))
#define XEDIT_MESSAGE_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_MESSAGE, XeditMessage const))
#define XEDIT_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XEDIT_TYPE_MESSAGE, XeditMessageClass))
#define XEDIT_IS_MESSAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XEDIT_TYPE_MESSAGE))
#define XEDIT_IS_MESSAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_MESSAGE))
#define XEDIT_MESSAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XEDIT_TYPE_MESSAGE, XeditMessageClass))
typedef struct _XeditMessage XeditMessage;
typedef struct _XeditMessageClass XeditMessageClass;
typedef struct _XeditMessagePrivate XeditMessagePrivate;
struct _XeditMessage {
GObject parent;
XeditMessagePrivate *priv;
};
struct _XeditMessageClass {
GObjectClass parent_class;
};
GType xedit_message_get_type (void) G_GNUC_CONST;
struct _XeditMessageType xedit_message_get_message_type (XeditMessage *message);
void xedit_message_get (XeditMessage *message,
...) G_GNUC_NULL_TERMINATED;
void xedit_message_get_valist (XeditMessage *message,
va_list var_args);
void xedit_message_get_value (XeditMessage *message,
const gchar *key,
GValue *value);
void xedit_message_set (XeditMessage *message,
...) G_GNUC_NULL_TERMINATED;
void xedit_message_set_valist (XeditMessage *message,
va_list var_args);
void xedit_message_set_value (XeditMessage *message,
const gchar *key,
GValue *value);
void xedit_message_set_valuesv (XeditMessage *message,
const gchar **keys,
GValue *values,
gint n_values);
const gchar *xedit_message_get_object_path (XeditMessage *message);
const gchar *xedit_message_get_method (XeditMessage *message);
gboolean xedit_message_has_key (XeditMessage *message,
const gchar *key);
GType xedit_message_get_key_type (XeditMessage *message,
const gchar *key);
gboolean xedit_message_validate (XeditMessage *message);
G_END_DECLS
#endif /* __XEDIT_MESSAGE_H__ */
// ex:ts=8:noet:

View File

@@ -0,0 +1,563 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xedit-metadata-manager.c
* This file is part of xedit
*
* Copyright (C) 2003-2007 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2003-2007. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <time.h>
#include <stdlib.h>
#include <libxml/xmlreader.h>
#include "xedit-metadata-manager.h"
#include "xedit-debug.h"
#include "xedit-dirs.h"
/*
#define XEDIT_METADATA_VERBOSE_DEBUG 1
*/
#define METADATA_FILE "xedit-metadata.xml"
#define MAX_ITEMS 50
typedef struct _XeditMetadataManager XeditMetadataManager;
typedef struct _Item Item;
struct _Item
{
time_t atime; /* time of last access */
GHashTable *values;
};
struct _XeditMetadataManager
{
gboolean values_loaded; /* It is true if the file
has been read */
guint timeout_id;
GHashTable *items;
};
static gboolean xedit_metadata_manager_save (gpointer data);
static XeditMetadataManager *xedit_metadata_manager = NULL;
static void
item_free (gpointer data)
{
Item *item;
g_return_if_fail (data != NULL);
#ifdef XEDIT_METADATA_VERBOSE_DEBUG
xedit_debug (DEBUG_METADATA);
#endif
item = (Item *)data;
if (item->values != NULL)
g_hash_table_destroy (item->values);
g_free (item);
}
static void
xedit_metadata_manager_arm_timeout (void)
{
if (xedit_metadata_manager->timeout_id == 0)
{
xedit_metadata_manager->timeout_id =
g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE,
2,
(GSourceFunc)xedit_metadata_manager_save,
NULL,
NULL);
}
}
static gboolean
xedit_metadata_manager_init (void)
{
xedit_debug (DEBUG_METADATA);
if (xedit_metadata_manager != NULL)
return TRUE;
xedit_metadata_manager = g_new0 (XeditMetadataManager, 1);
xedit_metadata_manager->values_loaded = FALSE;
xedit_metadata_manager->items =
g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
item_free);
return TRUE;
}
/* This function must be called before exiting xedit */
void
xedit_metadata_manager_shutdown (void)
{
xedit_debug (DEBUG_METADATA);
if (xedit_metadata_manager == NULL)
return;
if (xedit_metadata_manager->timeout_id)
{
g_source_remove (xedit_metadata_manager->timeout_id);
xedit_metadata_manager->timeout_id = 0;
xedit_metadata_manager_save (NULL);
}
if (xedit_metadata_manager->items != NULL)
g_hash_table_destroy (xedit_metadata_manager->items);
g_free (xedit_metadata_manager);
xedit_metadata_manager = NULL;
}
static void
parseItem (xmlDocPtr doc, xmlNodePtr cur)
{
Item *item;
xmlChar *uri;
xmlChar *atime;
#ifdef XEDIT_METADATA_VERBOSE_DEBUG
xedit_debug (DEBUG_METADATA);
#endif
if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0)
return;
uri = xmlGetProp (cur, (const xmlChar *)"uri");
if (uri == NULL)
return;
atime = xmlGetProp (cur, (const xmlChar *)"atime");
if (atime == NULL)
{
xmlFree (uri);
return;
}
item = g_new0 (Item, 1);
item->atime = g_ascii_strtoull ((char *)atime, NULL, 0);
item->values = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
g_free);
cur = cur->xmlChildrenNode;
while (cur != NULL)
{
if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0)
{
xmlChar *key;
xmlChar *value;
key = xmlGetProp (cur, (const xmlChar *)"key");
value = xmlGetProp (cur, (const xmlChar *)"value");
if ((key != NULL) && (value != NULL))
g_hash_table_insert (item->values,
g_strdup ((gchar *)key),
g_strdup ((gchar *)value));
if (key != NULL)
xmlFree (key);
if (value != NULL)
xmlFree (value);
}
cur = cur->next;
}
g_hash_table_insert (xedit_metadata_manager->items,
g_strdup ((gchar *)uri),
item);
xmlFree (uri);
xmlFree (atime);
}
static gchar *
get_metadata_filename (void)
{
gchar *cache_dir;
gchar *metadata;
cache_dir = xedit_dirs_get_user_cache_dir ();
metadata = g_build_filename (cache_dir,
METADATA_FILE,
NULL);
g_free (cache_dir);
return metadata;
}
static gboolean
load_values (void)
{
xmlDocPtr doc;
xmlNodePtr cur;
gchar *file_name;
xedit_debug (DEBUG_METADATA);
g_return_val_if_fail (xedit_metadata_manager != NULL, FALSE);
g_return_val_if_fail (xedit_metadata_manager->values_loaded == FALSE, FALSE);
xedit_metadata_manager->values_loaded = TRUE;
xmlKeepBlanksDefault (0);
/* FIXME: file locking - Paolo */
file_name = get_metadata_filename ();
if ((file_name == NULL) ||
(!g_file_test (file_name, G_FILE_TEST_EXISTS)))
{
g_free (file_name);
return FALSE;
}
doc = xmlParseFile (file_name);
g_free (file_name);
if (doc == NULL)
{
return FALSE;
}
cur = xmlDocGetRootElement (doc);
if (cur == NULL)
{
g_message ("The metadata file '%s' is empty", METADATA_FILE);
xmlFreeDoc (doc);
return FALSE;
}
if (xmlStrcmp (cur->name, (const xmlChar *) "metadata"))
{
g_message ("File '%s' is of the wrong type", METADATA_FILE);
xmlFreeDoc (doc);
return FALSE;
}
cur = xmlDocGetRootElement (doc);
cur = cur->xmlChildrenNode;
while (cur != NULL)
{
parseItem (doc, cur);
cur = cur->next;
}
xmlFreeDoc (doc);
return TRUE;
}
gchar *
xedit_metadata_manager_get (const gchar *uri,
const gchar *key)
{
Item *item;
gchar *value;
g_return_val_if_fail (uri != NULL, NULL);
g_return_val_if_fail (key != NULL, NULL);
xedit_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key );
xedit_metadata_manager_init ();
if (!xedit_metadata_manager->values_loaded)
{
gboolean res;
res = load_values ();
if (!res)
return NULL;
}
item = (Item *)g_hash_table_lookup (xedit_metadata_manager->items,
uri);
if (item == NULL)
return NULL;
item->atime = time (NULL);
if (item->values == NULL)
return NULL;
value = g_hash_table_lookup (item->values, key);
if (value == NULL)
return NULL;
else
return g_strdup (value);
}
void
xedit_metadata_manager_set (const gchar *uri,
const gchar *key,
const gchar *value)
{
Item *item;
g_return_if_fail (uri != NULL);
g_return_if_fail (key != NULL);
xedit_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value);
xedit_metadata_manager_init ();
if (!xedit_metadata_manager->values_loaded)
{
gboolean res;
res = load_values ();
if (!res)
return;
}
item = (Item *)g_hash_table_lookup (xedit_metadata_manager->items,
uri);
if (item == NULL)
{
item = g_new0 (Item, 1);
g_hash_table_insert (xedit_metadata_manager->items,
g_strdup (uri),
item);
}
if (item->values == NULL)
item->values = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
g_free);
if (value != NULL)
g_hash_table_insert (item->values,
g_strdup (key),
g_strdup (value));
else
g_hash_table_remove (item->values,
key);
item->atime = time (NULL);
xedit_metadata_manager_arm_timeout ();
}
static void
save_values (const gchar *key, const gchar *value, xmlNodePtr parent)
{
xmlNodePtr xml_node;
#ifdef XEDIT_METADATA_VERBOSE_DEBUG
xedit_debug (DEBUG_METADATA);
#endif
g_return_if_fail (key != NULL);
if (value == NULL)
return;
xml_node = xmlNewChild (parent,
NULL,
(const xmlChar *)"entry",
NULL);
xmlSetProp (xml_node,
(const xmlChar *)"key",
(const xmlChar *)key);
xmlSetProp (xml_node,
(const xmlChar *)"value",
(const xmlChar *)value);
#ifdef XEDIT_METADATA_VERBOSE_DEBUG
xedit_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value);
#endif
}
static void
save_item (const gchar *key, const gpointer *data, xmlNodePtr parent)
{
xmlNodePtr xml_node;
const Item *item = (const Item *)data;
gchar *atime;
#ifdef XEDIT_METADATA_VERBOSE_DEBUG
xedit_debug (DEBUG_METADATA);
#endif
g_return_if_fail (key != NULL);
if (item == NULL)
return;
xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL);
xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key);
#ifdef XEDIT_METADATA_VERBOSE_DEBUG
xedit_debug_message (DEBUG_METADATA, "uri: %s", key);
#endif
atime = g_strdup_printf ("%ld", item->atime);
xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime);
#ifdef XEDIT_METADATA_VERBOSE_DEBUG
xedit_debug_message (DEBUG_METADATA, "atime: %s", atime);
#endif
g_free (atime);
g_hash_table_foreach (item->values,
(GHFunc)save_values,
xml_node);
}
static void
get_oldest (const gchar *key, const gpointer value, const gchar ** key_to_remove)
{
const Item *item = (const Item *)value;
if (*key_to_remove == NULL)
{
*key_to_remove = key;
}
else
{
const Item *item_to_remove =
g_hash_table_lookup (xedit_metadata_manager->items,
*key_to_remove);
g_return_if_fail (item_to_remove != NULL);
if (item->atime < item_to_remove->atime)
{
*key_to_remove = key;
}
}
}
static void
resize_items (void)
{
while (g_hash_table_size (xedit_metadata_manager->items) > MAX_ITEMS)
{
gpointer key_to_remove = NULL;
g_hash_table_foreach (xedit_metadata_manager->items,
(GHFunc)get_oldest,
&key_to_remove);
g_return_if_fail (key_to_remove != NULL);
g_hash_table_remove (xedit_metadata_manager->items,
key_to_remove);
}
}
static gboolean
xedit_metadata_manager_save (gpointer data)
{
xmlDocPtr doc;
xmlNodePtr root;
gchar *file_name;
xedit_debug (DEBUG_METADATA);
xedit_metadata_manager->timeout_id = 0;
resize_items ();
xmlIndentTreeOutput = TRUE;
doc = xmlNewDoc ((const xmlChar *)"1.0");
if (doc == NULL)
return TRUE;
/* Create metadata root */
root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL);
xmlDocSetRootElement (doc, root);
g_hash_table_foreach (xedit_metadata_manager->items,
(GHFunc)save_item,
root);
/* FIXME: lock file - Paolo */
file_name = get_metadata_filename ();
if (file_name != NULL)
{
gchar *cache_dir;
int res;
/* make sure the cache dir exists */
cache_dir = xedit_dirs_get_user_cache_dir ();
res = g_mkdir_with_parents (cache_dir, 0755);
if (res != -1)
{
xmlSaveFormatFile (file_name, doc, 1);
}
g_free (cache_dir);
g_free (file_name);
}
xmlFreeDoc (doc);
xedit_debug_message (DEBUG_METADATA, "DONE");
return FALSE;
}

View File

@@ -0,0 +1,50 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xedit-metadata-manager.h
* This file is part of xedit
*
* Copyright (C) 2003 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2003. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*/
#ifndef __XEDIT_METADATA_MANAGER_H__
#define __XEDIT_METADATA_MANAGER_H__
#include <glib.h>
G_BEGIN_DECLS
/* This function must be called before exiting xedit */
void xedit_metadata_manager_shutdown (void);
gchar *xedit_metadata_manager_get (const gchar *uri,
const gchar *key);
void xedit_metadata_manager_set (const gchar *uri,
const gchar *key,
const gchar *value);
G_END_DECLS
#endif /* __XEDIT_METADATA_MANAGER_H__ */

1092
xedit/xedit-notebook.c Normal file

File diff suppressed because it is too large Load Diff

143
xedit/xedit-notebook.h Normal file
View File

@@ -0,0 +1,143 @@
/*
* xedit-notebook.h
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*/
/* This file is a modified version of the epiphany file ephy-notebook.h
* Here the relevant copyright:
*
* Copyright (C) 2002 Christophe Fergeau
* Copyright (C) 2003 Marco Pesenti Gritti
* Copyright (C) 2003, 2004 Christian Persch
*
*/
#ifndef XEDIT_NOTEBOOK_H
#define XEDIT_NOTEBOOK_H
#include <xedit/xedit-tab.h>
#include <glib.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_NOTEBOOK (xedit_notebook_get_type ())
#define XEDIT_NOTEBOOK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XEDIT_TYPE_NOTEBOOK, XeditNotebook))
#define XEDIT_NOTEBOOK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), XEDIT_TYPE_NOTEBOOK, XeditNotebookClass))
#define XEDIT_IS_NOTEBOOK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), XEDIT_TYPE_NOTEBOOK))
#define XEDIT_IS_NOTEBOOK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), XEDIT_TYPE_NOTEBOOK))
#define XEDIT_NOTEBOOK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), XEDIT_TYPE_NOTEBOOK, XeditNotebookClass))
/* Private structure type */
typedef struct _XeditNotebookPrivate XeditNotebookPrivate;
/*
* Main object structure
*/
typedef struct _XeditNotebook XeditNotebook;
struct _XeditNotebook
{
GtkNotebook notebook;
/*< private >*/
XeditNotebookPrivate *priv;
};
/*
* Class definition
*/
typedef struct _XeditNotebookClass XeditNotebookClass;
struct _XeditNotebookClass
{
GtkNotebookClass parent_class;
/* Signals */
void (* tab_added) (XeditNotebook *notebook,
XeditTab *tab);
void (* tab_removed) (XeditNotebook *notebook,
XeditTab *tab);
void (* tab_detached) (XeditNotebook *notebook,
XeditTab *tab);
void (* tabs_reordered) (XeditNotebook *notebook);
void (* tab_close_request)
(XeditNotebook *notebook,
XeditTab *tab);
};
/*
* Public methods
*/
GType xedit_notebook_get_type (void) G_GNUC_CONST;
GtkWidget *xedit_notebook_new (void);
void xedit_notebook_add_tab (XeditNotebook *nb,
XeditTab *tab,
gint position,
gboolean jump_to);
void xedit_notebook_remove_tab (XeditNotebook *nb,
XeditTab *tab);
void xedit_notebook_remove_all_tabs (XeditNotebook *nb);
void xedit_notebook_reorder_tab (XeditNotebook *src,
XeditTab *tab,
gint dest_position);
void xedit_notebook_move_tab (XeditNotebook *src,
XeditNotebook *dest,
XeditTab *tab,
gint dest_position);
/* FIXME: do we really need this function ? */
void xedit_notebook_set_always_show_tabs
(XeditNotebook *nb,
gboolean show_tabs);
void xedit_notebook_set_close_buttons_sensitive
(XeditNotebook *nb,
gboolean sensitive);
gboolean xedit_notebook_get_close_buttons_sensitive
(XeditNotebook *nb);
void xedit_notebook_set_tab_drag_and_drop_enabled
(XeditNotebook *nb,
gboolean enable);
gboolean xedit_notebook_get_tab_drag_and_drop_enabled
(XeditNotebook *nb);
G_END_DECLS
#endif /* XEDIT_NOTEBOOK_H */

343
xedit/xedit-object-module.c Normal file
View File

@@ -0,0 +1,343 @@
/*
* xedit-object-module.c
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
* Copyright (C) 2008 - Jesse van den Kieboom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/* This is a modified version of ephy-module.c from Epiphany source code.
* Here the original copyright assignment:
*
* Copyright (C) 2003 Marco Pesenti Gritti
* Copyright (C) 2003, 2004 Christian Persch
*
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id: xedit-module.c 6314 2008-06-05 12:57:53Z pborelli $
*/
#include "config.h"
#include "xedit-object-module.h"
#include "xedit-debug.h"
typedef GType (*XeditObjectModuleRegisterFunc) (GTypeModule *);
enum {
PROP_0,
PROP_MODULE_NAME,
PROP_PATH,
PROP_TYPE_REGISTRATION,
PROP_RESIDENT
};
struct _XeditObjectModulePrivate
{
GModule *library;
GType type;
gchar *path;
gchar *module_name;
gchar *type_registration;
gboolean resident;
};
G_DEFINE_TYPE (XeditObjectModule, xedit_object_module, G_TYPE_TYPE_MODULE);
static gboolean
xedit_object_module_load (GTypeModule *gmodule)
{
XeditObjectModule *module = XEDIT_OBJECT_MODULE (gmodule);
XeditObjectModuleRegisterFunc register_func;
gchar *path;
xedit_debug_message (DEBUG_PLUGINS, "Loading %s module from %s",
module->priv->module_name, module->priv->path);
path = g_module_build_path (module->priv->path, module->priv->module_name);
g_return_val_if_fail (path != NULL, FALSE);
xedit_debug_message (DEBUG_PLUGINS, "Module filename: %s", path);
module->priv->library = g_module_open (path,
G_MODULE_BIND_LAZY);
g_free (path);
if (module->priv->library == NULL)
{
g_warning ("%s: %s", module->priv->module_name, g_module_error());
return FALSE;
}
/* extract symbols from the lib */
if (!g_module_symbol (module->priv->library, module->priv->type_registration,
(void *) &register_func))
{
g_warning ("%s: %s", module->priv->module_name, g_module_error());
g_module_close (module->priv->library);
return FALSE;
}
/* symbol can still be NULL even though g_module_symbol
* returned TRUE */
if (register_func == NULL)
{
g_warning ("Symbol '%s' should not be NULL", module->priv->type_registration);
g_module_close (module->priv->library);
return FALSE;
}
module->priv->type = register_func (gmodule);
if (module->priv->type == 0)
{
g_warning ("Invalid object contained by module %s", module->priv->module_name);
return FALSE;
}
if (module->priv->resident)
{
g_module_make_resident (module->priv->library);
}
return TRUE;
}
static void
xedit_object_module_unload (GTypeModule *gmodule)
{
XeditObjectModule *module = XEDIT_OBJECT_MODULE (gmodule);
xedit_debug_message (DEBUG_PLUGINS, "Unloading %s", module->priv->path);
g_module_close (module->priv->library);
module->priv->library = NULL;
module->priv->type = 0;
}
static void
xedit_object_module_init (XeditObjectModule *module)
{
xedit_debug_message (DEBUG_PLUGINS, "XeditObjectModule %p initialising", module);
module->priv = G_TYPE_INSTANCE_GET_PRIVATE (module,
XEDIT_TYPE_OBJECT_MODULE,
XeditObjectModulePrivate);
}
static void
xedit_object_module_finalize (GObject *object)
{
XeditObjectModule *module = XEDIT_OBJECT_MODULE (object);
xedit_debug_message (DEBUG_PLUGINS, "XeditObjectModule %p finalising", module);
g_free (module->priv->path);
g_free (module->priv->module_name);
g_free (module->priv->type_registration);
G_OBJECT_CLASS (xedit_object_module_parent_class)->finalize (object);
}
static void
xedit_object_module_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XeditObjectModule *module = XEDIT_OBJECT_MODULE (object);
switch (prop_id)
{
case PROP_MODULE_NAME:
g_value_set_string (value, module->priv->module_name);
break;
case PROP_PATH:
g_value_set_string (value, module->priv->path);
break;
case PROP_TYPE_REGISTRATION:
g_value_set_string (value, module->priv->type_registration);
break;
case PROP_RESIDENT:
g_value_set_boolean (value, module->priv->resident);
break;
default:
g_return_if_reached ();
}
}
static void
xedit_object_module_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XeditObjectModule *module = XEDIT_OBJECT_MODULE (object);
switch (prop_id)
{
case PROP_MODULE_NAME:
module->priv->module_name = g_value_dup_string (value);
g_type_module_set_name (G_TYPE_MODULE (object),
module->priv->module_name);
break;
case PROP_PATH:
module->priv->path = g_value_dup_string (value);
break;
case PROP_TYPE_REGISTRATION:
module->priv->type_registration = g_value_dup_string (value);
break;
case PROP_RESIDENT:
module->priv->resident = g_value_get_boolean (value);
break;
default:
g_return_if_reached ();
}
}
static void
xedit_object_module_class_init (XeditObjectModuleClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (klass);
object_class->set_property = xedit_object_module_set_property;
object_class->get_property = xedit_object_module_get_property;
object_class->finalize = xedit_object_module_finalize;
module_class->load = xedit_object_module_load;
module_class->unload = xedit_object_module_unload;
g_object_class_install_property (object_class,
PROP_MODULE_NAME,
g_param_spec_string ("module-name",
"Module Name",
"The module to load for this object",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_PATH,
g_param_spec_string ("path",
"Path",
"The path to use when loading this module",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_TYPE_REGISTRATION,
g_param_spec_string ("type-registration",
"Type Registration",
"The name of the type registration function",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_RESIDENT,
g_param_spec_boolean ("resident",
"Resident",
"Whether the module is resident",
FALSE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_type_class_add_private (klass, sizeof (XeditObjectModulePrivate));
}
XeditObjectModule *
xedit_object_module_new (const gchar *module_name,
const gchar *path,
const gchar *type_registration,
gboolean resident)
{
return (XeditObjectModule *)g_object_new (XEDIT_TYPE_OBJECT_MODULE,
"module-name",
module_name,
"path",
path,
"type-registration",
type_registration,
"resident",
resident,
NULL);
}
GObject *
xedit_object_module_new_object (XeditObjectModule *module,
const gchar *first_property_name,
...)
{
va_list var_args;
GObject *result;
g_return_val_if_fail (module->priv->type != 0, NULL);
xedit_debug_message (DEBUG_PLUGINS, "Creating object of type %s",
g_type_name (module->priv->type));
va_start (var_args, first_property_name);
result = g_object_new_valist (module->priv->type, first_property_name, var_args);
va_end (var_args);
return result;
}
const gchar *
xedit_object_module_get_path (XeditObjectModule *module)
{
g_return_val_if_fail (XEDIT_IS_OBJECT_MODULE (module), NULL);
return module->priv->path;
}
const gchar *
xedit_object_module_get_module_name (XeditObjectModule *module)
{
g_return_val_if_fail (XEDIT_IS_OBJECT_MODULE (module), NULL);
return module->priv->module_name;
}
const gchar *
xedit_object_module_get_type_registration (XeditObjectModule *module)
{
g_return_val_if_fail (XEDIT_IS_OBJECT_MODULE (module), NULL);
return module->priv->type_registration;
}
GType
xedit_object_module_get_object_type (XeditObjectModule *module)
{
g_return_val_if_fail (XEDIT_IS_OBJECT_MODULE (module), 0);
return module->priv->type;
}

View File

@@ -0,0 +1,94 @@
/*
* xedit-object-module.h
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
* Copyright (C) 2008 - Jesse van den Kieboom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/* This is a modified version of xedit-module.h from Epiphany source code.
* Here the original copyright assignment:
*
* Copyright (C) 2003 Marco Pesenti Gritti
* Copyright (C) 2003, 2004 Christian Persch
*
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id: xedit-module.h 6263 2008-05-05 10:52:10Z sfre $
*/
#ifndef __XEDIT_OBJECT_MODULE_H__
#define __XEDIT_OBJECT_MODULE_H__
#include <glib-object.h>
#include <gmodule.h>
#include <stdarg.h>
G_BEGIN_DECLS
#define XEDIT_TYPE_OBJECT_MODULE (xedit_object_module_get_type ())
#define XEDIT_OBJECT_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_OBJECT_MODULE, XeditObjectModule))
#define XEDIT_OBJECT_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XEDIT_TYPE_OBJECT_MODULE, XeditObjectModuleClass))
#define XEDIT_IS_OBJECT_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XEDIT_TYPE_OBJECT_MODULE))
#define XEDIT_IS_OBJECT_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_OBJECT_MODULE))
#define XEDIT_OBJECT_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_OBJECT_MODULE, XeditObjectModuleClass))
typedef struct _XeditObjectModule XeditObjectModule;
typedef struct _XeditObjectModulePrivate XeditObjectModulePrivate;
struct _XeditObjectModule
{
GTypeModule parent;
XeditObjectModulePrivate *priv;
};
typedef struct _XeditObjectModuleClass XeditObjectModuleClass;
struct _XeditObjectModuleClass
{
GTypeModuleClass parent_class;
/* Virtual class methods */
void (* garbage_collect) ();
};
GType xedit_object_module_get_type (void) G_GNUC_CONST;
XeditObjectModule *xedit_object_module_new (const gchar *module_name,
const gchar *path,
const gchar *type_registration,
gboolean resident);
GObject *xedit_object_module_new_object (XeditObjectModule *module,
const gchar *first_property_name,
...);
GType xedit_object_module_get_object_type (XeditObjectModule *module);
const gchar *xedit_object_module_get_path (XeditObjectModule *module);
const gchar *xedit_object_module_get_module_name (XeditObjectModule *module);
const gchar *xedit_object_module_get_type_registration (XeditObjectModule *module);
G_END_DECLS
#endif

986
xedit/xedit-panel.c Normal file
View File

@@ -0,0 +1,986 @@
/*
* xedit-panel.c
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#include "xedit-panel.h"
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#include "xedit-close-button.h"
#include "xedit-window.h"
#include "xedit-debug.h"
#define PANEL_ITEM_KEY "XeditPanelItemKey"
#define XEDIT_PANEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), XEDIT_TYPE_PANEL, XeditPanelPrivate))
#if GTK_CHECK_VERSION (3, 0, 0)
#define gtk_hbox_new(X,Y) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,Y)
#define gtk_vbox_new(X,Y) gtk_box_new(GTK_ORIENTATION_VERTICAL,Y)
#endif
struct _XeditPanelPrivate
{
GtkOrientation orientation;
/* Title bar (vertical panel only) */
GtkWidget *title_image;
GtkWidget *title_label;
/* Notebook */
GtkWidget *notebook;
};
typedef struct _XeditPanelItem XeditPanelItem;
struct _XeditPanelItem
{
gchar *name;
GtkWidget *icon;
};
/* Properties */
enum {
PROP_0,
PROP_ORIENTATION
};
/* Signals */
enum {
ITEM_ADDED,
ITEM_REMOVED,
CLOSE,
FOCUS_DOCUMENT,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
static GObject *xedit_panel_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties);
#if GTK_CHECK_VERSION (3, 0, 0)
G_DEFINE_TYPE(XeditPanel, xedit_panel, GTK_TYPE_BOX)
#else
G_DEFINE_TYPE(XeditPanel, xedit_panel, GTK_TYPE_VBOX)
#endif
static void
xedit_panel_finalize (GObject *obj)
{
if (G_OBJECT_CLASS (xedit_panel_parent_class)->finalize)
(*G_OBJECT_CLASS (xedit_panel_parent_class)->finalize) (obj);
}
static void
xedit_panel_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XeditPanel *panel = XEDIT_PANEL (object);
switch (prop_id)
{
case PROP_ORIENTATION:
g_value_set_enum(value, panel->priv->orientation);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_panel_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XeditPanel *panel = XEDIT_PANEL (object);
switch (prop_id)
{
case PROP_ORIENTATION:
panel->priv->orientation = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xedit_panel_close (XeditPanel *panel)
{
gtk_widget_hide (GTK_WIDGET (panel));
}
static void
xedit_panel_focus_document (XeditPanel *panel)
{
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (panel));
if (gtk_widget_is_toplevel (toplevel) && XEDIT_IS_WINDOW (toplevel))
{
XeditView *view;
view = xedit_window_get_active_view (XEDIT_WINDOW (toplevel));
if (view != NULL)
gtk_widget_grab_focus (GTK_WIDGET (view));
}
}
static void
xedit_panel_grab_focus (GtkWidget *w)
{
gint n;
GtkWidget *tab;
XeditPanel *panel = XEDIT_PANEL (w);
n = gtk_notebook_get_current_page (GTK_NOTEBOOK (panel->priv->notebook));
if (n == -1)
return;
tab = gtk_notebook_get_nth_page (GTK_NOTEBOOK (panel->priv->notebook),
n);
g_return_if_fail (tab != NULL);
gtk_widget_grab_focus (tab);
}
static void
xedit_panel_class_init (XeditPanelClass *klass)
{
GtkBindingSet *binding_set;
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
g_type_class_add_private (klass, sizeof (XeditPanelPrivate));
object_class->constructor = xedit_panel_constructor;
object_class->finalize = xedit_panel_finalize;
object_class->get_property = xedit_panel_get_property;
object_class->set_property = xedit_panel_set_property;
g_object_class_install_property (object_class,
PROP_ORIENTATION,
#if GTK_CHECK_VERSION (3, 0, 0)
g_param_spec_enum ("panel-orientation",
"Panel Orientation",
#else
g_param_spec_enum ("orientation",
"Orientation",
#endif
"The panel's orientation",
GTK_TYPE_ORIENTATION,
GTK_ORIENTATION_VERTICAL,
G_PARAM_WRITABLE |
G_PARAM_READABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
widget_class->grab_focus = xedit_panel_grab_focus;
klass->close = xedit_panel_close;
klass->focus_document = xedit_panel_focus_document;
signals[ITEM_ADDED] =
g_signal_new ("item_added",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (XeditPanelClass, item_added),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
GTK_TYPE_WIDGET);
signals[ITEM_REMOVED] =
g_signal_new ("item_removed",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (XeditPanelClass, item_removed),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE,
1,
GTK_TYPE_WIDGET);
/* Keybinding signals */
signals[CLOSE] =
g_signal_new ("close",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (XeditPanelClass, close),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[FOCUS_DOCUMENT] =
g_signal_new ("focus_document",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (XeditPanelClass, focus_document),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
binding_set = gtk_binding_set_by_class (klass);
gtk_binding_entry_add_signal (binding_set,
GDK_KEY_Escape,
0,
"close",
0);
gtk_binding_entry_add_signal (binding_set,
GDK_KEY_Return,
GDK_CONTROL_MASK,
"focus_document",
0);
}
/* This is ugly, since it supports only known
* storage types of GtkImage, otherwise fall back
* to the empty icon.
* See http://bugzilla.gnome.org/show_bug.cgi?id=317520.
*/
static void
set_gtk_image_from_gtk_image (GtkImage *image,
GtkImage *source)
{
switch (gtk_image_get_storage_type (source))
{
case GTK_IMAGE_EMPTY:
gtk_image_clear (image);
break;
#if !GTK_CHECK_VERSION (3, 0, 0)
case GTK_IMAGE_PIXMAP:
{
GdkPixmap *pm;
GdkBitmap *bm;
gtk_image_get_pixmap (source, &pm, &bm);
gtk_image_set_from_pixmap (image, pm, bm);
}
break;
case GTK_IMAGE_IMAGE:
{
GdkImage *i;
GdkBitmap *bm;
gtk_image_get_image (source, &i, &bm);
gtk_image_set_from_image (image, i, bm);
}
break;
#endif
case GTK_IMAGE_PIXBUF:
{
GdkPixbuf *pb;
pb = gtk_image_get_pixbuf (source);
gtk_image_set_from_pixbuf (image, pb);
}
break;
case GTK_IMAGE_STOCK:
{
gchar *s_id;
GtkIconSize s;
gtk_image_get_stock (source, &s_id, &s);
gtk_image_set_from_stock (image, s_id, s);
}
break;
case GTK_IMAGE_ICON_SET:
{
GtkIconSet *is;
GtkIconSize s;
gtk_image_get_icon_set (source, &is, &s);
gtk_image_set_from_icon_set (image, is, s);
}
break;
case GTK_IMAGE_ANIMATION:
{
GdkPixbufAnimation *a;
a = gtk_image_get_animation (source);
gtk_image_set_from_animation (image, a);
}
break;
case GTK_IMAGE_ICON_NAME:
{
const gchar *n;
GtkIconSize s;
gtk_image_get_icon_name (source, &n, &s);
gtk_image_set_from_icon_name (image, n, s);
}
break;
default:
gtk_image_set_from_stock (image,
GTK_STOCK_FILE,
GTK_ICON_SIZE_MENU);
}
}
static void
sync_title (XeditPanel *panel,
XeditPanelItem *item)
{
if (panel->priv->orientation != GTK_ORIENTATION_VERTICAL)
return;
if (item != NULL)
{
gtk_label_set_text (GTK_LABEL (panel->priv->title_label),
item->name);
set_gtk_image_from_gtk_image (GTK_IMAGE (panel->priv->title_image),
GTK_IMAGE (item->icon));
}
else
{
gtk_label_set_text (GTK_LABEL (panel->priv->title_label),
_("Empty"));
gtk_image_set_from_stock (GTK_IMAGE (panel->priv->title_image),
GTK_STOCK_FILE,
GTK_ICON_SIZE_MENU);
}
}
static void
notebook_page_changed (GtkNotebook *notebook,
GtkWidget *page,
guint page_num,
XeditPanel *panel)
{
GtkWidget *item;
XeditPanelItem *data;
item = gtk_notebook_get_nth_page (notebook, page_num);
g_return_if_fail (item != NULL);
data = (XeditPanelItem *)g_object_get_data (G_OBJECT (item),
PANEL_ITEM_KEY);
g_return_if_fail (data != NULL);
sync_title (panel, data);
}
static void
panel_show (XeditPanel *panel,
gpointer user_data)
{
gint page;
GtkNotebook *nb;
nb = GTK_NOTEBOOK (panel->priv->notebook);
page = gtk_notebook_get_current_page (nb);
if (page != -1)
notebook_page_changed (nb, NULL, page, panel);
}
static void
xedit_panel_init (XeditPanel *panel)
{
panel->priv = XEDIT_PANEL_GET_PRIVATE (panel);
#if GTK_CHECK_VERSION (3, 0, 0)
gtk_orientable_set_orientation (GTK_ORIENTABLE (panel),
GTK_ORIENTATION_VERTICAL);
#endif
}
static void
close_button_clicked_cb (GtkWidget *widget,
GtkWidget *panel)
{
gtk_widget_hide (panel);
}
static GtkWidget *
create_close_button (XeditPanel *panel)
{
GtkWidget *button;
button = xedit_close_button_new ();
gtk_widget_set_tooltip_text (button, _("Hide panel"));
g_signal_connect (button,
"clicked",
G_CALLBACK (close_button_clicked_cb),
panel);
return button;
}
static void
build_notebook_for_panel (XeditPanel *panel)
{
/* Create the panel notebook */
panel->priv->notebook = gtk_notebook_new ();
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (panel->priv->notebook),
GTK_POS_BOTTOM);
gtk_notebook_set_scrollable (GTK_NOTEBOOK (panel->priv->notebook),
TRUE);
gtk_notebook_popup_enable (GTK_NOTEBOOK (panel->priv->notebook));
gtk_widget_show (GTK_WIDGET (panel->priv->notebook));
g_signal_connect (panel->priv->notebook,
"switch-page",
G_CALLBACK (notebook_page_changed),
panel);
}
static void
build_horizontal_panel (XeditPanel *panel)
{
GtkWidget *box;
GtkWidget *sidebar;
GtkWidget *close_button;
box = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start (GTK_BOX (box),
panel->priv->notebook,
TRUE,
TRUE,
0);
/* Toolbar, close button and first separator */
sidebar = gtk_vbox_new(FALSE, 6);
gtk_container_set_border_width (GTK_CONTAINER (sidebar), 4);
gtk_box_pack_start (GTK_BOX (box),
sidebar,
FALSE,
FALSE,
0);
close_button = create_close_button (panel);
gtk_box_pack_start (GTK_BOX (sidebar),
close_button,
FALSE,
FALSE,
0);
gtk_widget_show_all (box);
gtk_box_pack_start (GTK_BOX (panel),
box,
TRUE,
TRUE,
0);
}
static void
build_vertical_panel (XeditPanel *panel)
{
GtkWidget *close_button;
GtkWidget *title_hbox;
GtkWidget *icon_name_hbox;
GtkWidget *dummy_label;
/* Create title hbox */
title_hbox = gtk_hbox_new (FALSE, 6);
gtk_container_set_border_width (GTK_CONTAINER (title_hbox), 5);
gtk_box_pack_start (GTK_BOX (panel), title_hbox, FALSE, FALSE, 0);
icon_name_hbox = gtk_hbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (title_hbox),
icon_name_hbox,
TRUE,
TRUE,
0);
panel->priv->title_image =
gtk_image_new_from_stock (GTK_STOCK_FILE,
GTK_ICON_SIZE_MENU);
gtk_box_pack_start (GTK_BOX (icon_name_hbox),
panel->priv->title_image,
FALSE,
TRUE,
0);
dummy_label = gtk_label_new (" ");
gtk_box_pack_start (GTK_BOX (icon_name_hbox),
dummy_label,
FALSE,
FALSE,
0);
panel->priv->title_label = gtk_label_new (_("Empty"));
#if GTK_CHECK_VERSION (3, 16, 0)
gtk_label_set_xalign (GTK_LABEL (panel->priv->title_label), 0.0);
#else
gtk_misc_set_alignment (GTK_MISC (panel->priv->title_label), 0, 0.5);
#endif
gtk_label_set_ellipsize(GTK_LABEL (panel->priv->title_label), PANGO_ELLIPSIZE_END);
gtk_box_pack_start (GTK_BOX (icon_name_hbox),
panel->priv->title_label,
TRUE,
TRUE,
0);
close_button = create_close_button (panel);
gtk_box_pack_start (GTK_BOX (title_hbox),
close_button,
FALSE,
FALSE,
0);
gtk_widget_show_all (title_hbox);
gtk_box_pack_start (GTK_BOX (panel),
panel->priv->notebook,
TRUE,
TRUE,
0);
}
static GObject *
xedit_panel_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
/* Invoke parent constructor. */
XeditPanelClass *klass = XEDIT_PANEL_CLASS (g_type_class_peek (XEDIT_TYPE_PANEL));
GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
GObject *obj = parent_class->constructor (type,
n_construct_properties,
construct_properties);
/* Build the panel, now that we know the orientation
(_init has been called previously) */
XeditPanel *panel = XEDIT_PANEL (obj);
build_notebook_for_panel (panel);
if (panel->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
build_horizontal_panel (panel);
else
build_vertical_panel (panel);
g_signal_connect (panel,
"show",
G_CALLBACK (panel_show),
NULL);
return obj;
}
/**
* xedit_panel_new:
* @orientation: a #GtkOrientation
*
* Creates a new #XeditPanel with the given @orientation. You shouldn't create
* a new panel use xedit_window_get_side_panel() or xedit_window_get_bottom_panel()
* instead.
*
* Returns: a new #XeditPanel object.
*/
GtkWidget *
xedit_panel_new (GtkOrientation orientation)
{
return GTK_WIDGET (g_object_new (XEDIT_TYPE_PANEL, "orientation", orientation, NULL));
}
static GtkWidget *
build_tab_label (XeditPanel *panel,
GtkWidget *item,
const gchar *name,
GtkWidget *icon)
{
GtkWidget *hbox, *label_hbox, *label_ebox;
GtkWidget *label;
/* set hbox spacing and label padding (see below) so that there's an
* equal amount of space around the label */
hbox = gtk_hbox_new (FALSE, 4);
label_ebox = gtk_event_box_new ();
gtk_event_box_set_visible_window (GTK_EVENT_BOX (label_ebox), FALSE);
gtk_box_pack_start (GTK_BOX (hbox), label_ebox, TRUE, TRUE, 0);
label_hbox = gtk_hbox_new (FALSE, 4);
gtk_container_add (GTK_CONTAINER (label_ebox), label_hbox);
/* setup icon */
gtk_box_pack_start (GTK_BOX (label_hbox), icon, FALSE, FALSE, 0);
/* setup label */
label = gtk_label_new (name);
#if GTK_CHECK_VERSION (3, 16, 0)
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
#else
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
#if GTK_CHECK_VERSION (3, 0, 0)
gtk_widget_set_margin_left (label, 0);
gtk_widget_set_margin_right (label, 0);
gtk_widget_set_margin_top (label, 0);
gtk_widget_set_margin_bottom (label, 0);
#else
gtk_misc_set_padding (GTK_MISC (label), 0, 0);
#endif
gtk_box_pack_start (GTK_BOX (label_hbox), label, TRUE, TRUE, 0);
gtk_widget_set_tooltip_text (label_ebox, name);
gtk_widget_show_all (hbox);
if (panel->priv->orientation == GTK_ORIENTATION_VERTICAL)
gtk_widget_hide(label);
g_object_set_data (G_OBJECT (item), "label", label);
g_object_set_data (G_OBJECT (item), "hbox", hbox);
return hbox;
}
/**
* xedit_panel_add_item:
* @panel: a #XeditPanel
* @item: the #GtkWidget to add to the @panel
* @name: the name to be shown in the @panel
* @image: the image to be shown in the @panel
*
* Adds a new item to the @panel.
*/
void
xedit_panel_add_item (XeditPanel *panel,
GtkWidget *item,
const gchar *name,
GtkWidget *image)
{
XeditPanelItem *data;
GtkWidget *tab_label;
GtkWidget *menu_label;
gint w, h;
g_return_if_fail (XEDIT_IS_PANEL (panel));
g_return_if_fail (GTK_IS_WIDGET (item));
g_return_if_fail (name != NULL);
g_return_if_fail (image == NULL || GTK_IS_IMAGE (image));
data = g_new (XeditPanelItem, 1);
data->name = g_strdup (name);
if (image == NULL)
{
/* default to empty */
data->icon = gtk_image_new_from_stock (GTK_STOCK_FILE,
GTK_ICON_SIZE_MENU);
}
else
{
data->icon = image;
}
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
gtk_widget_set_size_request (data->icon, w, h);
g_object_set_data (G_OBJECT (item),
PANEL_ITEM_KEY,
data);
tab_label = build_tab_label (panel, item, data->name, data->icon);
menu_label = gtk_label_new (name);
#if GTK_CHECK_VERSION (3, 16, 0)
gtk_label_set_xalign (GTK_LABEL (menu_label), 0.0);
#else
gtk_misc_set_alignment (GTK_MISC (menu_label), 0.0, 0.5);
#endif
if (!gtk_widget_get_visible (item))
gtk_widget_show (item);
gtk_notebook_append_page_menu (GTK_NOTEBOOK (panel->priv->notebook),
item,
tab_label,
menu_label);
g_signal_emit (G_OBJECT (panel), signals[ITEM_ADDED], 0, item);
}
/**
* xedit_panel_add_item_with_stock_icon:
* @panel: a #XeditPanel
* @item: the #GtkWidget to add to the @panel
* @name: the name to be shown in the @panel
* @stock_id: a stock id
*
* Same as xedit_panel_add_item() but using an image from stock.
*/
void
xedit_panel_add_item_with_stock_icon (XeditPanel *panel,
GtkWidget *item,
const gchar *name,
const gchar *stock_id)
{
GtkWidget *icon = NULL;
if (stock_id != NULL)
{
icon = gtk_image_new_from_stock (stock_id,
GTK_ICON_SIZE_MENU);
}
xedit_panel_add_item (panel, item, name, icon);
}
/**
* xedit_panel_remove_item:
* @panel: a #XeditPanel
* @item: the item to be removed from the panel
*
* Removes the widget @item from the panel if it is in the @panel and returns
* %TRUE if there was not any problem.
*
* Returns: %TRUE if it was well removed.
*/
gboolean
xedit_panel_remove_item (XeditPanel *panel,
GtkWidget *item)
{
XeditPanelItem *data;
gint page_num;
g_return_val_if_fail (XEDIT_IS_PANEL (panel), FALSE);
g_return_val_if_fail (GTK_IS_WIDGET (item), FALSE);
page_num = gtk_notebook_page_num (GTK_NOTEBOOK (panel->priv->notebook),
item);
if (page_num == -1)
return FALSE;
data = (XeditPanelItem *)g_object_get_data (G_OBJECT (item),
PANEL_ITEM_KEY);
g_return_val_if_fail (data != NULL, FALSE);
g_free (data->name);
g_free (data);
g_object_set_data (G_OBJECT (item),
PANEL_ITEM_KEY,
NULL);
/* ref the item to keep it alive during signal emission */
g_object_ref (G_OBJECT (item));
gtk_notebook_remove_page (GTK_NOTEBOOK (panel->priv->notebook),
page_num);
/* if we removed all the pages, reset the title */
if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (panel->priv->notebook)) == 0)
sync_title (panel, NULL);
g_signal_emit (G_OBJECT (panel), signals[ITEM_REMOVED], 0, item);
g_object_unref (G_OBJECT (item));
return TRUE;
}
/**
* xedit_panel_activate_item:
* @panel: a #XeditPanel
* @item: the item to be activated
*
* Switches to the page that contains @item.
*
* Returns: %TRUE if it was activated
*/
gboolean
xedit_panel_activate_item (XeditPanel *panel,
GtkWidget *item)
{
gint page_num;
g_return_val_if_fail (XEDIT_IS_PANEL (panel), FALSE);
g_return_val_if_fail (GTK_IS_WIDGET (item), FALSE);
page_num = gtk_notebook_page_num (GTK_NOTEBOOK (panel->priv->notebook),
item);
if (page_num == -1)
return FALSE;
gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->priv->notebook),
page_num);
return TRUE;
}
/**
* xedit_panel_item_is_active:
* @panel: a #XeditPanel
* @item: a #GtkWidget
*
* Returns whether @item is the active widget in @panel
*
* Returns: %TRUE if @item is the active widget
*/
gboolean
xedit_panel_item_is_active (XeditPanel *panel,
GtkWidget *item)
{
gint cur_page;
gint page_num;
g_return_val_if_fail (XEDIT_IS_PANEL (panel), FALSE);
g_return_val_if_fail (GTK_IS_WIDGET (item), FALSE);
page_num = gtk_notebook_page_num (GTK_NOTEBOOK (panel->priv->notebook),
item);
if (page_num == -1)
return FALSE;
cur_page = gtk_notebook_get_current_page (
GTK_NOTEBOOK (panel->priv->notebook));
return (page_num == cur_page);
}
/**
* xedit_panel_get_orientation:
* @panel: a #XeditPanel
*
* Gets the orientation of the @panel.
*
* Returns: the #GtkOrientation of #XeditPanel
*/
GtkOrientation
xedit_panel_get_orientation (XeditPanel *panel)
{
g_return_val_if_fail (XEDIT_IS_PANEL (panel), GTK_ORIENTATION_VERTICAL);
return panel->priv->orientation;
}
/**
* xedit_panel_get_n_items:
* @panel: a #XeditPanel
*
* Gets the number of items in a @panel.
*
* Returns: the number of items contained in #XeditPanel
*/
gint
xedit_panel_get_n_items (XeditPanel *panel)
{
g_return_val_if_fail (XEDIT_IS_PANEL (panel), -1);
return gtk_notebook_get_n_pages (GTK_NOTEBOOK (panel->priv->notebook));
}
gint
_xedit_panel_get_active_item_id (XeditPanel *panel)
{
gint cur_page;
GtkWidget *item;
XeditPanelItem *data;
g_return_val_if_fail (XEDIT_IS_PANEL (panel), 0);
cur_page = gtk_notebook_get_current_page (
GTK_NOTEBOOK (panel->priv->notebook));
if (cur_page == -1)
return 0;
item = gtk_notebook_get_nth_page (
GTK_NOTEBOOK (panel->priv->notebook),
cur_page);
/* FIXME: for now we use as the hash of the name as id.
* However the name is not guaranteed to be unique and
* it is a translated string, so it's subotimal, but should
* be good enough for now since we don't want to add an
* ad hoc id argument.
*/
data = (XeditPanelItem *)g_object_get_data (G_OBJECT (item),
PANEL_ITEM_KEY);
g_return_val_if_fail (data != NULL, 0);
return g_str_hash (data->name);
}
void
_xedit_panel_set_active_item_by_id (XeditPanel *panel,
gint id)
{
gint n, i;
g_return_if_fail (XEDIT_IS_PANEL (panel));
if (id == 0)
return;
n = gtk_notebook_get_n_pages (
GTK_NOTEBOOK (panel->priv->notebook));
for (i = 0; i < n; i++)
{
GtkWidget *item;
XeditPanelItem *data;
item = gtk_notebook_get_nth_page (
GTK_NOTEBOOK (panel->priv->notebook), i);
data = (XeditPanelItem *)g_object_get_data (G_OBJECT (item),
PANEL_ITEM_KEY);
g_return_if_fail (data != NULL);
if (g_str_hash (data->name) == id)
{
gtk_notebook_set_current_page (
GTK_NOTEBOOK (panel->priv->notebook), i);
return;
}
}
}

138
xedit/xedit-panel.h Normal file
View File

@@ -0,0 +1,138 @@
/*
* xedit-panel.h
* This file is part of xedit
*
* Copyright (C) 2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_PANEL_H__
#define __XEDIT_PANEL_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_PANEL (xedit_panel_get_type())
#define XEDIT_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_PANEL, XeditPanel))
#define XEDIT_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_PANEL, XeditPanelClass))
#define XEDIT_IS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_PANEL))
#define XEDIT_IS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_PANEL))
#define XEDIT_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_PANEL, XeditPanelClass))
/* Private structure type */
typedef struct _XeditPanelPrivate XeditPanelPrivate;
/*
* Main object structure
*/
typedef struct _XeditPanel XeditPanel;
struct _XeditPanel
{
#if GTK_CHECK_VERSION (3, 0, 0)
GtkBox vbox;
#else
GtkVBox vbox;
#endif
/*< private > */
XeditPanelPrivate *priv;
};
/*
* Class definition
*/
typedef struct _XeditPanelClass XeditPanelClass;
struct _XeditPanelClass
{
#if GTK_CHECK_VERSION (3, 0, 0)
GtkBoxClass parent_class;
#else
GtkVBoxClass parent_class;
#endif
void (* item_added) (XeditPanel *panel,
GtkWidget *item);
void (* item_removed) (XeditPanel *panel,
GtkWidget *item);
/* Keybinding signals */
void (* close) (XeditPanel *panel);
void (* focus_document) (XeditPanel *panel);
/* Padding for future expansion */
void (*_xedit_reserved1) (void);
void (*_xedit_reserved2) (void);
void (*_xedit_reserved3) (void);
void (*_xedit_reserved4) (void);
};
/*
* Public methods
*/
GType xedit_panel_get_type (void) G_GNUC_CONST;
GtkWidget *xedit_panel_new (GtkOrientation orientation);
void xedit_panel_add_item (XeditPanel *panel,
GtkWidget *item,
const gchar *name,
GtkWidget *image);
void xedit_panel_add_item_with_stock_icon (XeditPanel *panel,
GtkWidget *item,
const gchar *name,
const gchar *stock_id);
gboolean xedit_panel_remove_item (XeditPanel *panel,
GtkWidget *item);
gboolean xedit_panel_activate_item (XeditPanel *panel,
GtkWidget *item);
gboolean xedit_panel_item_is_active (XeditPanel *panel,
GtkWidget *item);
GtkOrientation xedit_panel_get_orientation (XeditPanel *panel);
gint xedit_panel_get_n_items (XeditPanel *panel);
/*
* Non exported functions
*/
gint _xedit_panel_get_active_item_id (XeditPanel *panel);
void _xedit_panel_set_active_item_by_id (XeditPanel *panel,
gint id);
G_END_DECLS
#endif /* __XEDIT_PANEL_H__ */

View File

@@ -0,0 +1,68 @@
/*
* xedit-plugin-info-priv.h
* This file is part of xedit
*
* Copyright (C) 2002-2005 - Paolo Maggi
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002-2007. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_PLUGIN_INFO_PRIV_H__
#define __XEDIT_PLUGIN_INFO_PRIV_H__
#include "xedit-plugin-info.h"
#include "xedit-plugin.h"
struct _XeditPluginInfo
{
gint refcount;
XeditPlugin *plugin;
gchar *file;
gchar *module_name;
gchar *loader;
gchar **dependencies;
gchar *name;
gchar *desc;
gchar *icon_name;
gchar **authors;
gchar *copyright;
gchar *website;
gchar *version;
/* A plugin is unavailable if it is not possible to activate it
due to an error loading the plugin module (e.g. for Python plugins
when the interpreter has not been correctly initializated) */
gint available : 1;
};
XeditPluginInfo *_xedit_plugin_info_new (const gchar *file);
void _xedit_plugin_info_ref (XeditPluginInfo *info);
void _xedit_plugin_info_unref (XeditPluginInfo *info);
#endif /* __XEDIT_PLUGIN_INFO_PRIV_H__ */

396
xedit/xedit-plugin-info.c Normal file
View File

@@ -0,0 +1,396 @@
/*
* xedit-plugin-info.c
* This file is part of xedit
*
* Copyright (C) 2002-2005 - Paolo Maggi
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002-2007. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib/gi18n.h>
#include <glib.h>
#include "xedit-plugin-info.h"
#include "xedit-plugin-info-priv.h"
#include "xedit-debug.h"
#include "xedit-plugin.h"
void
_xedit_plugin_info_ref (XeditPluginInfo *info)
{
g_atomic_int_inc (&info->refcount);
}
static XeditPluginInfo *
xedit_plugin_info_copy (XeditPluginInfo *info)
{
_xedit_plugin_info_ref (info);
return info;
}
void
_xedit_plugin_info_unref (XeditPluginInfo *info)
{
if (!g_atomic_int_dec_and_test (&info->refcount))
return;
if (info->plugin != NULL)
{
xedit_debug_message (DEBUG_PLUGINS, "Unref plugin %s", info->name);
g_object_unref (info->plugin);
}
g_free (info->file);
g_free (info->module_name);
g_strfreev (info->dependencies);
g_free (info->name);
g_free (info->desc);
g_free (info->icon_name);
g_free (info->website);
g_free (info->copyright);
g_free (info->loader);
g_free (info->version);
g_strfreev (info->authors);
g_free (info);
}
/**
* xedit_plugin_info_get_type:
*
* Retrieves the #GType object which is associated with the #XeditPluginInfo
* class.
*
* Return value: the GType associated with #XeditPluginInfo.
**/
GType
xedit_plugin_info_get_type (void)
{
static GType the_type = 0;
if (G_UNLIKELY (!the_type))
the_type = g_boxed_type_register_static (
"XeditPluginInfo",
(GBoxedCopyFunc) xedit_plugin_info_copy,
(GBoxedFreeFunc) _xedit_plugin_info_unref);
return the_type;
}
/**
* xedit_plugin_info_new:
* @filename: the filename where to read the plugin information
*
* Creates a new #XeditPluginInfo from a file on the disk.
*
* Return value: a newly created #XeditPluginInfo.
*/
XeditPluginInfo *
_xedit_plugin_info_new (const gchar *file)
{
XeditPluginInfo *info;
GKeyFile *plugin_file = NULL;
gchar *str;
g_return_val_if_fail (file != NULL, NULL);
xedit_debug_message (DEBUG_PLUGINS, "Loading plugin: %s", file);
info = g_new0 (XeditPluginInfo, 1);
info->refcount = 1;
info->file = g_strdup (file);
plugin_file = g_key_file_new ();
if (!g_key_file_load_from_file (plugin_file, file, G_KEY_FILE_NONE, NULL))
{
g_warning ("Bad plugin file: %s", file);
goto error;
}
if (!g_key_file_has_key (plugin_file,
"Xedit Plugin",
"IAge",
NULL))
{
xedit_debug_message (DEBUG_PLUGINS,
"IAge key does not exist in file: %s", file);
goto error;
}
/* Check IAge=2 */
if (g_key_file_get_integer (plugin_file,
"Xedit Plugin",
"IAge",
NULL) != 2)
{
xedit_debug_message (DEBUG_PLUGINS,
"Wrong IAge in file: %s", file);
goto error;
}
/* Get module name */
str = g_key_file_get_string (plugin_file,
"Xedit Plugin",
"Module",
NULL);
if ((str != NULL) && (*str != '\0'))
{
info->module_name = str;
}
else
{
g_warning ("Could not find 'Module' in %s", file);
g_free (str);
goto error;
}
/* Get the dependency list */
info->dependencies = g_key_file_get_string_list (plugin_file,
"Xedit Plugin",
"Depends",
NULL,
NULL);
if (info->dependencies == NULL)
{
xedit_debug_message (DEBUG_PLUGINS, "Could not find 'Depends' in %s", file);
info->dependencies = g_new0 (gchar *, 1);
}
/* Get the loader for this plugin */
str = g_key_file_get_string (plugin_file,
"Xedit Plugin",
"Loader",
NULL);
if ((str != NULL) && (*str != '\0'))
{
info->loader = str;
}
else
{
/* default to the C loader */
info->loader = g_strdup("c");
g_free (str);
}
/* Get Name */
str = g_key_file_get_locale_string (plugin_file,
"Xedit Plugin",
"Name",
NULL, NULL);
if (str)
info->name = str;
else
{
g_warning ("Could not find 'Name' in %s", file);
goto error;
}
/* Get Description */
str = g_key_file_get_locale_string (plugin_file,
"Xedit Plugin",
"Description",
NULL, NULL);
if (str)
info->desc = str;
else
xedit_debug_message (DEBUG_PLUGINS, "Could not find 'Description' in %s", file);
/* Get Icon */
str = g_key_file_get_locale_string (plugin_file,
"Xedit Plugin",
"Icon",
NULL, NULL);
if (str)
info->icon_name = str;
else
xedit_debug_message (DEBUG_PLUGINS, "Could not find 'Icon' in %s, using 'xedit-plugin'", file);
/* Get Authors */
info->authors = g_key_file_get_string_list (plugin_file,
"Xedit Plugin",
"Authors",
NULL,
NULL);
if (info->authors == NULL)
xedit_debug_message (DEBUG_PLUGINS, "Could not find 'Authors' in %s", file);
/* Get Copyright */
str = g_key_file_get_string (plugin_file,
"Xedit Plugin",
"Copyright",
NULL);
if (str)
info->copyright = str;
else
xedit_debug_message (DEBUG_PLUGINS, "Could not find 'Copyright' in %s", file);
/* Get Website */
str = g_key_file_get_string (plugin_file,
"Xedit Plugin",
"Website",
NULL);
if (str)
info->website = str;
else
xedit_debug_message (DEBUG_PLUGINS, "Could not find 'Website' in %s", file);
/* Get Version */
str = g_key_file_get_string (plugin_file,
"Xedit Plugin",
"Version",
NULL);
if (str)
info->version = str;
else
xedit_debug_message (DEBUG_PLUGINS, "Could not find 'Version' in %s", file);
g_key_file_free (plugin_file);
/* If we know nothing about the availability of the plugin,
set it as available */
info->available = TRUE;
return info;
error:
g_free (info->file);
g_free (info->module_name);
g_free (info->name);
g_free (info->loader);
g_free (info);
g_key_file_free (plugin_file);
return NULL;
}
gboolean
xedit_plugin_info_is_active (XeditPluginInfo *info)
{
g_return_val_if_fail (info != NULL, FALSE);
return info->available && info->plugin != NULL;
}
gboolean
xedit_plugin_info_is_available (XeditPluginInfo *info)
{
g_return_val_if_fail (info != NULL, FALSE);
return info->available != FALSE;
}
gboolean
xedit_plugin_info_is_configurable (XeditPluginInfo *info)
{
xedit_debug_message (DEBUG_PLUGINS, "Is '%s' configurable?", info->name);
g_return_val_if_fail (info != NULL, FALSE);
if (info->plugin == NULL || !info->available)
return FALSE;
return xedit_plugin_is_configurable (info->plugin);
}
const gchar *
xedit_plugin_info_get_module_name (XeditPluginInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
return info->module_name;
}
const gchar *
xedit_plugin_info_get_name (XeditPluginInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
return info->name;
}
const gchar *
xedit_plugin_info_get_description (XeditPluginInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
return info->desc;
}
const gchar *
xedit_plugin_info_get_icon_name (XeditPluginInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
/* use the xedit-plugin icon as a default if the plugin does not
have its own */
if (info->icon_name != NULL &&
gtk_icon_theme_has_icon (gtk_icon_theme_get_default (),
info->icon_name))
return info->icon_name;
else
return "xedit-plugin";
}
const gchar **
xedit_plugin_info_get_authors (XeditPluginInfo *info)
{
g_return_val_if_fail (info != NULL, (const gchar **)NULL);
return (const gchar **) info->authors;
}
const gchar *
xedit_plugin_info_get_website (XeditPluginInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
return info->website;
}
const gchar *
xedit_plugin_info_get_copyright (XeditPluginInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
return info->copyright;
}
const gchar *
xedit_plugin_info_get_version (XeditPluginInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
return info->version;
}

63
xedit/xedit-plugin-info.h Normal file
View File

@@ -0,0 +1,63 @@
/*
* xedit-plugin-info.h
* This file is part of xedit
*
* Copyright (C) 2002-2005 - Paolo Maggi
* Copyright (C) 2007 - Paolo Maggi, Steve Frécinaux
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002-2007. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_PLUGIN_INFO_H__
#define __XEDIT_PLUGIN_INFO_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define XEDIT_TYPE_PLUGIN_INFO (xedit_plugin_info_get_type ())
#define XEDIT_PLUGIN_INFO(obj) ((XeditPluginInfo *) (obj))
typedef struct _XeditPluginInfo XeditPluginInfo;
GType xedit_plugin_info_get_type (void) G_GNUC_CONST;
gboolean xedit_plugin_info_is_active (XeditPluginInfo *info);
gboolean xedit_plugin_info_is_available (XeditPluginInfo *info);
gboolean xedit_plugin_info_is_configurable (XeditPluginInfo *info);
const gchar *xedit_plugin_info_get_module_name (XeditPluginInfo *info);
const gchar *xedit_plugin_info_get_name (XeditPluginInfo *info);
const gchar *xedit_plugin_info_get_description (XeditPluginInfo *info);
const gchar *xedit_plugin_info_get_icon_name (XeditPluginInfo *info);
const gchar **xedit_plugin_info_get_authors (XeditPluginInfo *info);
const gchar *xedit_plugin_info_get_website (XeditPluginInfo *info);
const gchar *xedit_plugin_info_get_copyright (XeditPluginInfo *info);
const gchar *xedit_plugin_info_get_version (XeditPluginInfo *info);
G_END_DECLS
#endif /* __XEDIT_PLUGIN_INFO_H__ */

131
xedit/xedit-plugin-loader.c Normal file
View File

@@ -0,0 +1,131 @@
/*
* xedit-plugin-loader.c
* This file is part of xedit
*
* Copyright (C) 2008 - Jesse van den Kieboom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "xedit-plugin-loader.h"
static void
xedit_plugin_loader_base_init (gpointer g_class)
{
static gboolean initialized = FALSE;
if (G_UNLIKELY (!initialized))
{
/* create interface signals here. */
initialized = TRUE;
}
}
GType
xedit_plugin_loader_get_type (void)
{
static GType type = 0;
if (G_UNLIKELY (type == 0))
{
static const GTypeInfo info =
{
sizeof (XeditPluginLoaderInterface),
xedit_plugin_loader_base_init, /* base_init */
NULL, /* base_finalize */
NULL, /* class_init */
NULL, /* class_finalize */
NULL, /* class_data */
0,
0, /* n_preallocs */
NULL /* instance_init */
};
type = g_type_register_static (G_TYPE_INTERFACE, "XeditPluginLoader", &info, 0);
}
return type;
}
const gchar *
xedit_plugin_loader_type_get_id (GType type)
{
GTypeClass *klass;
XeditPluginLoaderInterface *iface;
klass = g_type_class_ref (type);
if (klass == NULL)
{
g_warning ("Could not get class info for plugin loader");
return NULL;
}
iface = g_type_interface_peek (klass, XEDIT_TYPE_PLUGIN_LOADER);
if (iface == NULL)
{
g_warning ("Could not get plugin loader interface");
g_type_class_unref (klass);
return NULL;
}
g_return_val_if_fail (iface->get_id != NULL, NULL);
return iface->get_id ();
}
XeditPlugin *
xedit_plugin_loader_load (XeditPluginLoader *loader,
XeditPluginInfo *info,
const gchar *path)
{
XeditPluginLoaderInterface *iface;
g_return_val_if_fail (XEDIT_IS_PLUGIN_LOADER (loader), NULL);
iface = XEDIT_PLUGIN_LOADER_GET_INTERFACE (loader);
g_return_val_if_fail (iface->load != NULL, NULL);
return iface->load (loader, info, path);
}
void
xedit_plugin_loader_unload (XeditPluginLoader *loader,
XeditPluginInfo *info)
{
XeditPluginLoaderInterface *iface;
g_return_if_fail (XEDIT_IS_PLUGIN_LOADER (loader));
iface = XEDIT_PLUGIN_LOADER_GET_INTERFACE (loader);
g_return_if_fail (iface->unload != NULL);
iface->unload (loader, info);
}
void
xedit_plugin_loader_garbage_collect (XeditPluginLoader *loader)
{
XeditPluginLoaderInterface *iface;
g_return_if_fail (XEDIT_IS_PLUGIN_LOADER (loader));
iface = XEDIT_PLUGIN_LOADER_GET_INTERFACE (loader);
if (iface->garbage_collect != NULL)
iface->garbage_collect (loader);
}

106
xedit/xedit-plugin-loader.h Normal file
View File

@@ -0,0 +1,106 @@
/*
* xedit-plugin-loader.h
* This file is part of xedit
*
* Copyright (C) 2008 - Jesse van den Kieboom
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __XEDIT_PLUGIN_LOADER_H__
#define __XEDIT_PLUGIN_LOADER_H__
#include <glib-object.h>
#include <xedit/xedit-plugin.h>
#include <xedit/xedit-plugin-info.h>
G_BEGIN_DECLS
#define XEDIT_TYPE_PLUGIN_LOADER (xedit_plugin_loader_get_type ())
#define XEDIT_PLUGIN_LOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XEDIT_TYPE_PLUGIN_LOADER, XeditPluginLoader))
#define XEDIT_IS_PLUGIN_LOADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XEDIT_TYPE_PLUGIN_LOADER))
#define XEDIT_PLUGIN_LOADER_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), XEDIT_TYPE_PLUGIN_LOADER, XeditPluginLoaderInterface))
typedef struct _XeditPluginLoader XeditPluginLoader; /* dummy object */
typedef struct _XeditPluginLoaderInterface XeditPluginLoaderInterface;
struct _XeditPluginLoaderInterface {
GTypeInterface parent;
const gchar *(*get_id) (void);
XeditPlugin *(*load) (XeditPluginLoader *loader,
XeditPluginInfo *info,
const gchar *path);
void (*unload) (XeditPluginLoader *loader,
XeditPluginInfo *info);
void (*garbage_collect) (XeditPluginLoader *loader);
};
GType xedit_plugin_loader_get_type (void);
const gchar *xedit_plugin_loader_type_get_id (GType type);
XeditPlugin *xedit_plugin_loader_load (XeditPluginLoader *loader,
XeditPluginInfo *info,
const gchar *path);
void xedit_plugin_loader_unload (XeditPluginLoader *loader,
XeditPluginInfo *info);
void xedit_plugin_loader_garbage_collect (XeditPluginLoader *loader);
/**
* XEDIT_PLUGIN_LOADER_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init):
*
* Utility macro used to register interfaces for gobject types in plugin loaders.
*/
#define XEDIT_PLUGIN_LOADER_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init) \
const GInterfaceInfo g_implement_interface_info = \
{ \
(GInterfaceInitFunc) iface_init, \
NULL, \
NULL \
}; \
\
g_type_module_add_interface (type_module, \
g_define_type_id, \
TYPE_IFACE, \
&g_implement_interface_info);
/**
* XEDIT_PLUGIN_LOADER_REGISTER_TYPE(PluginLoaderName, plugin_loader_name, PARENT_TYPE, loader_interface_init):
*
* Utility macro used to register plugin loaders.
*/
#define XEDIT_PLUGIN_LOADER_REGISTER_TYPE(PluginLoaderName, plugin_loader_name, PARENT_TYPE, loader_iface_init) \
G_DEFINE_DYNAMIC_TYPE_EXTENDED (PluginLoaderName, \
plugin_loader_name, \
PARENT_TYPE, \
0, \
XEDIT_PLUGIN_LOADER_IMPLEMENT_INTERFACE(XEDIT_TYPE_PLUGIN_LOADER, loader_iface_init)); \
\
\
G_MODULE_EXPORT GType \
register_xedit_plugin_loader (GTypeModule *type_module) \
{ \
plugin_loader_name##_register_type (type_module); \
\
return plugin_loader_name##_get_type(); \
}
G_END_DECLS
#endif /* __XEDIT_PLUGIN_LOADER_H__ */

View File

@@ -0,0 +1,906 @@
/*
* xedit-plugin-manager.c
* This file is part of xedit
*
* Copyright (C) 2002 Paolo Maggi and James Willcox
* Copyright (C) 2003-2006 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 1998-2006. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib/gi18n.h>
#include "xedit-plugin-manager.h"
#include "xedit-utils.h"
#include "xedit-plugins-engine.h"
#include "xedit-plugin.h"
#include "xedit-debug.h"
enum
{
ACTIVE_COLUMN,
AVAILABLE_COLUMN,
INFO_COLUMN,
N_COLUMNS
};
#define PLUGIN_MANAGER_NAME_TITLE _("Plugin")
#define PLUGIN_MANAGER_ACTIVE_TITLE _("Enabled")
#define XEDIT_PLUGIN_MANAGER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), XEDIT_TYPE_PLUGIN_MANAGER, XeditPluginManagerPrivate))
struct _XeditPluginManagerPrivate
{
GtkWidget *tree;
GtkWidget *about_button;
GtkWidget *configure_button;
XeditPluginsEngine *engine;
GtkWidget *about;
GtkWidget *popup_menu;
};
#if GTK_CHECK_VERSION (3, 0, 0)
G_DEFINE_TYPE(XeditPluginManager, xedit_plugin_manager, GTK_TYPE_BOX)
#else
G_DEFINE_TYPE(XeditPluginManager, xedit_plugin_manager, GTK_TYPE_VBOX)
#endif
static XeditPluginInfo *plugin_manager_get_selected_plugin (XeditPluginManager *pm);
static void plugin_manager_toggle_active (XeditPluginManager *pm, GtkTreeIter *iter, GtkTreeModel *model);
static void xedit_plugin_manager_finalize (GObject *object);
static void
xedit_plugin_manager_class_init (XeditPluginManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = xedit_plugin_manager_finalize;
g_type_class_add_private (object_class, sizeof (XeditPluginManagerPrivate));
}
static void
about_button_cb (GtkWidget *button,
XeditPluginManager *pm)
{
XeditPluginInfo *info;
xedit_debug (DEBUG_PLUGINS);
info = plugin_manager_get_selected_plugin (pm);
g_return_if_fail (info != NULL);
/* if there is another about dialog already open destroy it */
if (pm->priv->about)
gtk_widget_destroy (pm->priv->about);
pm->priv->about = g_object_new (GTK_TYPE_ABOUT_DIALOG,
"program-name", xedit_plugin_info_get_name (info),
"copyright", xedit_plugin_info_get_copyright (info),
"authors", xedit_plugin_info_get_authors (info),
"comments", xedit_plugin_info_get_description (info),
"website", xedit_plugin_info_get_website (info),
"logo-icon-name", xedit_plugin_info_get_icon_name (info),
"version", xedit_plugin_info_get_version (info),
NULL);
gtk_window_set_destroy_with_parent (GTK_WINDOW (pm->priv->about),
TRUE);
g_signal_connect (pm->priv->about,
"response",
G_CALLBACK (gtk_widget_destroy),
NULL);
g_signal_connect (pm->priv->about,
"destroy",
G_CALLBACK (gtk_widget_destroyed),
&pm->priv->about);
gtk_window_set_transient_for (GTK_WINDOW (pm->priv->about),
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET(pm))));
gtk_widget_show (pm->priv->about);
}
static void
configure_button_cb (GtkWidget *button,
XeditPluginManager *pm)
{
XeditPluginInfo *info;
GtkWindow *toplevel;
xedit_debug (DEBUG_PLUGINS);
info = plugin_manager_get_selected_plugin (pm);
g_return_if_fail (info != NULL);
xedit_debug_message (DEBUG_PLUGINS, "Configuring: %s\n",
xedit_plugin_info_get_name (info));
toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET(pm)));
xedit_plugins_engine_configure_plugin (pm->priv->engine,
info, toplevel);
xedit_debug_message (DEBUG_PLUGINS, "Done");
}
static void
plugin_manager_view_info_cell_cb (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data)
{
XeditPluginInfo *info;
gchar *text;
g_return_if_fail (tree_model != NULL);
g_return_if_fail (tree_column != NULL);
gtk_tree_model_get (tree_model, iter, INFO_COLUMN, &info, -1);
if (info == NULL)
return;
text = g_markup_printf_escaped ("<b>%s</b>\n%s",
xedit_plugin_info_get_name (info),
xedit_plugin_info_get_description (info));
g_object_set (G_OBJECT (cell),
"markup", text,
"sensitive", xedit_plugin_info_is_available (info),
NULL);
g_free (text);
}
static void
plugin_manager_view_icon_cell_cb (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer data)
{
XeditPluginInfo *info;
g_return_if_fail (tree_model != NULL);
g_return_if_fail (tree_column != NULL);
gtk_tree_model_get (tree_model, iter, INFO_COLUMN, &info, -1);
if (info == NULL)
return;
g_object_set (G_OBJECT (cell),
"icon-name", xedit_plugin_info_get_icon_name (info),
"sensitive", xedit_plugin_info_is_available (info),
NULL);
}
static void
active_toggled_cb (GtkCellRendererToggle *cell,
gchar *path_str,
XeditPluginManager *pm)
{
GtkTreeIter iter;
GtkTreePath *path;
GtkTreeModel *model;
xedit_debug (DEBUG_PLUGINS);
path = gtk_tree_path_new_from_string (path_str);
model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
g_return_if_fail (model != NULL);
gtk_tree_model_get_iter (model, &iter, path);
if (&iter != NULL)
plugin_manager_toggle_active (pm, &iter, model);
gtk_tree_path_free (path);
}
static void
cursor_changed_cb (GtkTreeView *view,
gpointer data)
{
XeditPluginManager *pm = data;
XeditPluginInfo *info;
xedit_debug (DEBUG_PLUGINS);
info = plugin_manager_get_selected_plugin (pm);
gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->about_button),
info != NULL);
gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->configure_button),
(info != NULL) &&
xedit_plugin_info_is_configurable (info));
}
static void
row_activated_cb (GtkTreeView *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
gpointer data)
{
XeditPluginManager *pm = data;
GtkTreeIter iter;
GtkTreeModel *model;
xedit_debug (DEBUG_PLUGINS);
model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
g_return_if_fail (model != NULL);
gtk_tree_model_get_iter (model, &iter, path);
g_return_if_fail (&iter != NULL);
plugin_manager_toggle_active (pm, &iter, model);
}
static void
plugin_manager_populate_lists (XeditPluginManager *pm)
{
const GList *plugins;
GtkListStore *model;
GtkTreeIter iter;
xedit_debug (DEBUG_PLUGINS);
plugins = xedit_plugins_engine_get_plugin_list (pm->priv->engine);
model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree)));
while (plugins)
{
XeditPluginInfo *info;
info = (XeditPluginInfo *)plugins->data;
gtk_list_store_append (model, &iter);
gtk_list_store_set (model, &iter,
ACTIVE_COLUMN, xedit_plugin_info_is_active (info),
AVAILABLE_COLUMN, xedit_plugin_info_is_available (info),
INFO_COLUMN, info,
-1);
plugins = plugins->next;
}
if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
{
GtkTreeSelection *selection;
XeditPluginInfo* info;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree));
g_return_if_fail (selection != NULL);
gtk_tree_selection_select_iter (selection, &iter);
gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
INFO_COLUMN, &info, -1);
gtk_widget_set_sensitive (GTK_WIDGET (pm->priv->configure_button),
xedit_plugin_info_is_configurable (info));
}
}
static gboolean
plugin_manager_set_active (XeditPluginManager *pm,
GtkTreeIter *iter,
GtkTreeModel *model,
gboolean active)
{
XeditPluginInfo *info;
gboolean res = TRUE;
xedit_debug (DEBUG_PLUGINS);
gtk_tree_model_get (model, iter, INFO_COLUMN, &info, -1);
g_return_val_if_fail (info != NULL, FALSE);
if (active)
{
/* activate the plugin */
if (!xedit_plugins_engine_activate_plugin (pm->priv->engine, info)) {
xedit_debug_message (DEBUG_PLUGINS, "Could not activate %s.\n",
xedit_plugin_info_get_name (info));
res = FALSE;
}
}
else
{
/* deactivate the plugin */
if (!xedit_plugins_engine_deactivate_plugin (pm->priv->engine, info)) {
xedit_debug_message (DEBUG_PLUGINS, "Could not deactivate %s.\n",
xedit_plugin_info_get_name (info));
res = FALSE;
}
}
return res;
}
static void
plugin_manager_toggle_active (XeditPluginManager *pm,
GtkTreeIter *iter,
GtkTreeModel *model)
{
gboolean active;
xedit_debug (DEBUG_PLUGINS);
gtk_tree_model_get (model, iter, ACTIVE_COLUMN, &active, -1);
active ^= 1;
plugin_manager_set_active (pm, iter, model, active);
}
static XeditPluginInfo *
plugin_manager_get_selected_plugin (XeditPluginManager *pm)
{
XeditPluginInfo *info = NULL;
GtkTreeModel *model;
GtkTreeIter iter;
GtkTreeSelection *selection;
xedit_debug (DEBUG_PLUGINS);
model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
g_return_val_if_fail (model != NULL, NULL);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree));
g_return_val_if_fail (selection != NULL, NULL);
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
{
gtk_tree_model_get (model, &iter, INFO_COLUMN, &info, -1);
}
return info;
}
static void
plugin_manager_set_active_all (XeditPluginManager *pm,
gboolean active)
{
GtkTreeModel *model;
GtkTreeIter iter;
xedit_debug (DEBUG_PLUGINS);
model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
g_return_if_fail (model != NULL);
gtk_tree_model_get_iter_first (model, &iter);
do {
plugin_manager_set_active (pm, &iter, model, active);
}
while (gtk_tree_model_iter_next (model, &iter));
}
/* Callback used as the interactive search comparison function */
static gboolean
name_search_cb (GtkTreeModel *model,
gint column,
const gchar *key,
GtkTreeIter *iter,
gpointer data)
{
XeditPluginInfo *info;
gchar *normalized_string;
gchar *normalized_key;
gchar *case_normalized_string;
gchar *case_normalized_key;
gint key_len;
gboolean retval;
gtk_tree_model_get (model, iter, INFO_COLUMN, &info, -1);
if (!info)
return FALSE;
normalized_string = g_utf8_normalize (xedit_plugin_info_get_name (info), -1, G_NORMALIZE_ALL);
normalized_key = g_utf8_normalize (key, -1, G_NORMALIZE_ALL);
case_normalized_string = g_utf8_casefold (normalized_string, -1);
case_normalized_key = g_utf8_casefold (normalized_key, -1);
key_len = strlen (case_normalized_key);
/* Oddly enough, this callback must return whether to stop the search
* because we found a match, not whether we actually matched.
*/
retval = (strncmp (case_normalized_key, case_normalized_string, key_len) != 0);
g_free (normalized_key);
g_free (normalized_string);
g_free (case_normalized_key);
g_free (case_normalized_string);
return retval;
}
static void
enable_plugin_menu_cb (GtkMenu *menu,
XeditPluginManager *pm)
{
GtkTreeModel *model;
GtkTreeIter iter;
GtkTreeSelection *selection;
model = gtk_tree_view_get_model (GTK_TREE_VIEW (pm->priv->tree));
g_return_if_fail (model != NULL);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree));
g_return_if_fail (selection != NULL);
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
plugin_manager_toggle_active (pm, &iter, model);
}
static void
enable_all_menu_cb (GtkMenu *menu,
XeditPluginManager *pm)
{
plugin_manager_set_active_all (pm, TRUE);
}
static void
disable_all_menu_cb (GtkMenu *menu,
XeditPluginManager *pm)
{
plugin_manager_set_active_all (pm, FALSE);
}
static GtkWidget *
create_tree_popup_menu (XeditPluginManager *pm)
{
GtkWidget *menu;
GtkWidget *item;
GtkWidget *image;
XeditPluginInfo *info;
info = plugin_manager_get_selected_plugin (pm);
menu = gtk_menu_new ();
item = gtk_image_menu_item_new_with_mnemonic (_("_About"));
image = gtk_image_new_from_stock (GTK_STOCK_ABOUT,
GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
g_signal_connect (item, "activate",
G_CALLBACK (about_button_cb), pm);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
item = gtk_image_menu_item_new_with_mnemonic (_("C_onfigure"));
image = gtk_image_new_from_stock (GTK_STOCK_PREFERENCES,
GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
g_signal_connect (item, "activate",
G_CALLBACK (configure_button_cb), pm);
gtk_widget_set_sensitive (item, xedit_plugin_info_is_configurable (info));
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
item = gtk_check_menu_item_new_with_mnemonic (_("A_ctivate"));
gtk_widget_set_sensitive (item, xedit_plugin_info_is_available (info));
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item),
xedit_plugin_info_is_active (info));
g_signal_connect (item, "toggled",
G_CALLBACK (enable_plugin_menu_cb), pm);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
item = gtk_separator_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
item = gtk_menu_item_new_with_mnemonic (_("Ac_tivate All"));
g_signal_connect (item, "activate",
G_CALLBACK (enable_all_menu_cb), pm);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
item = gtk_menu_item_new_with_mnemonic (_("_Deactivate All"));
g_signal_connect (item, "activate",
G_CALLBACK (disable_all_menu_cb), pm);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show_all (menu);
return menu;
}
static void
tree_popup_menu_detach (XeditPluginManager *pm,
GtkMenu *menu)
{
pm->priv->popup_menu = NULL;
}
static void
show_tree_popup_menu (GtkTreeView *tree,
XeditPluginManager *pm,
GdkEventButton *event)
{
if (pm->priv->popup_menu)
gtk_widget_destroy (pm->priv->popup_menu);
pm->priv->popup_menu = create_tree_popup_menu (pm);
gtk_menu_attach_to_widget (GTK_MENU (pm->priv->popup_menu),
GTK_WIDGET (pm),
(GtkMenuDetachFunc) tree_popup_menu_detach);
if (event != NULL)
{
gtk_menu_popup (GTK_MENU (pm->priv->popup_menu), NULL, NULL,
NULL, NULL,
event->button, event->time);
}
else
{
gtk_menu_popup (GTK_MENU (pm->priv->popup_menu), NULL, NULL,
xedit_utils_menu_position_under_tree_view, tree,
0, gtk_get_current_event_time ());
gtk_menu_shell_select_first (GTK_MENU_SHELL (pm->priv->popup_menu),
FALSE);
}
}
static gboolean
button_press_event_cb (GtkWidget *tree,
GdkEventButton *event,
XeditPluginManager *pm)
{
/* We want the treeview selection to be updated before showing the menu.
* This code is evil, thanks to Federico Mena Quintero's black magic.
* See: http://mail.gnome.org/archives/gtk-devel-list/2006-February/msg00168.html
* FIXME: Let's remove it asap.
*/
static gboolean in_press = FALSE;
gboolean handled;
if (in_press)
return FALSE; /* we re-entered */
if (GDK_BUTTON_PRESS != event->type || 3 != event->button)
return FALSE; /* let the normal handler run */
in_press = TRUE;
handled = gtk_widget_event (tree, (GdkEvent *) event);
in_press = FALSE;
if (!handled)
return FALSE;
/* The selection is fully updated by now */
show_tree_popup_menu (GTK_TREE_VIEW (tree), pm, event);
return TRUE;
}
static gboolean
popup_menu_cb (GtkTreeView *tree,
XeditPluginManager *pm)
{
show_tree_popup_menu (tree, pm, NULL);
return TRUE;
}
static gint
model_name_sort_func (GtkTreeModel *model,
GtkTreeIter *iter1,
GtkTreeIter *iter2,
gpointer user_data)
{
XeditPluginInfo *info1, *info2;
gtk_tree_model_get (model, iter1, INFO_COLUMN, &info1, -1);
gtk_tree_model_get (model, iter2, INFO_COLUMN, &info2, -1);
return g_utf8_collate (xedit_plugin_info_get_name (info1),
xedit_plugin_info_get_name (info2));
}
static void
plugin_manager_construct_tree (XeditPluginManager *pm)
{
GtkTreeViewColumn *column;
GtkCellRenderer *cell;
GtkListStore *model;
xedit_debug (DEBUG_PLUGINS);
model = gtk_list_store_new (N_COLUMNS,
G_TYPE_BOOLEAN,
G_TYPE_BOOLEAN,
G_TYPE_POINTER);
gtk_tree_view_set_model (GTK_TREE_VIEW (pm->priv->tree),
GTK_TREE_MODEL (model));
g_object_unref (model);
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (pm->priv->tree), TRUE);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (pm->priv->tree), FALSE);
/* first column */
cell = gtk_cell_renderer_toggle_new ();
g_object_set (cell, "xpad", 6, NULL);
g_signal_connect (cell,
"toggled",
G_CALLBACK (active_toggled_cb),
pm);
column = gtk_tree_view_column_new_with_attributes (PLUGIN_MANAGER_ACTIVE_TITLE,
cell,
"active",
ACTIVE_COLUMN,
"activatable",
AVAILABLE_COLUMN,
"sensitive",
AVAILABLE_COLUMN,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (pm->priv->tree), column);
/* second column */
column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_title (column, PLUGIN_MANAGER_NAME_TITLE);
gtk_tree_view_column_set_resizable (column, TRUE);
cell = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (column, cell, FALSE);
g_object_set (cell, "stock-size", GTK_ICON_SIZE_SMALL_TOOLBAR, NULL);
gtk_tree_view_column_set_cell_data_func (column, cell,
plugin_manager_view_icon_cell_cb,
pm, NULL);
cell = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, cell, TRUE);
g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
gtk_tree_view_column_set_cell_data_func (column, cell,
plugin_manager_view_info_cell_cb,
pm, NULL);
gtk_tree_view_column_set_spacing (column, 6);
gtk_tree_view_append_column (GTK_TREE_VIEW (pm->priv->tree), column);
/* Sort on the plugin names */
gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (model),
model_name_sort_func,
NULL,
NULL);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (model),
GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
GTK_SORT_ASCENDING);
/* Enable search for our non-string column */
gtk_tree_view_set_search_column (GTK_TREE_VIEW (pm->priv->tree),
INFO_COLUMN);
gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (pm->priv->tree),
name_search_cb,
NULL,
NULL);
g_signal_connect (pm->priv->tree,
"cursor_changed",
G_CALLBACK (cursor_changed_cb),
pm);
g_signal_connect (pm->priv->tree,
"row_activated",
G_CALLBACK (row_activated_cb),
pm);
g_signal_connect (pm->priv->tree,
"button-press-event",
G_CALLBACK (button_press_event_cb),
pm);
g_signal_connect (pm->priv->tree,
"popup-menu",
G_CALLBACK (popup_menu_cb),
pm);
gtk_widget_show (pm->priv->tree);
}
static void
plugin_toggled_cb (XeditPluginsEngine *engine,
XeditPluginInfo *info,
XeditPluginManager *pm)
{
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
gboolean info_found = FALSE;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (pm->priv->tree));
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
/* There is an item selected: it's probably the one we want! */
XeditPluginInfo *tinfo;
gtk_tree_model_get (model, &iter, INFO_COLUMN, &tinfo, -1);
info_found = info == tinfo;
}
if (!info_found)
{
gtk_tree_model_get_iter_first (model, &iter);
do
{
XeditPluginInfo *tinfo;
gtk_tree_model_get (model, &iter, INFO_COLUMN, &tinfo, -1);
info_found = info == tinfo;
}
while (!info_found && gtk_tree_model_iter_next (model, &iter));
}
if (!info_found)
{
g_warning ("XeditPluginManager: plugin '%s' not found in the tree model",
xedit_plugin_info_get_name (info));
return;
}
gtk_list_store_set (GTK_LIST_STORE (model), &iter, ACTIVE_COLUMN, xedit_plugin_info_is_active (info), -1);
}
static void
xedit_plugin_manager_init (XeditPluginManager *pm)
{
GtkWidget *label;
GtkWidget *viewport;
GtkWidget *hbuttonbox;
xedit_debug (DEBUG_PLUGINS);
pm->priv = XEDIT_PLUGIN_MANAGER_GET_PRIVATE (pm);
#if GTK_CHECK_VERSION (3, 0, 0)
gtk_orientable_set_orientation (GTK_ORIENTABLE (pm),
GTK_ORIENTATION_VERTICAL);
#endif
/*
* Always we create the manager, firstly we rescan the plugins directory
*/
xedit_plugins_engine_rescan_plugins (xedit_plugins_engine_get_default ());
gtk_box_set_spacing (GTK_BOX (pm), 6);
label = gtk_label_new_with_mnemonic (_("Active _Plugins:"));
gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
#if GTK_CHECK_VERSION (3, 16, 0)
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
#else
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
#endif
gtk_box_pack_start (GTK_BOX (pm), label, FALSE, TRUE, 0);
viewport = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (viewport),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (viewport),
GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (pm), viewport, TRUE, TRUE, 0);
pm->priv->tree = gtk_tree_view_new ();
gtk_container_add (GTK_CONTAINER (viewport), pm->priv->tree);
gtk_label_set_mnemonic_widget (GTK_LABEL (label), pm->priv->tree);
#if GTK_CHECK_VERSION (3, 0, 0)
hbuttonbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
#else
hbuttonbox = gtk_hbutton_box_new ();
#endif
gtk_box_pack_start (GTK_BOX (pm), hbuttonbox, FALSE, FALSE, 0);
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_END);
gtk_box_set_spacing (GTK_BOX (hbuttonbox), 8);
pm->priv->about_button = xedit_gtk_button_new_with_stock_icon (_("_About Plugin"),
GTK_STOCK_ABOUT);
gtk_container_add (GTK_CONTAINER (hbuttonbox), pm->priv->about_button);
pm->priv->configure_button = xedit_gtk_button_new_with_stock_icon (_("C_onfigure Plugin"),
GTK_STOCK_PREFERENCES);
gtk_container_add (GTK_CONTAINER (hbuttonbox), pm->priv->configure_button);
/* setup a window of a sane size. */
gtk_widget_set_size_request (GTK_WIDGET (viewport), 270, 100);
g_signal_connect (pm->priv->about_button,
"clicked",
G_CALLBACK (about_button_cb),
pm);
g_signal_connect (pm->priv->configure_button,
"clicked",
G_CALLBACK (configure_button_cb),
pm);
plugin_manager_construct_tree (pm);
/* get the plugin engine and populate the treeview */
pm->priv->engine = xedit_plugins_engine_get_default ();
g_signal_connect_after (pm->priv->engine,
"activate-plugin",
G_CALLBACK (plugin_toggled_cb),
pm);
g_signal_connect_after (pm->priv->engine,
"deactivate-plugin",
G_CALLBACK (plugin_toggled_cb),
pm);
if (xedit_plugins_engine_get_plugin_list (pm->priv->engine) != NULL)
{
plugin_manager_populate_lists (pm);
}
else
{
gtk_widget_set_sensitive (pm->priv->about_button, FALSE);
gtk_widget_set_sensitive (pm->priv->configure_button, FALSE);
}
}
static void
xedit_plugin_manager_finalize (GObject *object)
{
XeditPluginManager *pm = XEDIT_PLUGIN_MANAGER (object);
g_signal_handlers_disconnect_by_func (pm->priv->engine,
plugin_toggled_cb,
pm);
if (pm->priv->popup_menu)
gtk_widget_destroy (pm->priv->popup_menu);
G_OBJECT_CLASS (xedit_plugin_manager_parent_class)->finalize (object);
}
GtkWidget *xedit_plugin_manager_new (void)
{
return g_object_new (XEDIT_TYPE_PLUGIN_MANAGER,0);
}

View File

@@ -0,0 +1,91 @@
/*
* xedit-plugin-manager.h
* This file is part of xedit
*
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_PLUGIN_MANAGER_H__
#define __XEDIT_PLUGIN_MANAGER_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_PLUGIN_MANAGER (xedit_plugin_manager_get_type())
#define XEDIT_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_PLUGIN_MANAGER, XeditPluginManager))
#define XEDIT_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_PLUGIN_MANAGER, XeditPluginManagerClass))
#define XEDIT_IS_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_PLUGIN_MANAGER))
#define XEDIT_IS_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_PLUGIN_MANAGER))
#define XEDIT_PLUGIN_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_PLUGIN_MANAGER, XeditPluginManagerClass))
/* Private structure type */
typedef struct _XeditPluginManagerPrivate XeditPluginManagerPrivate;
/*
* Main object structure
*/
typedef struct _XeditPluginManager XeditPluginManager;
struct _XeditPluginManager
{
#if GTK_CHECK_VERSION (3, 0, 0)
GtkBox vbox;
#else
GtkVBox vbox;
#endif
/*< private > */
XeditPluginManagerPrivate *priv;
};
/*
* Class definition
*/
typedef struct _XeditPluginManagerClass XeditPluginManagerClass;
struct _XeditPluginManagerClass
{
#if GTK_CHECK_VERSION (3, 0, 0)
GtkBoxClass parent_class;
#else
GtkVBoxClass parent_class;
#endif
};
/*
* Public methods
*/
GType xedit_plugin_manager_get_type (void) G_GNUC_CONST;
GtkWidget *xedit_plugin_manager_new (void);
G_END_DECLS
#endif /* __XEDIT_PLUGIN_MANAGER_H__ */

334
xedit/xedit-plugin.c Normal file
View File

@@ -0,0 +1,334 @@
/*
* xedit-plugin.h
* This file is part of xedit
*
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "xedit-plugin.h"
#include "xedit-dirs.h"
/* properties */
enum {
PROP_0,
PROP_INSTALL_DIR,
PROP_DATA_DIR_NAME,
PROP_DATA_DIR
};
typedef struct _XeditPluginPrivate XeditPluginPrivate;
struct _XeditPluginPrivate
{
gchar *install_dir;
gchar *data_dir_name;
};
#define XEDIT_PLUGIN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), XEDIT_TYPE_PLUGIN, XeditPluginPrivate))
G_DEFINE_TYPE(XeditPlugin, xedit_plugin, G_TYPE_OBJECT)
static void
dummy (XeditPlugin *plugin, XeditWindow *window)
{
/* Empty */
}
static GtkWidget *
create_configure_dialog (XeditPlugin *plugin)
{
return NULL;
}
static gboolean
is_configurable (XeditPlugin *plugin)
{
return (XEDIT_PLUGIN_GET_CLASS (plugin)->create_configure_dialog !=
create_configure_dialog);
}
static void
xedit_plugin_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id)
{
case PROP_INSTALL_DIR:
g_value_take_string (value, xedit_plugin_get_install_dir (XEDIT_PLUGIN (object)));
break;
case PROP_DATA_DIR:
g_value_take_string (value, xedit_plugin_get_data_dir (XEDIT_PLUGIN (object)));
break;
default:
g_return_if_reached ();
}
}
static void
xedit_plugin_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XeditPluginPrivate *priv = XEDIT_PLUGIN_GET_PRIVATE (object);
switch (prop_id)
{
case PROP_INSTALL_DIR:
priv->install_dir = g_value_dup_string (value);
break;
case PROP_DATA_DIR_NAME:
priv->data_dir_name = g_value_dup_string (value);
break;
default:
g_return_if_reached ();
}
}
static void
xedit_plugin_finalize (GObject *object)
{
XeditPluginPrivate *priv = XEDIT_PLUGIN_GET_PRIVATE (object);
g_free (priv->install_dir);
g_free (priv->data_dir_name);
G_OBJECT_CLASS (xedit_plugin_parent_class)->finalize (object);
}
static void
xedit_plugin_class_init (XeditPluginClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
klass->activate = dummy;
klass->deactivate = dummy;
klass->update_ui = dummy;
klass->create_configure_dialog = create_configure_dialog;
klass->is_configurable = is_configurable;
object_class->get_property = xedit_plugin_get_property;
object_class->set_property = xedit_plugin_set_property;
object_class->finalize = xedit_plugin_finalize;
g_object_class_install_property (object_class,
PROP_INSTALL_DIR,
g_param_spec_string ("install-dir",
"Install Directory",
"The directory where the plugin is installed",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/* the basename of the data dir is set at construction time by the plugin loader
* while the full path is constructed on the fly to take into account relocability
* that's why we have a writeonly prop and a readonly prop */
g_object_class_install_property (object_class,
PROP_DATA_DIR_NAME,
g_param_spec_string ("data-dir-name",
"Basename of the data directory",
"The basename of the directory where the plugin should look for its data files",
NULL,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_DATA_DIR,
g_param_spec_string ("data-dir",
"Data Directory",
"The full path of the directory where the plugin should look for its data files",
NULL,
G_PARAM_READABLE));
g_type_class_add_private (klass, sizeof (XeditPluginPrivate));
}
static void
xedit_plugin_init (XeditPlugin *plugin)
{
/* Empty */
}
/**
* xedit_plugin_get_install_dir:
* @plugin: a #XeditPlugin
*
* Get the path of the directory where the plugin is installed.
*
* Return value: a newly allocated string with the path of the
* directory where the plugin is installed
*/
gchar *
xedit_plugin_get_install_dir (XeditPlugin *plugin)
{
g_return_val_if_fail (XEDIT_IS_PLUGIN (plugin), NULL);
return g_strdup (XEDIT_PLUGIN_GET_PRIVATE (plugin)->install_dir);
}
/**
* xedit_plugin_get_data_dir:
* @plugin: a #XeditPlugin
*
* Get the path of the directory where the plugin should look for
* its data files.
*
* Return value: a newly allocated string with the path of the
* directory where the plugin should look for its data files
*/
gchar *
xedit_plugin_get_data_dir (XeditPlugin *plugin)
{
XeditPluginPrivate *priv;
gchar *xedit_lib_dir;
gchar *data_dir;
g_return_val_if_fail (XEDIT_IS_PLUGIN (plugin), NULL);
priv = XEDIT_PLUGIN_GET_PRIVATE (plugin);
/* If it's a "user" plugin the data dir is
* install_dir/data_dir_name if instead it's a
* "system" plugin the data dir is under xedit_data_dir,
* so it's under $prefix/share/xedit/plugins/data_dir_name
* where data_dir_name usually it's the name of the plugin
*/
xedit_lib_dir = xedit_dirs_get_xedit_lib_dir ();
/* CHECK: is checking the prefix enough or should we be more
* careful about normalizing paths etc? */
if (g_str_has_prefix (priv->install_dir, xedit_lib_dir))
{
gchar *xedit_data_dir;
xedit_data_dir = xedit_dirs_get_xedit_data_dir ();
data_dir = g_build_filename (xedit_data_dir,
"plugins",
priv->data_dir_name,
NULL);
g_free (xedit_data_dir);
}
else
{
data_dir = g_build_filename (priv->install_dir,
priv->data_dir_name,
NULL);
}
g_free (xedit_lib_dir);
return data_dir;
}
/**
* xedit_plugin_activate:
* @plugin: a #XeditPlugin
* @window: a #XeditWindow
*
* Activates the plugin.
*/
void
xedit_plugin_activate (XeditPlugin *plugin,
XeditWindow *window)
{
g_return_if_fail (XEDIT_IS_PLUGIN (plugin));
g_return_if_fail (XEDIT_IS_WINDOW (window));
XEDIT_PLUGIN_GET_CLASS (plugin)->activate (plugin, window);
}
/**
* xedit_plugin_deactivate:
* @plugin: a #XeditPlugin
* @window: a #XeditWindow
*
* Deactivates the plugin.
*/
void
xedit_plugin_deactivate (XeditPlugin *plugin,
XeditWindow *window)
{
g_return_if_fail (XEDIT_IS_PLUGIN (plugin));
g_return_if_fail (XEDIT_IS_WINDOW (window));
XEDIT_PLUGIN_GET_CLASS (plugin)->deactivate (plugin, window);
}
/**
* xedit_plugin_update_ui:
* @plugin: a #XeditPlugin
* @window: a #XeditWindow
*
* Triggers an update of the user interface to take into account state changes
* caused by the plugin.
*/
void
xedit_plugin_update_ui (XeditPlugin *plugin,
XeditWindow *window)
{
g_return_if_fail (XEDIT_IS_PLUGIN (plugin));
g_return_if_fail (XEDIT_IS_WINDOW (window));
XEDIT_PLUGIN_GET_CLASS (plugin)->update_ui (plugin, window);
}
/**
* xedit_plugin_is_configurable:
* @plugin: a #XeditPlugin
*
* Whether the plugin is configurable.
*
* Returns: TRUE if the plugin is configurable:
*/
gboolean
xedit_plugin_is_configurable (XeditPlugin *plugin)
{
g_return_val_if_fail (XEDIT_IS_PLUGIN (plugin), FALSE);
return XEDIT_PLUGIN_GET_CLASS (plugin)->is_configurable (plugin);
}
/**
* xedit_plugin_create_configure_dialog:
* @plugin: a #XeditPlugin
*
* Creates the configure dialog widget for the plugin.
*
* Returns: the configure dialog widget for the plugin.
*/
GtkWidget *
xedit_plugin_create_configure_dialog (XeditPlugin *plugin)
{
g_return_val_if_fail (XEDIT_IS_PLUGIN (plugin), NULL);
return XEDIT_PLUGIN_GET_CLASS (plugin)->create_configure_dialog (plugin);
}

240
xedit/xedit-plugin.h Normal file
View File

@@ -0,0 +1,240 @@
/*
* xedit-plugin.h
* This file is part of xedit
*
* Copyright (C) 2002-2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_PLUGIN_H__
#define __XEDIT_PLUGIN_H__
#include <glib-object.h>
#include <xedit/xedit-window.h>
#include <xedit/xedit-debug.h>
/* TODO: add a .h file that includes all the .h files normally needed to
* develop a plugin */
G_BEGIN_DECLS
/*
* Type checking and casting macros
*/
#define XEDIT_TYPE_PLUGIN (xedit_plugin_get_type())
#define XEDIT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_PLUGIN, XeditPlugin))
#define XEDIT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_PLUGIN, XeditPluginClass))
#define XEDIT_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_PLUGIN))
#define XEDIT_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_PLUGIN))
#define XEDIT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_PLUGIN, XeditPluginClass))
/*
* Main object structure
*/
typedef struct _XeditPlugin XeditPlugin;
struct _XeditPlugin
{
GObject parent;
};
/*
* Class definition
*/
typedef struct _XeditPluginClass XeditPluginClass;
struct _XeditPluginClass
{
GObjectClass parent_class;
/* Virtual public methods */
void (*activate) (XeditPlugin *plugin,
XeditWindow *window);
void (*deactivate) (XeditPlugin *plugin,
XeditWindow *window);
void (*update_ui) (XeditPlugin *plugin,
XeditWindow *window);
GtkWidget *(*create_configure_dialog)
(XeditPlugin *plugin);
/* Plugins should not override this, it's handled automatically by
the XeditPluginClass */
gboolean (*is_configurable)
(XeditPlugin *plugin);
/* Padding for future expansion */
void (*_xedit_reserved1) (void);
void (*_xedit_reserved2) (void);
void (*_xedit_reserved3) (void);
void (*_xedit_reserved4) (void);
};
/*
* Public methods
*/
GType xedit_plugin_get_type (void) G_GNUC_CONST;
gchar *xedit_plugin_get_install_dir (XeditPlugin *plugin);
gchar *xedit_plugin_get_data_dir (XeditPlugin *plugin);
void xedit_plugin_activate (XeditPlugin *plugin,
XeditWindow *window);
void xedit_plugin_deactivate (XeditPlugin *plugin,
XeditWindow *window);
void xedit_plugin_update_ui (XeditPlugin *plugin,
XeditWindow *window);
gboolean xedit_plugin_is_configurable (XeditPlugin *plugin);
GtkWidget *xedit_plugin_create_configure_dialog
(XeditPlugin *plugin);
/**
* XEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, CODE):
*
* Utility macro used to register plugins with additional code.
*/
#define XEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, CODE) \
G_DEFINE_DYNAMIC_TYPE_EXTENDED (PluginName, \
plugin_name, \
XEDIT_TYPE_PLUGIN, \
0, \
GTypeModule *module G_GNUC_UNUSED = type_module; /* back compat */ \
CODE) \
\
/* This is not very nice, but G_DEFINE_DYNAMIC wants it and our old macro \
* did not support it */ \
static void \
plugin_name##_class_finalize (PluginName##Class *klass) \
{ \
} \
\
\
G_MODULE_EXPORT GType \
register_xedit_plugin (GTypeModule *type_module) \
{ \
plugin_name##_register_type (type_module); \
\
return plugin_name##_get_type(); \
}
/**
* XEDIT_PLUGIN_REGISTER_TYPE(PluginName, plugin_name):
*
* Utility macro used to register plugins.
*/
#define XEDIT_PLUGIN_REGISTER_TYPE(PluginName, plugin_name) \
XEDIT_PLUGIN_REGISTER_TYPE_WITH_CODE(PluginName, plugin_name, ;)
/**
* XEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, CODE):
*
* Utility macro used to register gobject types in plugins with additional code.
*
* Deprecated: use G_DEFINE_DYNAMIC_TYPE_EXTENDED instead
*/
#define XEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, CODE) \
\
static GType g_define_type_id = 0; \
\
GType \
object_name##_get_type (void) \
{ \
return g_define_type_id; \
} \
\
static void object_name##_init (ObjectName *self); \
static void object_name##_class_init (ObjectName##Class *klass); \
static gpointer object_name##_parent_class = NULL; \
static void object_name##_class_intern_init (gpointer klass) \
{ \
object_name##_parent_class = g_type_class_peek_parent (klass); \
object_name##_class_init ((ObjectName##Class *) klass); \
} \
\
GType \
object_name##_register_type (GTypeModule *type_module) \
{ \
GTypeModule *module G_GNUC_UNUSED = type_module; /* back compat */ \
static const GTypeInfo our_info = \
{ \
sizeof (ObjectName##Class), \
NULL, /* base_init */ \
NULL, /* base_finalize */ \
(GClassInitFunc) object_name##_class_intern_init, \
NULL, \
NULL, /* class_data */ \
sizeof (ObjectName), \
0, /* n_preallocs */ \
(GInstanceInitFunc) object_name##_init \
}; \
\
g_define_type_id = g_type_module_register_type (type_module, \
PARENT_TYPE, \
#ObjectName, \
&our_info, \
0); \
\
CODE \
\
return g_define_type_id; \
}
/**
* XEDIT_PLUGIN_DEFINE_TYPE(ObjectName, object_name, PARENT_TYPE):
*
* Utility macro used to register gobject types in plugins.
*
* Deprecated: use G_DEFINE_DYNAMIC instead
*/
#define XEDIT_PLUGIN_DEFINE_TYPE(ObjectName, object_name, PARENT_TYPE) \
XEDIT_PLUGIN_DEFINE_TYPE_WITH_CODE(ObjectName, object_name, PARENT_TYPE, ;)
/**
* XEDIT_PLUGIN_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init):
*
* Utility macro used to register interfaces for gobject types in plugins.
*/
#define XEDIT_PLUGIN_IMPLEMENT_INTERFACE(object_name, TYPE_IFACE, iface_init) \
const GInterfaceInfo object_name##_interface_info = \
{ \
(GInterfaceInitFunc) iface_init, \
NULL, \
NULL \
}; \
\
g_type_module_add_interface (type_module, \
g_define_type_id, \
TYPE_IFACE, \
&object_name##_interface_info);
G_END_DECLS
#endif /* __XEDIT_PLUGIN_H__ */

View File

@@ -0,0 +1,861 @@
/*
* xedit-plugins-engine.c
* This file is part of xedit
*
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib/gi18n.h>
#include "xedit-plugins-engine.h"
#include "xedit-plugin-info-priv.h"
#include "xedit-plugin.h"
#include "xedit-debug.h"
#include "xedit-app.h"
#include "xedit-prefs-manager.h"
#include "xedit-plugin-loader.h"
#include "xedit-object-module.h"
#include "xedit-dirs.h"
#define XEDIT_PLUGINS_ENGINE_BASE_KEY "/apps/xedit/plugins"
#define XEDIT_PLUGINS_ENGINE_KEY XEDIT_PLUGINS_ENGINE_BASE_KEY "/active-plugins"
#define PLUGIN_EXT ".xedit-plugin"
#define LOADER_EXT G_MODULE_SUFFIX
typedef struct
{
XeditPluginLoader *loader;
XeditObjectModule *module;
} LoaderInfo;
/* Signals */
enum
{
ACTIVATE_PLUGIN,
DEACTIVATE_PLUGIN,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE(XeditPluginsEngine, xedit_plugins_engine, G_TYPE_OBJECT)
struct _XeditPluginsEnginePrivate
{
GList *plugin_list;
GHashTable *loaders;
gboolean activate_from_prefs;
};
XeditPluginsEngine *default_engine = NULL;
static void xedit_plugins_engine_activate_plugin_real (XeditPluginsEngine *engine,
XeditPluginInfo *info);
static void xedit_plugins_engine_deactivate_plugin_real (XeditPluginsEngine *engine,
XeditPluginInfo *info);
typedef gboolean (*LoadDirCallback)(XeditPluginsEngine *engine, const gchar *filename, gpointer userdata);
static gboolean
load_dir_real (XeditPluginsEngine *engine,
const gchar *dir,
const gchar *suffix,
LoadDirCallback callback,
gpointer userdata)
{
GError *error = NULL;
GDir *d;
const gchar *dirent;
gboolean ret = TRUE;
g_return_val_if_fail (dir != NULL, TRUE);
xedit_debug_message (DEBUG_PLUGINS, "DIR: %s", dir);
d = g_dir_open (dir, 0, &error);
if (!d)
{
g_warning ("%s", error->message);
g_error_free (error);
return TRUE;
}
while ((dirent = g_dir_read_name (d)))
{
gchar *filename;
if (!g_str_has_suffix (dirent, suffix))
continue;
filename = g_build_filename (dir, dirent, NULL);
ret = callback (engine, filename, userdata);
g_free (filename);
if (!ret)
break;
}
g_dir_close (d);
return ret;
}
static gboolean
load_plugin_info (XeditPluginsEngine *engine,
const gchar *filename,
gpointer userdata)
{
XeditPluginInfo *info;
info = _xedit_plugin_info_new (filename);
if (info == NULL)
return TRUE;
/* If a plugin with this name has already been loaded
* drop this one (user plugins override system plugins) */
if (xedit_plugins_engine_get_plugin_info (engine, xedit_plugin_info_get_module_name (info)) != NULL)
{
xedit_debug_message (DEBUG_PLUGINS, "Two or more plugins named '%s'. "
"Only the first will be considered.\n",
xedit_plugin_info_get_module_name (info));
_xedit_plugin_info_unref (info);
return TRUE;
}
engine->priv->plugin_list = g_list_prepend (engine->priv->plugin_list, info);
xedit_debug_message (DEBUG_PLUGINS, "Plugin %s loaded", info->name);
return TRUE;
}
static void
load_all_plugins (XeditPluginsEngine *engine)
{
gchar *plugin_dir;
const gchar *pdirs_env = NULL;
/* load user plugins */
plugin_dir = xedit_dirs_get_user_plugins_dir ();
if (g_file_test (plugin_dir, G_FILE_TEST_IS_DIR))
{
load_dir_real (engine,
plugin_dir,
PLUGIN_EXT,
load_plugin_info,
NULL);
}
g_free (plugin_dir);
/* load system plugins */
pdirs_env = g_getenv ("XEDIT_PLUGINS_PATH");
xedit_debug_message (DEBUG_PLUGINS, "XEDIT_PLUGINS_PATH=%s", pdirs_env);
if (pdirs_env != NULL)
{
gchar **pdirs;
gint i;
pdirs = g_strsplit (pdirs_env, G_SEARCHPATH_SEPARATOR_S, 0);
for (i = 0; pdirs[i] != NULL; i++)
{
if (!load_dir_real (engine,
pdirs[i],
PLUGIN_EXT,
load_plugin_info,
NULL))
{
break;
}
}
g_strfreev (pdirs);
}
else
{
plugin_dir = xedit_dirs_get_xedit_plugins_dir ();
load_dir_real (engine,
plugin_dir,
PLUGIN_EXT,
load_plugin_info,
NULL);
g_free (plugin_dir);
}
}
static guint
hash_lowercase (gconstpointer data)
{
gchar *lowercase;
guint ret;
lowercase = g_ascii_strdown ((const gchar *)data, -1);
ret = g_str_hash (lowercase);
g_free (lowercase);
return ret;
}
static gboolean
equal_lowercase (gconstpointer a, gconstpointer b)
{
return g_ascii_strcasecmp ((const gchar *)a, (const gchar *)b) == 0;
}
static void
loader_destroy (LoaderInfo *info)
{
if (!info)
return;
if (info->loader)
g_object_unref (info->loader);
g_free (info);
}
static void
add_loader (XeditPluginsEngine *engine,
const gchar *loader_id,
XeditObjectModule *module)
{
LoaderInfo *info;
info = g_new (LoaderInfo, 1);
info->loader = NULL;
info->module = module;
g_hash_table_insert (engine->priv->loaders, g_strdup (loader_id), info);
}
static void
xedit_plugins_engine_init (XeditPluginsEngine *engine)
{
xedit_debug (DEBUG_PLUGINS);
if (!g_module_supported ())
{
g_warning ("xedit is not able to initialize the plugins engine.");
return;
}
engine->priv = G_TYPE_INSTANCE_GET_PRIVATE (engine,
XEDIT_TYPE_PLUGINS_ENGINE,
XeditPluginsEnginePrivate);
load_all_plugins (engine);
/* make sure that the first reactivation will read active plugins
from the prefs */
engine->priv->activate_from_prefs = TRUE;
/* mapping from loadername -> loader object */
engine->priv->loaders = g_hash_table_new_full (hash_lowercase,
equal_lowercase,
(GDestroyNotify)g_free,
(GDestroyNotify)loader_destroy);
}
static void
loader_garbage_collect (const char *id, LoaderInfo *info)
{
if (info->loader)
xedit_plugin_loader_garbage_collect (info->loader);
}
void
xedit_plugins_engine_garbage_collect (XeditPluginsEngine *engine)
{
g_hash_table_foreach (engine->priv->loaders,
(GHFunc) loader_garbage_collect,
NULL);
}
static void
xedit_plugins_engine_finalize (GObject *object)
{
XeditPluginsEngine *engine = XEDIT_PLUGINS_ENGINE (object);
GList *item;
xedit_debug (DEBUG_PLUGINS);
/* Firs deactivate all plugins */
for (item = engine->priv->plugin_list; item; item = item->next)
{
XeditPluginInfo *info = XEDIT_PLUGIN_INFO (item->data);
if (xedit_plugin_info_is_active (info))
xedit_plugins_engine_deactivate_plugin_real (engine, info);
}
/* unref the loaders */
g_hash_table_destroy (engine->priv->loaders);
/* and finally free the infos */
for (item = engine->priv->plugin_list; item; item = item->next)
{
XeditPluginInfo *info = XEDIT_PLUGIN_INFO (item->data);
_xedit_plugin_info_unref (info);
}
g_list_free (engine->priv->plugin_list);
G_OBJECT_CLASS (xedit_plugins_engine_parent_class)->finalize (object);
}
static void
xedit_plugins_engine_class_init (XeditPluginsEngineClass *klass)
{
GType the_type = G_TYPE_FROM_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = xedit_plugins_engine_finalize;
klass->activate_plugin = xedit_plugins_engine_activate_plugin_real;
klass->deactivate_plugin = xedit_plugins_engine_deactivate_plugin_real;
signals[ACTIVATE_PLUGIN] =
g_signal_new ("activate-plugin",
the_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XeditPluginsEngineClass, activate_plugin),
NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE,
1,
XEDIT_TYPE_PLUGIN_INFO | G_SIGNAL_TYPE_STATIC_SCOPE);
signals[DEACTIVATE_PLUGIN] =
g_signal_new ("deactivate-plugin",
the_type,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XeditPluginsEngineClass, deactivate_plugin),
NULL, NULL,
g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE,
1,
XEDIT_TYPE_PLUGIN_INFO | G_SIGNAL_TYPE_STATIC_SCOPE);
g_type_class_add_private (klass, sizeof (XeditPluginsEnginePrivate));
}
static gboolean
load_loader (XeditPluginsEngine *engine,
const gchar *filename,
gpointer data)
{
XeditObjectModule *module;
gchar *base;
gchar *path;
const gchar *id;
GType type;
/* try to load in the module */
path = g_path_get_dirname (filename);
base = g_path_get_basename (filename);
/* for now they are all resident */
module = xedit_object_module_new (base,
path,
"register_xedit_plugin_loader",
TRUE);
g_free (base);
g_free (path);
/* make sure to load the type definition */
if (!g_type_module_use (G_TYPE_MODULE (module)))
{
g_object_unref (module);
g_warning ("Plugin loader module `%s' could not be loaded", filename);
return TRUE;
}
/* get the exported type and check the name as exported by the
* loader interface */
type = xedit_object_module_get_object_type (module);
id = xedit_plugin_loader_type_get_id (type);
add_loader (engine, id, module);
g_type_module_unuse (G_TYPE_MODULE (module));
return TRUE;
}
static void
ensure_loader (LoaderInfo *info)
{
if (info->loader == NULL && info->module != NULL)
{
/* create a new loader object */
XeditPluginLoader *loader;
loader = (XeditPluginLoader *)xedit_object_module_new_object (info->module, NULL);
if (loader == NULL || !XEDIT_IS_PLUGIN_LOADER (loader))
{
g_warning ("Loader object is not a valid XeditPluginLoader instance");
if (loader != NULL && G_IS_OBJECT (loader))
g_object_unref (loader);
}
else
{
info->loader = loader;
}
}
}
static XeditPluginLoader *
get_plugin_loader (XeditPluginsEngine *engine, XeditPluginInfo *info)
{
const gchar *loader_id;
LoaderInfo *loader_info;
loader_id = info->loader;
loader_info = (LoaderInfo *)g_hash_table_lookup (
engine->priv->loaders,
loader_id);
if (loader_info == NULL)
{
gchar *loader_dir;
loader_dir = xedit_dirs_get_xedit_plugin_loaders_dir ();
/* loader could not be found in the hash, try to find it by
scanning */
load_dir_real (engine,
loader_dir,
LOADER_EXT,
(LoadDirCallback)load_loader,
NULL);
g_free (loader_dir);
loader_info = (LoaderInfo *)g_hash_table_lookup (
engine->priv->loaders,
loader_id);
}
if (loader_info == NULL)
{
/* cache non-existent so we don't scan again */
add_loader (engine, loader_id, NULL);
return NULL;
}
ensure_loader (loader_info);
return loader_info->loader;
}
XeditPluginsEngine *
xedit_plugins_engine_get_default (void)
{
if (default_engine != NULL)
return default_engine;
default_engine = XEDIT_PLUGINS_ENGINE (g_object_new (XEDIT_TYPE_PLUGINS_ENGINE, NULL));
g_object_add_weak_pointer (G_OBJECT (default_engine),
(gpointer) &default_engine);
return default_engine;
}
const GList *
xedit_plugins_engine_get_plugin_list (XeditPluginsEngine *engine)
{
xedit_debug (DEBUG_PLUGINS);
return engine->priv->plugin_list;
}
static gint
compare_plugin_info_and_name (XeditPluginInfo *info,
const gchar *module_name)
{
return strcmp (xedit_plugin_info_get_module_name (info), module_name);
}
XeditPluginInfo *
xedit_plugins_engine_get_plugin_info (XeditPluginsEngine *engine,
const gchar *name)
{
GList *l = g_list_find_custom (engine->priv->plugin_list,
name,
(GCompareFunc) compare_plugin_info_and_name);
return l == NULL ? NULL : (XeditPluginInfo *) l->data;
}
static void
save_active_plugin_list (XeditPluginsEngine *engine)
{
GSList *active_plugins = NULL;
GList *l;
for (l = engine->priv->plugin_list; l != NULL; l = l->next)
{
XeditPluginInfo *info = (XeditPluginInfo *) l->data;
if (xedit_plugin_info_is_active (info))
{
active_plugins = g_slist_prepend (active_plugins,
(gpointer)xedit_plugin_info_get_module_name (info));
}
}
xedit_prefs_manager_set_active_plugins (active_plugins);
g_slist_free (active_plugins);
}
static gboolean
load_plugin (XeditPluginsEngine *engine,
XeditPluginInfo *info)
{
XeditPluginLoader *loader;
gchar *path;
if (xedit_plugin_info_is_active (info))
return TRUE;
if (!xedit_plugin_info_is_available (info))
return FALSE;
loader = get_plugin_loader (engine, info);
if (loader == NULL)
{
g_warning ("Could not find loader `%s' for plugin `%s'", info->loader, info->name);
info->available = FALSE;
return FALSE;
}
path = g_path_get_dirname (info->file);
g_return_val_if_fail (path != NULL, FALSE);
info->plugin = xedit_plugin_loader_load (loader, info, path);
g_free (path);
if (info->plugin == NULL)
{
g_warning ("Error loading plugin '%s'", info->name);
info->available = FALSE;
return FALSE;
}
return TRUE;
}
static void
xedit_plugins_engine_activate_plugin_real (XeditPluginsEngine *engine,
XeditPluginInfo *info)
{
const GList *wins;
if (!load_plugin (engine, info))
return;
for (wins = xedit_app_get_windows (xedit_app_get_default ());
wins != NULL;
wins = wins->next)
{
xedit_plugin_activate (info->plugin, XEDIT_WINDOW (wins->data));
}
}
gboolean
xedit_plugins_engine_activate_plugin (XeditPluginsEngine *engine,
XeditPluginInfo *info)
{
xedit_debug (DEBUG_PLUGINS);
g_return_val_if_fail (info != NULL, FALSE);
if (!xedit_plugin_info_is_available (info))
return FALSE;
if (xedit_plugin_info_is_active (info))
return TRUE;
g_signal_emit (engine, signals[ACTIVATE_PLUGIN], 0, info);
if (xedit_plugin_info_is_active (info))
save_active_plugin_list (engine);
return xedit_plugin_info_is_active (info);
}
static void
call_plugin_deactivate (XeditPlugin *plugin,
XeditWindow *window)
{
xedit_plugin_deactivate (plugin, window);
/* ensure update of ui manager, because we suspect it does something
with expected static strings in the type module (when unloaded the
strings don't exist anymore, and ui manager updates in an idle
func) */
gtk_ui_manager_ensure_update (xedit_window_get_ui_manager (window));
}
static void
xedit_plugins_engine_deactivate_plugin_real (XeditPluginsEngine *engine,
XeditPluginInfo *info)
{
const GList *wins;
XeditPluginLoader *loader;
if (!xedit_plugin_info_is_active (info) ||
!xedit_plugin_info_is_available (info))
return;
for (wins = xedit_app_get_windows (xedit_app_get_default ());
wins != NULL;
wins = wins->next)
{
call_plugin_deactivate (info->plugin, XEDIT_WINDOW (wins->data));
}
/* first unref the plugin (the loader still has one) */
g_object_unref (info->plugin);
/* find the loader and tell it to gc and unload the plugin */
loader = get_plugin_loader (engine, info);
xedit_plugin_loader_garbage_collect (loader);
xedit_plugin_loader_unload (loader, info);
info->plugin = NULL;
}
gboolean
xedit_plugins_engine_deactivate_plugin (XeditPluginsEngine *engine,
XeditPluginInfo *info)
{
xedit_debug (DEBUG_PLUGINS);
g_return_val_if_fail (info != NULL, FALSE);
if (!xedit_plugin_info_is_active (info))
return TRUE;
g_signal_emit (engine, signals[DEACTIVATE_PLUGIN], 0, info);
if (!xedit_plugin_info_is_active (info))
save_active_plugin_list (engine);
return !xedit_plugin_info_is_active (info);
}
void
xedit_plugins_engine_activate_plugins (XeditPluginsEngine *engine,
XeditWindow *window)
{
GSList *active_plugins = NULL;
GList *pl;
xedit_debug (DEBUG_PLUGINS);
g_return_if_fail (XEDIT_IS_PLUGINS_ENGINE (engine));
g_return_if_fail (XEDIT_IS_WINDOW (window));
/* the first time, we get the 'active' plugins from GSettings */
if (engine->priv->activate_from_prefs)
{
active_plugins = xedit_prefs_manager_get_active_plugins ();
}
for (pl = engine->priv->plugin_list; pl; pl = pl->next)
{
XeditPluginInfo *info = (XeditPluginInfo*)pl->data;
if (engine->priv->activate_from_prefs &&
g_slist_find_custom (active_plugins,
xedit_plugin_info_get_module_name (info),
(GCompareFunc)strcmp) == NULL)
continue;
/* If plugin is not active, don't try to activate/load it */
if (!engine->priv->activate_from_prefs &&
!xedit_plugin_info_is_active (info))
continue;
if (load_plugin (engine, info))
xedit_plugin_activate (info->plugin,
window);
}
if (engine->priv->activate_from_prefs)
{
g_slist_foreach (active_plugins, (GFunc) g_free, NULL);
g_slist_free (active_plugins);
engine->priv->activate_from_prefs = FALSE;
}
xedit_debug_message (DEBUG_PLUGINS, "End");
/* also call update_ui after activation */
xedit_plugins_engine_update_plugins_ui (engine, window);
}
void
xedit_plugins_engine_deactivate_plugins (XeditPluginsEngine *engine,
XeditWindow *window)
{
GList *pl;
xedit_debug (DEBUG_PLUGINS);
g_return_if_fail (XEDIT_IS_PLUGINS_ENGINE (engine));
g_return_if_fail (XEDIT_IS_WINDOW (window));
for (pl = engine->priv->plugin_list; pl; pl = pl->next)
{
XeditPluginInfo *info = (XeditPluginInfo*)pl->data;
/* check if the plugin is actually active */
if (!xedit_plugin_info_is_active (info))
continue;
/* call deactivate for the plugin for this window */
xedit_plugin_deactivate (info->plugin, window);
}
xedit_debug_message (DEBUG_PLUGINS, "End");
}
void
xedit_plugins_engine_update_plugins_ui (XeditPluginsEngine *engine,
XeditWindow *window)
{
GList *pl;
xedit_debug (DEBUG_PLUGINS);
g_return_if_fail (XEDIT_IS_PLUGINS_ENGINE (engine));
g_return_if_fail (XEDIT_IS_WINDOW (window));
/* call update_ui for all active plugins */
for (pl = engine->priv->plugin_list; pl; pl = pl->next)
{
XeditPluginInfo *info = (XeditPluginInfo*)pl->data;
if (!xedit_plugin_info_is_active (info))
continue;
xedit_debug_message (DEBUG_PLUGINS, "Updating UI of %s", info->name);
xedit_plugin_update_ui (info->plugin, window);
}
}
void
xedit_plugins_engine_configure_plugin (XeditPluginsEngine *engine,
XeditPluginInfo *info,
GtkWindow *parent)
{
GtkWidget *conf_dlg;
GtkWindowGroup *wg;
xedit_debug (DEBUG_PLUGINS);
g_return_if_fail (info != NULL);
conf_dlg = xedit_plugin_create_configure_dialog (info->plugin);
g_return_if_fail (conf_dlg != NULL);
gtk_window_set_transient_for (GTK_WINDOW (conf_dlg),
parent);
wg = gtk_window_get_group (parent);
if (wg == NULL)
{
wg = gtk_window_group_new ();
gtk_window_group_add_window (wg, parent);
}
gtk_window_group_add_window (wg,
GTK_WINDOW (conf_dlg));
gtk_window_set_modal (GTK_WINDOW (conf_dlg), TRUE);
gtk_widget_show (conf_dlg);
}
void
xedit_plugins_engine_active_plugins_changed (XeditPluginsEngine *engine)
{
gboolean to_activate;
GSList *active_plugins;
GList *pl;
xedit_debug (DEBUG_PLUGINS);
active_plugins = xedit_prefs_manager_get_active_plugins ();
for (pl = engine->priv->plugin_list; pl; pl = pl->next)
{
XeditPluginInfo *info = (XeditPluginInfo*)pl->data;
if (!xedit_plugin_info_is_available (info))
continue;
to_activate = (g_slist_find_custom (active_plugins,
xedit_plugin_info_get_module_name (info),
(GCompareFunc)strcmp) != NULL);
if (!xedit_plugin_info_is_active (info) && to_activate)
g_signal_emit (engine, signals[ACTIVATE_PLUGIN], 0, info);
else if (xedit_plugin_info_is_active (info) && !to_activate)
g_signal_emit (engine, signals[DEACTIVATE_PLUGIN], 0, info);
}
g_slist_foreach (active_plugins, (GFunc) g_free, NULL);
g_slist_free (active_plugins);
}
void
xedit_plugins_engine_rescan_plugins (XeditPluginsEngine *engine)
{
xedit_debug (DEBUG_PLUGINS);
load_all_plugins (engine);
}

View File

@@ -0,0 +1,107 @@
/*
* xedit-plugins-engine.h
* This file is part of xedit
*
* Copyright (C) 2002-2005 - Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*/
#ifndef __XEDIT_PLUGINS_ENGINE_H__
#define __XEDIT_PLUGINS_ENGINE_H__
#include <glib.h>
#include "xedit-window.h"
#include "xedit-plugin-info.h"
#include "xedit-plugin.h"
G_BEGIN_DECLS
#define XEDIT_TYPE_PLUGINS_ENGINE (xedit_plugins_engine_get_type ())
#define XEDIT_PLUGINS_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XEDIT_TYPE_PLUGINS_ENGINE, XeditPluginsEngine))
#define XEDIT_PLUGINS_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XEDIT_TYPE_PLUGINS_ENGINE, XeditPluginsEngineClass))
#define XEDIT_IS_PLUGINS_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XEDIT_TYPE_PLUGINS_ENGINE))
#define XEDIT_IS_PLUGINS_ENGINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XEDIT_TYPE_PLUGINS_ENGINE))
#define XEDIT_PLUGINS_ENGINE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XEDIT_TYPE_PLUGINS_ENGINE, XeditPluginsEngineClass))
typedef struct _XeditPluginsEngine XeditPluginsEngine;
typedef struct _XeditPluginsEnginePrivate XeditPluginsEnginePrivate;
struct _XeditPluginsEngine
{
GObject parent;
XeditPluginsEnginePrivate *priv;
};
typedef struct _XeditPluginsEngineClass XeditPluginsEngineClass;
struct _XeditPluginsEngineClass
{
GObjectClass parent_class;
void (* activate_plugin) (XeditPluginsEngine *engine,
XeditPluginInfo *info);
void (* deactivate_plugin) (XeditPluginsEngine *engine,
XeditPluginInfo *info);
};
GType xedit_plugins_engine_get_type (void) G_GNUC_CONST;
XeditPluginsEngine *xedit_plugins_engine_get_default (void);
void xedit_plugins_engine_garbage_collect (XeditPluginsEngine *engine);
const GList *xedit_plugins_engine_get_plugin_list (XeditPluginsEngine *engine);
XeditPluginInfo *xedit_plugins_engine_get_plugin_info (XeditPluginsEngine *engine,
const gchar *name);
/* plugin load and unloading (overall, for all windows) */
gboolean xedit_plugins_engine_activate_plugin (XeditPluginsEngine *engine,
XeditPluginInfo *info);
gboolean xedit_plugins_engine_deactivate_plugin (XeditPluginsEngine *engine,
XeditPluginInfo *info);
void xedit_plugins_engine_configure_plugin (XeditPluginsEngine *engine,
XeditPluginInfo *info,
GtkWindow *parent);
/* plugin activation/deactivation per window, private to XeditWindow */
void xedit_plugins_engine_activate_plugins (XeditPluginsEngine *engine,
XeditWindow *window);
void xedit_plugins_engine_deactivate_plugins (XeditPluginsEngine *engine,
XeditWindow *window);
void xedit_plugins_engine_update_plugins_ui (XeditPluginsEngine *engine,
XeditWindow *window);
/* private for GSettings notification */
void xedit_plugins_engine_active_plugins_changed
(XeditPluginsEngine *engine);
void xedit_plugins_engine_rescan_plugins (XeditPluginsEngine *engine);
G_END_DECLS
#endif /* __XEDIT_PLUGINS_ENGINE_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,84 @@
/*
* xedit-prefs-manager-app.h
* This file is part of xedit
*
* Copyright (C) 2002-2005 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002-2005. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*
* $Id$
*
*/
#ifndef __XEDIT_PREFS_MANAGER_APP_H__
#define __XEDIT_PREFS_MANAGER_APP_H__
#include <glib.h>
#include <xedit/xedit-prefs-manager.h>
/** LIFE CYCLE MANAGEMENT FUNCTIONS **/
gboolean xedit_prefs_manager_app_init (void);
/* This function must be called before exiting xedit */
void xedit_prefs_manager_app_shutdown (void);
/* Window state */
gint xedit_prefs_manager_get_window_state (void);
void xedit_prefs_manager_set_window_state (gint ws);
gboolean xedit_prefs_manager_window_state_can_set (void);
/* Window size */
void xedit_prefs_manager_get_window_size (gint *width,
gint *height);
void xedit_prefs_manager_get_default_window_size (gint *width,
gint *height);
void xedit_prefs_manager_set_window_size (gint width,
gint height);
gboolean xedit_prefs_manager_window_size_can_set (void);
/* Side panel */
gint xedit_prefs_manager_get_side_panel_size (void);
gint xedit_prefs_manager_get_default_side_panel_size(void);
void xedit_prefs_manager_set_side_panel_size (gint ps);
gboolean xedit_prefs_manager_side_panel_size_can_set (void);
gint xedit_prefs_manager_get_side_panel_active_page (void);
void xedit_prefs_manager_set_side_panel_active_page (gint id);
gboolean xedit_prefs_manager_side_panel_active_page_can_set (void);
/* Bottom panel */
gint xedit_prefs_manager_get_bottom_panel_size (void);
gint xedit_prefs_manager_get_default_bottom_panel_size(void);
void xedit_prefs_manager_set_bottom_panel_size (gint ps);
gboolean xedit_prefs_manager_bottom_panel_size_can_set (void);
gint xedit_prefs_manager_get_bottom_panel_active_page (void);
void xedit_prefs_manager_set_bottom_panel_active_page (gint id);
gboolean xedit_prefs_manager_bottom_panel_active_page_can_set (void);
/* File filter */
gint xedit_prefs_manager_get_active_file_filter (void);
void xedit_prefs_manager_set_active_file_filter (gint id);
gboolean xedit_prefs_manager_active_file_filter_can_set (void);
#endif /* __XEDIT_PREFS_MANAGER_APP_H__ */

View File

@@ -0,0 +1,47 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xedit-prefs-manager-private.h
* This file is part of xedit
*
* Copyright (C) 2002 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*/
#ifndef __XEDIT_PREFS_MANAGER_PRIVATE_H__
#define __XEDIT_PREFS_MANAGER_PRIVATE_H__
#include <gio/gio.h>
typedef struct _XeditPrefsManager XeditPrefsManager;
struct _XeditPrefsManager {
GSettings *settings;
GSettings *lockdown_settings;
GSettings *interface_settings;
};
extern XeditPrefsManager *xedit_prefs_manager;
#endif /* __XEDIT_PREFS_MANAGER_PRIVATE_H__ */

941
xedit/xedit-prefs-manager.c Normal file
View File

@@ -0,0 +1,941 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xedit-prefs-manager.c
* This file is part of xedit
*
* Copyright (C) 2002 Paolo Maggi
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xedit Team, 2002. See the AUTHORS file for a
* list of people on the xedit Team.
* See the ChangeLog files for a list of changes.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
#include "xedit-prefs-manager.h"
#include "xedit-prefs-manager-private.h"
#include "xedit-debug.h"
#include "xedit-encodings.h"
#include "xedit-utils.h"
#define DEFINE_BOOL_PREF(name, key) gboolean \
xedit_prefs_manager_get_ ## name (void) \
{ \
xedit_debug (DEBUG_PREFS); \
\
return xedit_prefs_manager_get_bool (key); \
} \
\
void \
xedit_prefs_manager_set_ ## name (gboolean v) \
{ \
xedit_debug (DEBUG_PREFS); \
\
xedit_prefs_manager_set_bool (key, \
v); \
} \
\
gboolean \
xedit_prefs_manager_ ## name ## _can_set (void) \
{ \
xedit_debug (DEBUG_PREFS); \
\
return xedit_prefs_manager_key_is_writable (key); \
}
#define DEFINE_INT_PREF(name, key) gint \
xedit_prefs_manager_get_ ## name (void) \
{ \
xedit_debug (DEBUG_PREFS); \
\
return xedit_prefs_manager_get_int (key); \
} \
\
void \
xedit_prefs_manager_set_ ## name (gint v) \
{ \
xedit_debug (DEBUG_PREFS); \
\
xedit_prefs_manager_set_int (key, \
v); \
} \
\
gboolean \
xedit_prefs_manager_ ## name ## _can_set (void) \
{ \
xedit_debug (DEBUG_PREFS); \
\
return xedit_prefs_manager_key_is_writable (key); \
}
#define DEFINE_STRING_PREF(name, key) gchar* \
xedit_prefs_manager_get_ ## name (void) \
{ \
xedit_debug (DEBUG_PREFS); \
\
return xedit_prefs_manager_get_string (key); \
} \
\
void \
xedit_prefs_manager_set_ ## name (const gchar* v) \
{ \
xedit_debug (DEBUG_PREFS); \
\
xedit_prefs_manager_set_string (key, \
v); \
} \
\
gboolean \
xedit_prefs_manager_ ## name ## _can_set (void) \
{ \
xedit_debug (DEBUG_PREFS); \
\
return xedit_prefs_manager_key_is_writable (key); \
}
XeditPrefsManager *xedit_prefs_manager = NULL;
static GtkWrapMode get_wrap_mode_from_string (const gchar* str);
static gboolean xedit_prefs_manager_get_bool (const gchar* key);
static gint xedit_prefs_manager_get_int (const gchar* key);
static gchar *xedit_prefs_manager_get_string (const gchar* key);
gboolean
xedit_prefs_manager_init (void)
{
xedit_debug (DEBUG_PREFS);
if (xedit_prefs_manager == NULL)
{
xedit_prefs_manager = g_new0 (XeditPrefsManager, 1);
xedit_prefs_manager->settings = g_settings_new (XEDIT_SCHEMA);
xedit_prefs_manager->lockdown_settings = g_settings_new (GPM_LOCKDOWN_SCHEMA);
xedit_prefs_manager->interface_settings = g_settings_new (GPM_INTERFACE_SCHEMA);
}
return xedit_prefs_manager != NULL;
}
void
xedit_prefs_manager_shutdown (void)
{
xedit_debug (DEBUG_PREFS);
g_return_if_fail (xedit_prefs_manager != NULL);
g_object_unref (xedit_prefs_manager->settings);
xedit_prefs_manager->settings = NULL;
g_object_unref (xedit_prefs_manager->lockdown_settings);
xedit_prefs_manager->lockdown_settings = NULL;
g_object_unref (xedit_prefs_manager->interface_settings);
xedit_prefs_manager->interface_settings = NULL;
}
static gboolean
xedit_prefs_manager_get_bool (const gchar* key)
{
xedit_debug (DEBUG_PREFS);
return g_settings_get_boolean (xedit_prefs_manager->settings, key);
}
static gint
xedit_prefs_manager_get_int (const gchar* key)
{
xedit_debug (DEBUG_PREFS);
return g_settings_get_int (xedit_prefs_manager->settings, key);
}
static gchar *
xedit_prefs_manager_get_string (const gchar* key)
{
xedit_debug (DEBUG_PREFS);
return g_settings_get_string (xedit_prefs_manager->settings, key);
}
static void
xedit_prefs_manager_set_bool (const gchar* key, gboolean value)
{
xedit_debug (DEBUG_PREFS);
g_return_if_fail (g_settings_is_writable (
xedit_prefs_manager->settings, key));
g_settings_set_boolean (xedit_prefs_manager->settings, key, value);
}
static void
xedit_prefs_manager_set_int (const gchar* key, gint value)
{
xedit_debug (DEBUG_PREFS);
g_return_if_fail (g_settings_is_writable (
xedit_prefs_manager->settings, key));
g_settings_set_int (xedit_prefs_manager->settings, key, value);
}
static void
xedit_prefs_manager_set_string (const gchar* key, const gchar* value)
{
xedit_debug (DEBUG_PREFS);
g_return_if_fail (value != NULL);
g_return_if_fail (g_settings_is_writable (
xedit_prefs_manager->settings, key));
g_settings_set_string (xedit_prefs_manager->settings, key, value);
}
static gboolean
xedit_prefs_manager_key_is_writable (const gchar* key)
{
xedit_debug (DEBUG_PREFS);
g_return_val_if_fail (xedit_prefs_manager != NULL, FALSE);
g_return_val_if_fail (xedit_prefs_manager->settings != NULL, FALSE);
return g_settings_is_writable (xedit_prefs_manager->settings, key);
}
/* Use default font */
DEFINE_BOOL_PREF (use_default_font,
GPM_USE_DEFAULT_FONT)
/* Editor font */
DEFINE_STRING_PREF (editor_font,
GPM_EDITOR_FONT)
/* System font */
gchar *
xedit_prefs_manager_get_system_font (void)
{
xedit_debug (DEBUG_PREFS);
return g_settings_get_string (xedit_prefs_manager->interface_settings,
GPM_SYSTEM_FONT);
}
/* Create backup copy */
DEFINE_BOOL_PREF (create_backup_copy,
GPM_CREATE_BACKUP_COPY)
/* Auto save */
DEFINE_BOOL_PREF (auto_save,
GPM_AUTO_SAVE)
/* Auto save interval */
DEFINE_INT_PREF (auto_save_interval,
GPM_AUTO_SAVE_INTERVAL)
/* Undo actions limit: if < 1 then no limits */
DEFINE_INT_PREF (undo_actions_limit,
GPM_UNDO_ACTIONS_LIMIT)
static GtkWrapMode
get_wrap_mode_from_string (const gchar* str)
{
GtkWrapMode res;
g_return_val_if_fail (str != NULL, GTK_WRAP_WORD);
if (strcmp (str, "GTK_WRAP_NONE") == 0)
res = GTK_WRAP_NONE;
else
{
if (strcmp (str, "GTK_WRAP_CHAR") == 0)
res = GTK_WRAP_CHAR;
else
res = GTK_WRAP_WORD;
}
return res;
}
/* Wrap mode */
GtkWrapMode
xedit_prefs_manager_get_wrap_mode (void)
{
gchar *str;
GtkWrapMode res;
xedit_debug (DEBUG_PREFS);
str = xedit_prefs_manager_get_string (GPM_WRAP_MODE);
res = get_wrap_mode_from_string (str);
g_free (str);
return res;
}
void
xedit_prefs_manager_set_wrap_mode (GtkWrapMode wp)
{
const gchar * str;
xedit_debug (DEBUG_PREFS);
switch (wp)
{
case GTK_WRAP_NONE:
str = "GTK_WRAP_NONE";
break;
case GTK_WRAP_CHAR:
str = "GTK_WRAP_CHAR";
break;
default: /* GTK_WRAP_WORD */
str = "GTK_WRAP_WORD";
}
xedit_prefs_manager_set_string (GPM_WRAP_MODE,
str);
}
gboolean
xedit_prefs_manager_wrap_mode_can_set (void)
{
xedit_debug (DEBUG_PREFS);
return xedit_prefs_manager_key_is_writable (GPM_WRAP_MODE);
}
/* Tabs size */
DEFINE_INT_PREF (tabs_size,
GPM_TABS_SIZE)
/* Insert spaces */
DEFINE_BOOL_PREF (insert_spaces,
GPM_INSERT_SPACES)
/* Auto indent */
DEFINE_BOOL_PREF (auto_indent,
GPM_AUTO_INDENT)
/* Display line numbers */
DEFINE_BOOL_PREF (display_line_numbers,
GPM_DISPLAY_LINE_NUMBERS)
/* Toolbar visibility */
DEFINE_BOOL_PREF (toolbar_visible,
GPM_TOOLBAR_VISIBLE)
/* Toolbar suttons style */
XeditToolbarSetting
xedit_prefs_manager_get_toolbar_buttons_style (void)
{
gchar *str;
XeditToolbarSetting res;
xedit_debug (DEBUG_PREFS);
str = xedit_prefs_manager_get_string (GPM_TOOLBAR_BUTTONS_STYLE);
if (strcmp (str, "XEDIT_TOOLBAR_ICONS") == 0)
res = XEDIT_TOOLBAR_ICONS;
else
{
if (strcmp (str, "XEDIT_TOOLBAR_ICONS_AND_TEXT") == 0)
res = XEDIT_TOOLBAR_ICONS_AND_TEXT;
else
{
if (strcmp (str, "XEDIT_TOOLBAR_ICONS_BOTH_HORIZ") == 0)
res = XEDIT_TOOLBAR_ICONS_BOTH_HORIZ;
else
res = XEDIT_TOOLBAR_SYSTEM;
}
}
g_free (str);
return res;
}
void
xedit_prefs_manager_set_toolbar_buttons_style (XeditToolbarSetting tbs)
{
const gchar * str;
xedit_debug (DEBUG_PREFS);
switch (tbs)
{
case XEDIT_TOOLBAR_ICONS:
str = "XEDIT_TOOLBAR_ICONS";
break;
case XEDIT_TOOLBAR_ICONS_AND_TEXT:
str = "XEDIT_TOOLBAR_ICONS_AND_TEXT";
break;
case XEDIT_TOOLBAR_ICONS_BOTH_HORIZ:
str = "XEDIT_TOOLBAR_ICONS_BOTH_HORIZ";
break;
default: /* XEDIT_TOOLBAR_SYSTEM */
str = "XEDIT_TOOLBAR_SYSTEM";
}
xedit_prefs_manager_set_string (GPM_TOOLBAR_BUTTONS_STYLE,
str);
}
gboolean
xedit_prefs_manager_toolbar_buttons_style_can_set (void)
{
xedit_debug (DEBUG_PREFS);
return xedit_prefs_manager_key_is_writable (GPM_TOOLBAR_BUTTONS_STYLE);
}
/* Statusbar visiblity */
DEFINE_BOOL_PREF (statusbar_visible,
GPM_STATUSBAR_VISIBLE)
/* Side Pane visiblity */
DEFINE_BOOL_PREF (side_pane_visible,
GPM_SIDE_PANE_VISIBLE)
/* Bottom Panel visiblity */
DEFINE_BOOL_PREF (bottom_panel_visible,
GPM_BOTTOM_PANEL_VISIBLE)
/* Print syntax highlighting */
DEFINE_BOOL_PREF (print_syntax_hl,
GPM_PRINT_SYNTAX)
/* Print header */
DEFINE_BOOL_PREF (print_header,
GPM_PRINT_HEADER)
/* Print Wrap mode */
GtkWrapMode
xedit_prefs_manager_get_print_wrap_mode (void)
{
gchar *str;
GtkWrapMode res;
xedit_debug (DEBUG_PREFS);
str = xedit_prefs_manager_get_string (GPM_PRINT_WRAP_MODE);
if (strcmp (str, "GTK_WRAP_NONE") == 0)
res = GTK_WRAP_NONE;
else
{
if (strcmp (str, "GTK_WRAP_WORD") == 0)
res = GTK_WRAP_WORD;
else
res = GTK_WRAP_CHAR;
}
g_free (str);
return res;
}
void
xedit_prefs_manager_set_print_wrap_mode (GtkWrapMode pwp)
{
const gchar *str;
xedit_debug (DEBUG_PREFS);
switch (pwp)
{
case GTK_WRAP_NONE:
str = "GTK_WRAP_NONE";
break;
case GTK_WRAP_WORD:
str = "GTK_WRAP_WORD";
break;
default: /* GTK_WRAP_CHAR */
str = "GTK_WRAP_CHAR";
}
xedit_prefs_manager_set_string (GPM_PRINT_WRAP_MODE, str);
}
gboolean
xedit_prefs_manager_print_wrap_mode_can_set (void)
{
xedit_debug (DEBUG_PREFS);
return xedit_prefs_manager_key_is_writable (GPM_PRINT_WRAP_MODE);
}
/* Print line numbers */
DEFINE_INT_PREF (print_line_numbers,
GPM_PRINT_LINE_NUMBERS)
/* Printing fonts */
DEFINE_STRING_PREF (print_font_body,
GPM_PRINT_FONT_BODY)
gchar *
xedit_prefs_manager_get_default_string_value (const gchar *key)
{
gchar *font = NULL;
g_settings_delay (xedit_prefs_manager->settings);
g_settings_reset (xedit_prefs_manager->settings, key);
font = g_settings_get_string (xedit_prefs_manager->settings, key);
g_settings_revert (xedit_prefs_manager->settings);
return font;
}
gchar *
xedit_prefs_manager_get_default_print_font_body (void)
{
return xedit_prefs_manager_get_default_string_value (GPM_PRINT_FONT_BODY);
}
DEFINE_STRING_PREF (print_font_header,
GPM_PRINT_FONT_HEADER)
gchar *
xedit_prefs_manager_get_default_print_font_header (void)
{
return xedit_prefs_manager_get_default_string_value (GPM_PRINT_FONT_HEADER);
}
DEFINE_STRING_PREF (print_font_numbers,
GPM_PRINT_FONT_NUMBERS)
gchar *
xedit_prefs_manager_get_default_print_font_numbers (void)
{
return xedit_prefs_manager_get_default_string_value (GPM_PRINT_FONT_NUMBERS);
}
/* Max number of files in "Recent Files" menu.
* This is configurable only using gsettings, dconf or dconf-editor
*/
gint
xedit_prefs_manager_get_max_recents (void)
{
xedit_debug (DEBUG_PREFS);
return xedit_prefs_manager_get_int (GPM_MAX_RECENTS);
}
/* GSettings/GSList utility functions from mate-panel */
GSList*
xedit_prefs_manager_get_gslist (GSettings *settings, const gchar *key)
{
gchar **array;
GSList *list = NULL;
gint i;
array = g_settings_get_strv (settings, key);
if (array != NULL) {
for (i = 0; array[i]; i++) {
list = g_slist_append (list, g_strdup (array[i]));
}
}
g_strfreev (array);
return list;
}
void
xedit_prefs_manager_set_gslist (GSettings *settings, const gchar *key, GSList *list)
{
GArray *array;
GSList *l;
array = g_array_new (TRUE, TRUE, sizeof (gchar *));
for (l = list; l; l = l->next) {
array = g_array_append_val (array, l->data);
}
g_settings_set_strv (settings, key, (const gchar **) array->data);
g_array_free (array, TRUE);
}
/* Encodings */
static gboolean
data_exists (GSList *list,
const gpointer data)
{
while (list != NULL)
{
if (list->data == data)
return TRUE;
list = g_slist_next (list);
}
return FALSE;
}
GSList *
xedit_prefs_manager_get_auto_detected_encodings (void)
{
GSList *strings;
GSList *res = NULL;
xedit_debug (DEBUG_PREFS);
g_return_val_if_fail (xedit_prefs_manager != NULL, NULL);
g_return_val_if_fail (xedit_prefs_manager->settings != NULL, NULL);
strings = xedit_prefs_manager_get_gslist (xedit_prefs_manager->settings, GPM_AUTO_DETECTED_ENCODINGS);
if (strings != NULL)
{
GSList *tmp;
const XeditEncoding *enc;
tmp = strings;
while (tmp)
{
const char *charset = tmp->data;
if (strcmp (charset, "CURRENT") == 0)
g_get_charset (&charset);
g_return_val_if_fail (charset != NULL, NULL);
enc = xedit_encoding_get_from_charset (charset);
if (enc != NULL)
{
if (!data_exists (res, (gpointer)enc))
res = g_slist_prepend (res, (gpointer)enc);
}
tmp = g_slist_next (tmp);
}
g_slist_foreach (strings, (GFunc) g_free, NULL);
g_slist_free (strings);
res = g_slist_reverse (res);
}
xedit_debug_message (DEBUG_PREFS, "Done");
return res;
}
GSList *
xedit_prefs_manager_get_shown_in_menu_encodings (void)
{
GSList *strings;
GSList *res = NULL;
xedit_debug (DEBUG_PREFS);
g_return_val_if_fail (xedit_prefs_manager != NULL, NULL);
g_return_val_if_fail (xedit_prefs_manager->settings != NULL, NULL);
strings = xedit_prefs_manager_get_gslist (xedit_prefs_manager->settings, GPM_SHOWN_IN_MENU_ENCODINGS);
if (strings != NULL)
{
GSList *tmp;
const XeditEncoding *enc;
tmp = strings;
while (tmp)
{
const char *charset = tmp->data;
if (strcmp (charset, "CURRENT") == 0)
g_get_charset (&charset);
g_return_val_if_fail (charset != NULL, NULL);
enc = xedit_encoding_get_from_charset (charset);
if (enc != NULL)
{
if (!data_exists (res, (gpointer)enc))
res = g_slist_prepend (res, (gpointer)enc);
}
tmp = g_slist_next (tmp);
}
g_slist_foreach (strings, (GFunc) g_free, NULL);
g_slist_free (strings);
res = g_slist_reverse (res);
}
return res;
}
void
xedit_prefs_manager_set_shown_in_menu_encodings (const GSList *encs)
{
GSList *list = NULL;
g_return_if_fail (xedit_prefs_manager != NULL);
g_return_if_fail (xedit_prefs_manager->settings != NULL);
g_return_if_fail (xedit_prefs_manager_shown_in_menu_encodings_can_set ());
while (encs != NULL)
{
const XeditEncoding *enc;
const gchar *charset;
enc = (const XeditEncoding *)encs->data;
charset = xedit_encoding_get_charset (enc);
g_return_if_fail (charset != NULL);
list = g_slist_prepend (list, (gpointer)charset);
encs = g_slist_next (encs);
}
list = g_slist_reverse (list);
xedit_prefs_manager_set_gslist (xedit_prefs_manager->settings, GPM_SHOWN_IN_MENU_ENCODINGS, list);
g_slist_free (list);
}
gboolean
xedit_prefs_manager_shown_in_menu_encodings_can_set (void)
{
xedit_debug (DEBUG_PREFS);
return xedit_prefs_manager_key_is_writable (GPM_SHOWN_IN_MENU_ENCODINGS);
}
/* Highlight current line */
DEFINE_BOOL_PREF (highlight_current_line,
GPM_HIGHLIGHT_CURRENT_LINE)
/* Highlight matching bracket */
DEFINE_BOOL_PREF (bracket_matching,
GPM_BRACKET_MATCHING)
/* Display Right Margin */
DEFINE_BOOL_PREF (display_right_margin,
GPM_DISPLAY_RIGHT_MARGIN)
/* Right Margin Position */
DEFINE_INT_PREF (right_margin_position,
GPM_RIGHT_MARGIN_POSITION)
static GtkSourceSmartHomeEndType
get_smart_home_end_from_string (const gchar *str)
{
GtkSourceSmartHomeEndType res;
g_return_val_if_fail (str != NULL, GTK_SOURCE_SMART_HOME_END_AFTER);
if (strcmp (str, "DISABLED") == 0)
res = GTK_SOURCE_SMART_HOME_END_DISABLED;
else if (strcmp (str, "BEFORE") == 0)
res = GTK_SOURCE_SMART_HOME_END_BEFORE;
else if (strcmp (str, "ALWAYS") == 0)
res = GTK_SOURCE_SMART_HOME_END_ALWAYS;
else
res = GTK_SOURCE_SMART_HOME_END_AFTER;
return res;
}
GtkSourceSmartHomeEndType
xedit_prefs_manager_get_smart_home_end (void)
{
gchar *str;
GtkSourceSmartHomeEndType res;
xedit_debug (DEBUG_PREFS);
str = xedit_prefs_manager_get_string (GPM_SMART_HOME_END);
res = get_smart_home_end_from_string (str);
g_free (str);
return res;
}
void
xedit_prefs_manager_set_smart_home_end (GtkSourceSmartHomeEndType smart_he)
{
const gchar *str;
xedit_debug (DEBUG_PREFS);
switch (smart_he)
{
case GTK_SOURCE_SMART_HOME_END_DISABLED:
str = "DISABLED";
break;
case GTK_SOURCE_SMART_HOME_END_BEFORE:
str = "BEFORE";
break;
case GTK_SOURCE_SMART_HOME_END_ALWAYS:
str = "ALWAYS";
break;
default: /* GTK_SOURCE_SMART_HOME_END_AFTER */
str = "AFTER";
}
xedit_prefs_manager_set_string (GPM_WRAP_MODE, str);
}
gboolean
xedit_prefs_manager_smart_home_end_can_set (void)
{
xedit_debug (DEBUG_PREFS);
return xedit_prefs_manager_key_is_writable (GPM_SMART_HOME_END);
}
/* Enable syntax highlighting */
DEFINE_BOOL_PREF (enable_syntax_highlighting,
GPM_SYNTAX_HL_ENABLE)
/* Enable search highlighting */
DEFINE_BOOL_PREF (enable_search_highlighting,
GPM_SEARCH_HIGHLIGHTING_ENABLE)
/* Source style scheme */
DEFINE_STRING_PREF (source_style_scheme,
GPM_SOURCE_STYLE_SCHEME)
GSList *
xedit_prefs_manager_get_writable_vfs_schemes (void)
{
GSList *strings;
xedit_debug (DEBUG_PREFS);
g_return_val_if_fail (xedit_prefs_manager != NULL, NULL);
g_return_val_if_fail (xedit_prefs_manager->settings != NULL, NULL);
strings = xedit_prefs_manager_get_gslist (xedit_prefs_manager->settings, GPM_WRITABLE_VFS_SCHEMES);
/* The 'file' scheme is writable by default. */
strings = g_slist_prepend (strings, g_strdup ("file"));
xedit_debug_message (DEBUG_PREFS, "Done");
return strings;
}
gboolean
xedit_prefs_manager_get_restore_cursor_position (void)
{
xedit_debug (DEBUG_PREFS);
return xedit_prefs_manager_get_bool (GPM_RESTORE_CURSOR_POSITION);
}
/* Plugins: we just store/return a list of strings, all the magic has to
* happen in the plugin engine */
GSList *
xedit_prefs_manager_get_active_plugins (void)
{
GSList *plugins;
xedit_debug (DEBUG_PREFS);
g_return_val_if_fail (xedit_prefs_manager != NULL, NULL);
g_return_val_if_fail (xedit_prefs_manager->settings != NULL, NULL);
plugins = xedit_prefs_manager_get_gslist (xedit_prefs_manager->settings, GPM_ACTIVE_PLUGINS);
return plugins;
}
void
xedit_prefs_manager_set_active_plugins (const GSList *plugins)
{
g_return_if_fail (xedit_prefs_manager != NULL);
g_return_if_fail (xedit_prefs_manager->settings != NULL);
g_return_if_fail (xedit_prefs_manager_active_plugins_can_set ());
xedit_prefs_manager_set_gslist (xedit_prefs_manager->settings, GPM_ACTIVE_PLUGINS, (GSList *) plugins);
}
gboolean
xedit_prefs_manager_active_plugins_can_set (void)
{
xedit_debug (DEBUG_PREFS);
return xedit_prefs_manager_key_is_writable (GPM_ACTIVE_PLUGINS);
}
/* Global Lockdown */
XeditLockdownMask
xedit_prefs_manager_get_lockdown (void)
{
guint lockdown = 0;
if (g_settings_get_boolean (xedit_prefs_manager->lockdown_settings, GPM_LOCKDOWN_COMMAND_LINE))
lockdown |= XEDIT_LOCKDOWN_COMMAND_LINE;
if (g_settings_get_boolean (xedit_prefs_manager->lockdown_settings, GPM_LOCKDOWN_PRINTING))
lockdown |= XEDIT_LOCKDOWN_PRINTING;
if (g_settings_get_boolean (xedit_prefs_manager->lockdown_settings, GPM_LOCKDOWN_PRINT_SETUP))
lockdown |= XEDIT_LOCKDOWN_PRINT_SETUP;
if (g_settings_get_boolean (xedit_prefs_manager->lockdown_settings, GPM_LOCKDOWN_SAVE_TO_DISK))
lockdown |= XEDIT_LOCKDOWN_SAVE_TO_DISK;
return lockdown;
}

Some files were not shown because too many files have changed in this diff Show More