[almanah] core: Add support for hyperlinks
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [almanah] core: Add support for hyperlinks
- Date: Thu, 14 Apr 2011 21:13:06 +0000 (UTC)
commit 3bfc9106408009a745d0bcfa19719911a7bd96ad
Author: Philip Withnall <philip tecnocode co uk>
Date: Sat Apr 2 22:16:27 2011 +0100
core: Add support for hyperlinks
These replace definitions. Closes: bgo#631835
data/almanah.ui | 76 +++++++++++++++++
src/Makefile.am | 2 +
src/main-window.c | 167 ++++++++++++++++++++++++++++++++++---
src/uri-entry-dialog.c | 215 ++++++++++++++++++++++++++++++++++++++++++++++++
src/uri-entry-dialog.h | 57 +++++++++++++
5 files changed, 505 insertions(+), 12 deletions(-)
---
diff --git a/data/almanah.ui b/data/almanah.ui
index 85d100f..2d7ff5f 100644
--- a/data/almanah.ui
+++ b/data/almanah.ui
@@ -147,6 +147,14 @@
<accelerator key="U" modifiers="GDK_CONTROL_MASK"/>
</child>
<child>
+ <object class="GtkToggleAction" id="almanah_ui_hyperlink">
+ <property name="name">format-hyperlink</property>
+ <property name="label" translatable="yes">Add/Remove _Hyperlink</property>
+ <property name="tooltip" translatable="yes">Add or remove a hyperlink from the currently selected text to a specified URI.</property>
+ </object>
+ <accelerator key="H" modifiers="GDK_CONTROL_MASK"/>
+ </child>
+ <child>
<object class="GtkAction" id="almanah_ui_insert_time">
<property name="name">format-insert-time</property>
<property name="label" translatable="yes">Insert _Time</property>
@@ -219,6 +227,7 @@
<menuitem action="almanah_ui_bold"/>
<menuitem action="almanah_ui_italic"/>
<menuitem action="almanah_ui_underline"/>
+ <menuitem action="almanah_ui_hyperlink"/>
<separator/>
<menuitem action="almanah_ui_insert_time"/>
<menuitem action="almanah_ui_important"/>
@@ -234,6 +243,7 @@
<toolitem action="almanah_ui_bold"/>
<toolitem action="almanah_ui_italic"/>
<toolitem action="almanah_ui_underline"/>
+ <toolitem action="almanah_ui_hyperlink"/>
</toolbar>
</ui>
</object>
@@ -694,6 +704,72 @@
</action-widgets>
</object>
+ <object class="AlmanahUriEntryDialog" id="almanah_uri_entry_dialog">
+ <property name="border-width">5</property>
+ <child internal-child="vbox">
+ <object class="GtkVBox" id="vbox11">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkVBox" id="almanah_ued_vbox">
+ <property name="spacing">6</property>
+ <property name="border-width">5</property>
+ <child>
+ <object class="GtkEntry" id="almanah_ued_uri_entry">
+ <property name="activates-default">True</property>
+ <signal name="notify::text" handler="ued_uri_entry_notify_text_cb"/>
+ <accessibility>
+ <relation target="almanah_ued_description_label" type="described-by"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="almanah_ued_description_label">
+ <property name="xalign">0</property>
+ <!-- Translators: Use two popular URIs from your locale, preferably one on the Internet and one local file. -->
+ <property name="label" translatable="yes">e.g. â??http://google.com/â;?? or â??file:///home/me/Photos/photo.jpgâ??.</property>
+ <accessibility>
+ <relation target="almanah_ued_uri_entry" type="description-for"/>
+ </accessibility>
+ <attributes>
+ <attribute name="scale" value="0.8"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="almanah_ued_hbuttonbox">
+ <child>
+ <object class="GtkButton" id="almanah_ued_cancel_button">
+ <property name="use-stock">True</property>
+ <property name="label">gtk-cancel</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="almanah_ued_ok_button">
+ <property name="use-stock">True</property>
+ <property name="label">gtk-ok</property>
+ <property name="can-default">True</property>
+ <property name="has-default">True</property>
+ <property name="sensitive">False</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-6">almanah_ued_cancel_button</action-widget><!-- GTK_RESPONSE_CANCEL -->
+ <action-widget response="-5">almanah_ued_ok_button</action-widget><!-- GTK_RESPONSE_OK -->
+ </action-widgets>
+ </object>
+
<object class="GtkListStore" id="almanah_ied_mode_store">
<columns>
<column type="guint"/><!-- Type -->
diff --git a/src/Makefile.am b/src/Makefile.am
index 08ddde5..778da31 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,6 +31,8 @@ almanah_SOURCES = \
import-operation.h \
export-operation.c \
export-operation.h \
+ uri-entry-dialog.c \
+ uri-entry-dialog.h \
widgets/calendar.c \
widgets/calendar.h \
widgets/hyperlink-tag.c \
diff --git a/src/main-window.c b/src/main-window.c
index cb264e2..5c0c4d8 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -38,7 +38,9 @@
#include "storage-manager.h"
#include "event.h"
#include "import-export-dialog.h"
+#include "uri-entry-dialog.h"
#include "widgets/calendar.h"
+#include "widgets/hyperlink-tag.h"
static void almanah_main_window_dispose (GObject *object);
#ifdef ENABLE_SPELL_CHECKING
@@ -55,6 +57,7 @@ static void mw_entry_buffer_has_selection_cb (GObject *object, GParamSpec *pspec
static void mw_bold_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window);
static void mw_italic_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window);
static void mw_underline_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window);
+static void mw_hyperlink_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window);
static void mw_events_updated_cb (AlmanahEventManager *event_manager, AlmanahEventFactoryType type_id, AlmanahMainWindow *main_window);
static void mw_events_selection_changed_cb (GtkTreeSelection *tree_selection, AlmanahMainWindow *main_window);
static void mw_events_value_data_cb (GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data);
@@ -94,6 +97,7 @@ struct _AlmanahMainWindowPrivate {
GtkToggleAction *bold_action;
GtkToggleAction *italic_action;
GtkToggleAction *underline_action;
+ GtkToggleAction *hyperlink_action;
GtkAction *cut_action;
GtkAction *copy_action;
GtkAction *delete_action;
@@ -222,6 +226,7 @@ almanah_main_window_new (void)
priv->bold_action = GTK_TOGGLE_ACTION (gtk_builder_get_object (builder, "almanah_ui_bold"));;
priv->italic_action = GTK_TOGGLE_ACTION (gtk_builder_get_object (builder, "almanah_ui_italic"));
priv->underline_action = GTK_TOGGLE_ACTION (gtk_builder_get_object (builder, "almanah_ui_underline"));
+ priv->hyperlink_action = GTK_TOGGLE_ACTION (gtk_builder_get_object (builder, "almanah_ui_hyperlink"));
priv->cut_action = GTK_ACTION (gtk_builder_get_object (builder, "almanah_ui_cut"));
priv->copy_action = GTK_ACTION (gtk_builder_get_object (builder, "almanah_ui_copy"));
priv->delete_action = GTK_ACTION (gtk_builder_get_object (builder, "almanah_ui_delete"));
@@ -252,6 +257,7 @@ almanah_main_window_new (void)
g_signal_connect (priv->bold_action, "toggled", G_CALLBACK (mw_bold_toggled_cb), main_window);
g_signal_connect (priv->italic_action, "toggled", G_CALLBACK (mw_italic_toggled_cb), main_window);
g_signal_connect (priv->underline_action, "toggled", G_CALLBACK (mw_underline_toggled_cb), main_window);
+ g_signal_connect (priv->hyperlink_action, "toggled", (GCallback) mw_hyperlink_toggled_cb, main_window);
/* Notification for event changes */
g_signal_connect (almanah->event_manager, "events-updated", G_CALLBACK (mw_events_updated_cb), main_window);
@@ -612,7 +618,7 @@ mw_entry_buffer_cursor_position_cb (GObject *object, GParamSpec *pspec, AlmanahM
AlmanahMainWindowPrivate *priv = main_window->priv;
GSList *_tag_list = NULL, *tag_list = NULL;
gboolean range_selected = FALSE;
- gboolean bold_toggled = FALSE, italic_toggled = FALSE, underline_toggled = FALSE;
+ gboolean bold_toggled = FALSE, italic_toggled = FALSE, underline_toggled = FALSE, hyperlink_toggled = FALSE;
/* Ensure we don't overwrite current formatting options when characters are being typed.
* (Execution of this function will be sandwiched between:
@@ -633,27 +639,37 @@ mw_entry_buffer_cursor_position_cb (GObject *object, GParamSpec *pspec, AlmanahM
tag_list = _tag_list;
while (tag_list != NULL) {
+ GtkTextTag *tag;
gchar *tag_name;
GtkToggleAction *action = NULL;
- g_object_get (tag_list->data, "name", &tag_name, NULL);
+ tag = GTK_TEXT_TAG (tag_list->data);
+ g_object_get (tag, "name", &tag_name, NULL);
/* See if we can do anything with the tag */
- if (strcmp (tag_name, "bold") == 0) {
- action = priv->bold_action;
- bold_toggled = TRUE;
- } else if (strcmp (tag_name, "italic") == 0) {
- action = priv->italic_action;
- italic_toggled = TRUE;
- } else if (strcmp (tag_name, "underline") == 0) {
- action = priv->underline_action;
- underline_toggled = TRUE;
+ if (tag_name != NULL) {
+ if (strcmp (tag_name, "bold") == 0) {
+ action = priv->bold_action;
+ bold_toggled = TRUE;
+ } else if (strcmp (tag_name, "italic") == 0) {
+ action = priv->italic_action;
+ italic_toggled = TRUE;
+ } else if (strcmp (tag_name, "underline") == 0) {
+ action = priv->underline_action;
+ underline_toggled = TRUE;
+ }
+ }
+
+ /* Hyperlink? */
+ if (ALMANAH_IS_HYPERLINK_TAG (tag)) {
+ action = priv->hyperlink_action;
+ hyperlink_toggled = TRUE;
}
if (action != NULL) {
/* Force the toggle status on the action */
gtk_toggle_action_set_active (action, TRUE);
- } else if (strcmp (tag_name, "gtkspell-misspelled") != 0) {
+ } else if (tag_name == NULL || strcmp (tag_name, "gtkspell-misspelled") != 0) {
/* Print a warning about the unknown tag */
g_warning (_("Unknown or duplicate text tag \"%s\" in entry. Ignoring."), tag_name);
}
@@ -672,6 +688,10 @@ mw_entry_buffer_cursor_position_cb (GObject *object, GParamSpec *pspec, AlmanahM
gtk_toggle_action_set_active (priv->italic_action, FALSE);
if (underline_toggled == FALSE)
gtk_toggle_action_set_active (priv->underline_action, FALSE);
+
+ if (hyperlink_toggled == FALSE) {
+ gtk_toggle_action_set_active (priv->hyperlink_action, FALSE);
+ }
}
/* Unblock signals */
@@ -896,6 +916,129 @@ mw_underline_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window
apply_formatting (main_window, "underline", gtk_toggle_action_get_active (action));
}
+static gboolean
+hyperlink_tag_event_cb (GtkTextTag *tag, GObject *object, GdkEvent *event, GtkTextIter *iter, gpointer user_data)
+{
+ AlmanahHyperlinkTag *self = ALMANAH_HYPERLINK_TAG (tag);
+
+ /* Open the hyperlink if it's control-clicked */
+ if (event->type == GDK_BUTTON_RELEASE && event->button.state & GDK_CONTROL_MASK) {
+ GtkWindow *main_window;
+ const gchar *uri;
+ GError *error = NULL;
+
+ main_window = GTK_WINDOW (almanah->main_window);
+ uri = almanah_hyperlink_tag_get_uri (self);
+
+ /* Attempt to open the URI */
+ gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (main_window)), uri, gdk_event_get_time (event), &error);
+
+ if (error != NULL) {
+ /* Error */
+ GtkWidget *dialog = gtk_message_dialog_new (main_window,
+ GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ _("Error opening URI"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ g_error_free (error);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+mw_hyperlink_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *self)
+{
+ AlmanahMainWindowPrivate *priv = self->priv;
+ GtkTextIter start, end;
+
+ /* Make sure we don't muck up the formatting when the actions are having
+ * their sensitivity set by the code. */
+ if (priv->updating_formatting == TRUE)
+ return;
+
+ gtk_text_buffer_get_selection_bounds (priv->entry_buffer, &start, &end);
+
+ if (gtk_toggle_action_get_active (action) == TRUE) {
+ /* Add a new hyperlink on the selected text */
+ AlmanahUriEntryDialog *uri_entry_dialog;
+
+ /* Get a URI from the user */
+ uri_entry_dialog = almanah_uri_entry_dialog_new ();
+ gtk_window_set_transient_for (GTK_WINDOW (uri_entry_dialog), GTK_WINDOW (self));
+ gtk_widget_show_all (GTK_WIDGET (uri_entry_dialog));
+
+ if (almanah_uri_entry_dialog_run (uri_entry_dialog) == TRUE) {
+ GtkTextTag *tag;
+ GtkTextTagTable *table;
+
+ /* Create and apply a new anonymous tag */
+ tag = GTK_TEXT_TAG (almanah_hyperlink_tag_new (almanah_uri_entry_dialog_get_uri (uri_entry_dialog)));
+
+ table = gtk_text_buffer_get_tag_table (priv->entry_buffer);
+ gtk_text_tag_table_add (table, tag);
+
+ gtk_text_buffer_apply_tag (priv->entry_buffer, tag, &start, &end);
+
+ /* Connect up events */
+ g_signal_connect (tag, "event", (GCallback) hyperlink_tag_event_cb, NULL);
+
+ /* The text tag table keeps a reference */
+ g_object_unref (tag);
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (uri_entry_dialog));
+ } else {
+ GtkTextIter iter = start;
+ GSList *tags, *i;
+
+ /* Remove all hyperlinks which are active at the start iter. This covers the case of hyperlinks which span more than the
+ * selected text (i.e. begin before the start iter and end after the end iter). All other spanning hyperlinks will have an end point
+ * inside the selected text, and will be caught below. */
+ tags = gtk_text_iter_get_tags (&start);
+
+ for (i = tags; i != NULL; i = i->next) {
+ GtkTextTag *tag = GTK_TEXT_TAG (i->data);
+
+ if (ALMANAH_IS_HYPERLINK_TAG (tag)) {
+ GtkTextIter tag_start = start, tag_end = start;
+
+ if (gtk_text_iter_backward_to_tag_toggle (&tag_start, tag) == TRUE &&
+ gtk_text_iter_forward_to_tag_toggle (&tag_end, tag) == TRUE) {
+ gtk_text_buffer_remove_tag (priv->entry_buffer, tag, &tag_start, &tag_end);
+ }
+ }
+ }
+
+ g_slist_free (tags);
+
+ /* Remove all hyperlinks which span the selected text and have an end point inside the selected text */
+ while (gtk_text_iter_forward_to_tag_toggle (&iter, NULL) == TRUE) {
+ /* Break once we've passed the end of the selected text range */
+ if (gtk_text_iter_compare (&iter, &end) > 0) {
+ break;
+ }
+
+ tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
+
+ for (i = tags; i != NULL; i = i->next) {
+ if (ALMANAH_IS_HYPERLINK_TAG (i->data)) {
+ gtk_text_buffer_remove_tag (priv->entry_buffer, GTK_TEXT_TAG (i->data), &start, &end);
+ }
+ }
+
+ g_slist_free (tags);
+ }
+ }
+
+ gtk_text_buffer_set_modified (priv->entry_buffer, TRUE);
+}
+
void
mw_about_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
{
diff --git a/src/uri-entry-dialog.c b/src/uri-entry-dialog.c
new file mode 100644
index 0000000..fe61f7b
--- /dev/null
+++ b/src/uri-entry-dialog.c
@@ -0,0 +1,215 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Almanah
+ * Copyright (C) Philip Withnall 2011 <philip tecnocode co uk>
+ *
+ * Almanah 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Almanah 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 Almanah. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "uri-entry-dialog.h"
+#include "main.h"
+#include "interface.h"
+
+static void almanah_uri_entry_dialog_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
+static void almanah_uri_entry_dialog_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
+
+/* GtkBuilder callbacks */
+G_MODULE_EXPORT void ued_uri_entry_notify_text_cb (GObject *gobject, GParamSpec *pspec, AlmanahUriEntryDialog *self);
+
+struct _AlmanahUriEntryDialogPrivate {
+ gchar *uri;
+ GtkWidget *ok_button;
+ GtkEntry *uri_entry;
+};
+
+enum {
+ PROP_URI = 1
+};
+
+G_DEFINE_TYPE (AlmanahUriEntryDialog, almanah_uri_entry_dialog, GTK_TYPE_DIALOG)
+#define ALMANAH_URI_ENTRY_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_URI_ENTRY_DIALOG, AlmanahUriEntryDialogPrivate))
+
+static void
+almanah_uri_entry_dialog_class_init (AlmanahUriEntryDialogClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (AlmanahUriEntryDialogPrivate));
+
+ gobject_class->set_property = almanah_uri_entry_dialog_set_property;
+ gobject_class->get_property = almanah_uri_entry_dialog_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_URI,
+ g_param_spec_string ("uri",
+ "URI", "The current URI entered in the dialog.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+almanah_uri_entry_dialog_init (AlmanahUriEntryDialog *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_URI_ENTRY_DIALOG, AlmanahUriEntryDialogPrivate);
+
+ g_signal_connect (self, "response", (GCallback) gtk_widget_hide, self);
+ gtk_window_set_resizable (GTK_WINDOW (self), FALSE);
+ gtk_window_set_title (GTK_WINDOW (self), _("Enter URI"));
+}
+
+static void
+almanah_uri_entry_dialog_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+ AlmanahUriEntryDialogPrivate *priv = ALMANAH_URI_ENTRY_DIALOG (object)->priv;
+
+ switch (property_id) {
+ case PROP_URI:
+ g_value_set_string (value, priv->uri);
+ break;
+ default:
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+almanah_uri_entry_dialog_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+ AlmanahUriEntryDialog *self = ALMANAH_URI_ENTRY_DIALOG (object);
+
+ switch (property_id) {
+ case PROP_URI:
+ almanah_uri_entry_dialog_set_uri (self, g_value_get_string (value));
+ break;
+ default:
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+AlmanahUriEntryDialog *
+almanah_uri_entry_dialog_new (void)
+{
+ GtkBuilder *builder;
+ AlmanahUriEntryDialog *uri_entry_dialog;
+ AlmanahUriEntryDialogPrivate *priv;
+ GError *error = NULL;
+ const gchar *interface_filename = almanah_get_interface_filename ();
+ const gchar *object_names[] = {
+ "almanah_uri_entry_dialog",
+ NULL
+ };
+
+ builder = gtk_builder_new ();
+
+ if (gtk_builder_add_objects_from_file (builder, interface_filename, (gchar**) object_names, &error) == FALSE) {
+ /* Show an error */
+ GtkWidget *dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ _("UI file \"%s\" could not be loaded"), interface_filename);
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ g_error_free (error);
+ g_object_unref (builder);
+
+ return NULL;
+ }
+
+ gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE);
+ uri_entry_dialog = ALMANAH_URI_ENTRY_DIALOG (gtk_builder_get_object (builder, "almanah_uri_entry_dialog"));
+ gtk_builder_connect_signals (builder, uri_entry_dialog);
+
+ if (uri_entry_dialog == NULL) {
+ g_object_unref (builder);
+ return NULL;
+ }
+
+ priv = uri_entry_dialog->priv;
+
+ /* Grab widgets */
+ priv->ok_button = GTK_WIDGET (gtk_builder_get_object (builder, "almanah_ued_ok_button"));
+ priv->uri_entry = GTK_ENTRY (gtk_builder_get_object (builder, "almanah_ued_uri_entry"));
+
+ g_object_unref (builder);
+
+ return uri_entry_dialog;
+}
+
+gboolean
+almanah_uri_entry_dialog_run (AlmanahUriEntryDialog *self)
+{
+ /* Reset the URI entry and consequently the OK button */
+ gtk_entry_set_text (self->priv->uri_entry, "");
+ g_free (self->priv->uri);
+ self->priv->uri = NULL;
+
+ return (gtk_dialog_run (GTK_DIALOG (self)) == GTK_RESPONSE_OK) ? TRUE : FALSE;
+}
+
+static gboolean
+is_uri_valid (const gchar *uri)
+{
+ gchar *tmp;
+
+ /* We assume that g_uri_parse_scheme() will fail if the URI is invalid. */
+ tmp = g_uri_parse_scheme (uri);
+ g_free (tmp);
+
+ return (tmp != NULL) ? TRUE : FALSE;
+}
+
+void
+ued_uri_entry_notify_text_cb (GObject *gobject, GParamSpec *param_spec, AlmanahUriEntryDialog *self)
+{
+ AlmanahUriEntryDialogPrivate *priv = self->priv;
+
+ /* Enable/Disable the OK button based on whether the current URI is valid. */
+ if (is_uri_valid (gtk_entry_get_text (priv->uri_entry)) == TRUE) {
+ /* The URI was parsed successfully; update priv->uri and enable the OK button */
+ priv->uri = g_strdup (gtk_entry_get_text (priv->uri_entry));
+ gtk_widget_set_sensitive (priv->ok_button, TRUE);
+ } else {
+ /* Failure due to the URI entered being invalid; disable the OK button */
+ gtk_widget_set_sensitive (priv->ok_button, FALSE);
+ }
+}
+
+const gchar *
+almanah_uri_entry_dialog_get_uri (AlmanahUriEntryDialog *self)
+{
+ g_return_val_if_fail (ALMANAH_IS_URI_ENTRY_DIALOG (self), NULL);
+ return self->priv->uri;
+}
+
+void
+almanah_uri_entry_dialog_set_uri (AlmanahUriEntryDialog *self, const gchar *uri)
+{
+ g_return_if_fail (ALMANAH_IS_URI_ENTRY_DIALOG (self));
+ g_return_if_fail (uri == NULL || is_uri_valid (uri) == TRUE);
+
+ g_free (self->priv->uri);
+ self->priv->uri = g_strdup (uri);
+
+ g_object_notify (G_OBJECT (self), "uri");
+}
diff --git a/src/uri-entry-dialog.h b/src/uri-entry-dialog.h
new file mode 100644
index 0000000..c59165b
--- /dev/null
+++ b/src/uri-entry-dialog.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Almanah
+ * Copyright (C) Philip Withnall 2011 <philip tecnocode co uk>
+ *
+ * Almanah 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Almanah 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 Almanah. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef ALMANAH_URI_ENTRY_DIALOG_H
+#define ALMANAH_URI_ENTRY_DIALOG_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define ALMANAH_TYPE_URI_ENTRY_DIALOG (almanah_uri_entry_dialog_get_type ())
+#define ALMANAH_URI_ENTRY_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_URI_ENTRY_DIALOG, AlmanahUriEntryDialog))
+#define ALMANAH_URI_ENTRY_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), ALMANAH_TYPE_URI_ENTRY_DIALOG, AlmanahUriEntryDialogClass))
+#define ALMANAH_IS_URI_ENTRY_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), ALMANAH_TYPE_URI_ENTRY_DIALOG))
+#define ALMANAH_IS_URI_ENTRY_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), ALMANAH_TYPE_URI_ENTRY_DIALOG))
+#define ALMANAH_URI_ENTRY_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ALMANAH_TYPE_URI_ENTRY_DIALOG, AlmanahUriEntryDialogClass))
+
+typedef struct _AlmanahUriEntryDialogPrivate AlmanahUriEntryDialogPrivate;
+
+typedef struct {
+ GtkDialog parent;
+ AlmanahUriEntryDialogPrivate *priv;
+} AlmanahUriEntryDialog;
+
+typedef struct {
+ GtkDialogClass parent;
+} AlmanahUriEntryDialogClass;
+
+GType almanah_uri_entry_dialog_get_type (void) G_GNUC_CONST;
+
+AlmanahUriEntryDialog *almanah_uri_entry_dialog_new (void) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+gboolean almanah_uri_entry_dialog_run (AlmanahUriEntryDialog *self);
+
+const gchar *almanah_uri_entry_dialog_get_uri (AlmanahUriEntryDialog *self) G_GNUC_PURE;
+void almanah_uri_entry_dialog_set_uri (AlmanahUriEntryDialog *self, const gchar *uri);
+
+G_END_DECLS
+
+#endif /* !ALMANAH_URI_ENTRY_DIALOG_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]