diary r83 - in trunk: . data po src src/links



Author: pwithnall
Date: Fri Oct 10 22:22:19 2008
New Revision: 83
URL: http://svn.gnome.org/viewvc/diary?rev=83&view=rev

Log:
2008-10-10  Philip Withnall  <philip tecnocode co uk>

	* data/almanah.ui:
	* src/Makefile.am:
	* src/add-link-dialog.c (almanah_add_link_dialog_class_init),
	(almanah_add_link_dialog_init), 
(almanah_add_link_dialog_dispose),
	(almanah_add_link_dialog_new), (destroy_extra_widgets),
	(ald_response_cb), (ald_type_combo_box_changed_cb), 
(ald_show_cb),
	(almanah_add_link_dialog_get_link):
	* src/add-link-dialog.h:
	* src/entry.c (almanah_entry_class_init), (almanah_entry_init),
	(almanah_entry_finalize), (almanah_entry_get_property),
	(almanah_entry_set_property), (almanah_entry_new),
	(almanah_entry_set_content), (almanah_entry_get_content),
	(almanah_entry_get_date), (almanah_entry_get_editability),
	(almanah_entry_is_empty):
	* src/entry.h:
	* src/interface.c (diary_get_interface_filename),
	(diary_create_interface), (diary_interface_error),
	(diary_calendar_month_changed_cb):
	* src/interface.h:
	* src/link.c (almanah_link_class_init), (almanah_link_init),
	(almanah_link_finalize), (almanah_link_get_property),
	(almanah_link_set_property), (almanah_link_new),
	(almanah_link_format_value), (almanah_link_view),
	(almanah_link_build_dialog), (almanah_link_get_values),
	(almanah_link_populate_model), (almanah_link_get_type_id),
	(almanah_link_get_name), (almanah_link_get_description),
	(almanah_link_get_icon_name), (almanah_link_get_value),
	(almanah_link_set_value), (almanah_link_get_value2),
	(almanah_link_set_value2):
	* src/link.h:
	* src/links/file.c (almanah_file_link_class_init),
	(almanah_file_link_init), (file_format_value), (file_view),
	(file_build_dialog), (file_get_values):
	* src/links/file.h:
	* src/links/note.c (almanah_note_link_class_init),
	(almanah_note_link_init), (note_format_value), (note_view),
	(note_build_dialog), (note_get_values):
	* src/links/note.h:
	* src/links/uri.c (almanah_uri_link_class_init),
	(almanah_uri_link_init), (uri_format_value), (uri_view),
	(uri_build_dialog), (uri_get_values):
	* src/links/uri.h:
	* src/main-window.c (almanah_main_window_class_init),
	(almanah_main_window_init), (almanah_main_window_dispose),
	(almanah_main_window_new), (save_current_entry),
	(add_link_to_current_entry), (remove_link_from_current_entry),
	(almanah_main_window_select_date),
	(mw_entry_buffer_cursor_position_changed_cb), 
(mw_delete_event_cb),
	(mw_quit_activate_cb), (mw_cut_activate_cb), 
(mw_copy_activate_cb),
	(mw_paste_activate_cb), (mw_delete_activate_cb),
	(mw_search_activate_cb), (apply_formatting), 
(mw_bold_toggled_cb),
	(mw_italic_toggled_cb), (mw_underline_toggled_cb),
	(mw_about_activate_cb), (mw_jump_to_today_activate_cb),
	(mw_add_link_activate_cb), (mw_remove_link_activate_cb),
	(mw_calendar_day_selected_cb), (mw_links_selection_changed_cb),
	(mw_links_value_data_cb), (mw_links_tree_view_row_activated_cb),
	(mw_entry_view_focus_out_event_cb), (mw_add_button_clicked_cb),
	(mw_remove_button_clicked_cb), (mw_view_button_clicked_cb):
	* src/main-window.h:
	* src/main.c (diary_quit), (main):
	* src/main.h:
	* src/printing.c (print_entry):
	* src/search-dialog.c (almanah_search_dialog_class_init),
	(almanah_search_dialog_init), (almanah_search_dialog_new),
	(sd_results_selection_changed_cb), (sd_response_cb),
	(sd_search_button_clicked_cb), (select_date),
	(sd_view_button_clicked_cb):
	* src/search-dialog.h:
	* src/storage-manager.c (almanah_storage_manager_error_quark),
	(almanah_storage_manager_class_init),
	(almanah_storage_manager_init), (almanah_storage_manager_new),
	(almanah_storage_manager_finalize),
	(almanah_storage_manager_get_property),
	(almanah_storage_manager_set_property), (create_tables),
	(prepare_gpgme), (open_db_files), (decrypt_database),
	(encrypt_database), (almanah_storage_manager_connect),
	(almanah_storage_manager_disconnect),
	(almanah_storage_manager_query),
	(almanah_storage_manager_free_results),
	(almanah_storage_manager_query_async),
	(almanah_storage_manager_get_statistics),
	(almanah_storage_manager_entry_exists),
	(almanah_storage_manager_get_entry),
	(almanah_storage_manager_set_entry),
	(almanah_storage_manager_search_entries),
	(almanah_storage_manager_get_month_marked_days),
	(almanah_storage_manager_get_entry_links),
	(almanah_storage_manager_add_entry_link),
	(almanah_storage_manager_remove_entry_link):
	* src/storage-manager.h: Major architectural update, moving a 
lot of
	things to GObject, and adding basic text formatting support.



Added:
   trunk/src/entry.c
   trunk/src/entry.h
   trunk/src/links/file.h
   trunk/src/links/note.h
   trunk/src/links/uri.h
Modified:
   trunk/ChangeLog
   trunk/data/almanah.ui
   trunk/po/ChangeLog
   trunk/po/Makefile.in.in
   trunk/src/Makefile.am
   trunk/src/add-link-dialog.c
   trunk/src/add-link-dialog.h
   trunk/src/interface.c
   trunk/src/interface.h
   trunk/src/link.c
   trunk/src/link.h
   trunk/src/links/file.c
   trunk/src/links/note.c
   trunk/src/links/uri.c
   trunk/src/main-window.c
   trunk/src/main-window.h
   trunk/src/main.c
   trunk/src/main.h
   trunk/src/printing.c
   trunk/src/search-dialog.c
   trunk/src/search-dialog.h
   trunk/src/storage-manager.c
   trunk/src/storage-manager.h

Modified: trunk/data/almanah.ui
==============================================================================
--- trunk/data/almanah.ui	(original)
+++ trunk/data/almanah.ui	Fri Oct 10 22:22:19 2008
@@ -66,6 +66,30 @@
 					</object>
 				</child>
 				<child>
+					<object class="GtkAction" id="dry_ui_format">
+						<property name="name">format</property>
+						<property name="label" translatable="yes">F_ormat</property>
+					</object>
+				</child>
+				<child>
+					<object class="GtkToggleAction" id="dry_ui_bold">
+						<property name="stock-id">gtk-bold</property>
+						<property name="name">format-bold</property>
+					</object>
+				</child>
+				<child>
+					<object class="GtkToggleAction" id="dry_ui_italic">
+						<property name="stock-id">gtk-italic</property>
+						<property name="name">format-italic</property>
+					</object>
+				</child>
+				<child>
+					<object class="GtkToggleAction" id="dry_ui_underline">
+						<property name="stock-id">gtk-underline</property>
+						<property name="name">format-underline</property>
+					</object>
+				</child>
+				<child>
 					<object class="GtkAction" id="dry_ui_help">
 						<property name="name">help</property>
 						<property name="label" translatable="yes">_Help</property>
@@ -118,6 +142,11 @@
 					<separator/>
 					<menuitem action="dry_ui_search"/>
 				</menu>
+				<menu action="dry_ui_format">
+					<menuitem action="dry_ui_bold"/>
+					<menuitem action="dry_ui_italic"/>
+					<menuitem action="dry_ui_underline"/>
+				</menu>
 				<menu action="dry_ui_help">
 					<menuitem action="dry_ui_about"/>
 				</menu>
@@ -127,12 +156,15 @@
 				<separator/>
 				<toolitem action="dry_ui_add_link"/>
 				<toolitem action="dry_ui_remove_link"/>
+				<separator/>
+				<toolitem action="dry_ui_bold"/>
+				<toolitem action="dry_ui_italic"/>
+				<toolitem action="dry_ui_underline"/>
 			</toolbar>
 		</ui>
 	</object>
 
-	<!-- TODO: Change to dry_mw_link_store -->
-	<object class="GtkListStore" id="dry_mw_links_store">
+	<object class="GtkListStore" id="dry_mw_link_store">
 		<columns>
 			<column type="gchararray"/><!--Type-->
 			<column type="gchararray"/><!--Value-->
@@ -145,9 +177,7 @@
 		<property name="stock">gtk-open</property>
 	</object>
 
-	<object class="GtkWindow" id="dry_main_window">
-		<property name="title" translatable="yes">Almanah Diary</property>
-		<signal name="delete-event" handler="mw_delete_event_cb"/>
+	<object class="AlmanahMainWindow" id="dry_main_window">
 		<child>
 			<object class="GtkVBox" id="vbox1">
 				<child>
@@ -235,7 +265,7 @@
 										<property name="shadow-type">GTK_SHADOW_IN</property>
 										<child>
 											<object class="GtkTreeView" id="dry_mw_links_tree_view">
-												<property name="model">dry_mw_links_store</property>
+												<property name="model">dry_mw_link_store</property>
 												<property name="can-focus">True</property>
 												<property name="headers-visible">False</property>
 												<signal name="row-activated" handler="mw_links_tree_view_row_activated_cb"/>
@@ -318,16 +348,12 @@
 	</object>
 
 	<!-- TODO: Use the description of link types somewhere -->
-	<object class="GtkDialog" id="dry_add_link_dialog">
-		<property name="title" translatable="yes">Add Link</property>
-		<property name="has-separator">False</property>
-		<property name="allow-grow">False</property>
-		<signal name="destroy" handler="ald_destroy_cb"/>
+	<object class="AlmanahAddLinkDialog" id="dry_add_link_dialog">
 		<child internal-child="vbox">
 			<object class="GtkVBox" id="vbox1">
 				<child>
 					<object class="GtkTable" id="dry_ald_table">
-						<property name="n-rows">1</property>
+						<property name="n-rows">2</property>
 						<property name="n-columns">2</property>
 						<property name="column-spacing">5</property>
 						<property name="row-spacing">5</property>
@@ -370,7 +396,15 @@
 								<property name="y-options">GTK_FILL</property>
 							</packing>
 						</child>
-						<!-- Placeholder -->
+						<child>
+							<object class="GtkVBox" id="dry_ald_vbox"/>
+							<packing>
+								<property name="left-attach">1</property>
+								<property name="right-attach">3</property>
+								<property name="top-attach">2</property>
+								<property name="bottom-attach">3</property>
+							</packing>
+						</child>
 					</object>
 				</child>
 				<child internal-child="action_area">
@@ -412,11 +446,7 @@
 		</columns>
 	</object>
 
-	<object class="GtkDialog" id="dry_search_dialog">
-		<property name="title" translatable="yes">Search</property>
-		<property name="has-separator">False</property>
-		<property name="modal">False</property>
-		<signal name="destroy" handler="sd_destroy_cb"/>
+	<object class="AlmanahSearchDialog" id="dry_search_dialog">
 		<child internal-child="vbox">
 			<object class="GtkVBox" id="vbox2">
 				<child>

Modified: trunk/po/Makefile.in.in
==============================================================================
--- trunk/po/Makefile.in.in	(original)
+++ trunk/po/Makefile.in.in	Fri Oct 10 22:22:19 2008
@@ -54,16 +54,16 @@
 
 ALL_LINGUAS = @ALL_LINGUAS@
 
-PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; fi)
+PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; else echo "$(ALL_LINGUAS)"; fi)
 
 USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep ^$$lang$$ $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep ^$$lang$$`"; then printf "$$lang "; fi; done; fi)
 
 USE_LINGUAS=$(shell if test -n "$(USER_LINGUAS)" -o -n "$(LINGUAS)"; then LLINGUAS="$(USER_LINGUAS)"; else if test -n "$(PO_LINGUAS)"; then LLINGUAS="$(PO_LINGUAS)"; else LLINGUAS="$(ALL_LINGUAS)"; fi; fi; for lang in $$LLINGUAS; do printf "$$lang "; done)
 
-POFILES=$(shell LINGUAS="$(USE_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.po "; done)
+POFILES=$(shell LINGUAS="$(PO_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.po "; done)
 
-DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(POFILES)
-EXTRA_DISTFILES = POTFILES.skip Makevars LINGUAS
+DISTFILES = Makefile.in.in POTFILES.in $(POFILES)
+EXTRA_DISTFILES = ChangeLog POTFILES.skip Makevars LINGUAS
 
 POTFILES = \
 # This comment gets stripped out

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Fri Oct 10 22:22:19 2008
@@ -32,11 +32,13 @@
 	search-dialog.h		\
 	printing.c		\
 	printing.h		\
+	entry.c			\
+	entry.h			\
 	link.c			\
 	link.h			\
-	links/uri.c		\
 	links/file.c		\
-	links/note.c
+	links/note.c		\
+	links/uri.c
 
 almanah_LDFLAGS = 
 almanah_LDADD = \

Modified: trunk/src/add-link-dialog.c
==============================================================================
--- trunk/src/add-link-dialog.c	(original)
+++ trunk/src/add-link-dialog.c	Fri Oct 10 22:22:19 2008
@@ -1,89 +1,187 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * 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 <string.h>
 
-#include "main.h"
-#include "link.h"
 #include "add-link-dialog.h"
+#include "link.h"
+#include "interface.h"
+
+static void almanah_add_link_dialog_init (AlmanahAddLinkDialog *self);
+static void almanah_add_link_dialog_dispose (GObject *object);
+static void ald_response_cb (GtkDialog *dialog, gint response_id, AlmanahAddLinkDialog *add_link_dialog);
+static void ald_show_cb (GtkWidget *widget, AlmanahAddLinkDialog *add_link_dialog);
+
+struct _AlmanahAddLinkDialogPrivate {
+	GtkComboBox *ald_type_combo_box;
+	GtkVBox *ald_vbox;
+	GtkListStore *ald_type_store;
+	AlmanahLink *link;
+};
+
+G_DEFINE_TYPE (AlmanahAddLinkDialog, almanah_add_link_dialog, GTK_TYPE_DIALOG)
+#define ALMANAH_ADD_LINK_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_ADD_LINK_DIALOG, AlmanahAddLinkDialogPrivate))
+
+static void
+almanah_add_link_dialog_class_init (AlmanahAddLinkDialogClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	g_type_class_add_private (klass, sizeof (AlmanahAddLinkDialogPrivate));
+	gobject_class->dispose = almanah_add_link_dialog_dispose;
+}
+
+static void
+almanah_add_link_dialog_init (AlmanahAddLinkDialog *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_ADD_LINK_DIALOG, AlmanahAddLinkDialogPrivate);
+
+	g_signal_connect (self, "response", G_CALLBACK (ald_response_cb), self);
+	g_signal_connect (self, "show", G_CALLBACK (ald_show_cb), self);
+	gtk_dialog_set_has_separator (GTK_DIALOG (self), FALSE);
+	gtk_window_set_resizable (GTK_WINDOW (self), FALSE);
+	gtk_window_set_title (GTK_WINDOW (self), _("Add Link"));
+}
 
 static void
-destroy_extra_table_widgets (void)
+almanah_add_link_dialog_dispose (GObject *object)
 {
-	GList *children;
+	AlmanahAddLinkDialogPrivate *priv = ALMANAH_ADD_LINK_DIALOG (object)->priv;
 
-	/* Destroy the foreign children */
-	children = gtk_container_get_children (GTK_CONTAINER (diary->ald_table));
-	for (; children != NULL; children = children->next) {
-		if (g_object_get_data (G_OBJECT (children->data), "native") == NULL)
-			gtk_widget_destroy (GTK_WIDGET (children->data));
+	if (priv->link != NULL) {
+		g_object_unref (priv->link);
+		priv->link = NULL;
 	}
-	g_list_free (children);
 
-	/* Resize the table */
-	gtk_table_resize (diary->ald_table, 1, 2);
+	/* Chain up to the parent class */
+	G_OBJECT_CLASS (almanah_add_link_dialog_parent_class)->dispose (object);
 }
 
-void
-diary_add_link_dialog_setup (GtkBuilder *builder)
+AlmanahAddLinkDialog *
+almanah_add_link_dialog_new (void)
 {
-	g_object_set_data (gtk_builder_get_object (builder, "dry_ald_type_label"), "native", GUINT_TO_POINTER (TRUE));
-	g_object_set_data (G_OBJECT (diary->ald_type_combo_box), "native", GUINT_TO_POINTER (TRUE));
+	GtkBuilder *builder;
+	AlmanahAddLinkDialog *add_link_dialog;
+	AlmanahAddLinkDialogPrivate *priv;
+	GError *error = NULL;
+	const gchar *interface_filename = diary_get_interface_filename ();
+	const gchar *object_names[] = {
+		"dry_add_link_dialog",
+		"dry_ald_type_store",
+		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);
 
-	diary_populate_link_model (diary->ald_type_store, 1, 0, 2);
-	gtk_combo_box_set_active (diary->ald_type_combo_box, 0);
+		g_error_free (error);
+		g_object_unref (builder);
+
+		return NULL;
+	}
+
+	gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE);
+	add_link_dialog = ALMANAH_ADD_LINK_DIALOG (gtk_builder_get_object (builder, "dry_add_link_dialog"));
+	gtk_builder_connect_signals (builder, add_link_dialog);
+
+	if (add_link_dialog == NULL) {
+		g_object_unref (builder);
+		return NULL;
+	}
+
+	priv = add_link_dialog->priv;
+
+	/* Grab our child widgets */
+	priv->ald_type_combo_box = GTK_COMBO_BOX (gtk_builder_get_object (builder, "dry_ald_type_combo_box"));
+	priv->ald_vbox = GTK_VBOX (gtk_builder_get_object (builder, "dry_ald_vbox"));
+	priv->ald_type_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "dry_ald_type_store"));
+
+	almanah_link_populate_model (priv->ald_type_store, 1, 0, 2);
+	gtk_combo_box_set_active (priv->ald_type_combo_box, 0);
+
+	g_object_unref (builder);
+
+	return add_link_dialog;
 }
 
-void
-diary_hide_ald (void)
+static void
+destroy_extra_widgets (AlmanahAddLinkDialog *self)
 {
-	/* Resize the table so we lose all the custom widgets */
-	gtk_widget_hide_all (diary->add_link_dialog);
-	destroy_extra_table_widgets ();
+	gtk_container_foreach (GTK_CONTAINER (self->priv->ald_vbox), (GtkCallback) gtk_widget_destroy, NULL);
 }
 
-void
-ald_destroy_cb (GtkWindow *window, gpointer user_data)
+static void
+ald_response_cb (GtkDialog *dialog, gint response_id, AlmanahAddLinkDialog *add_link_dialog)
 {
-	diary_hide_ald ();
+	/* Save the entered data */
+	g_assert (add_link_dialog->priv->link != NULL);
+	almanah_link_get_values (add_link_dialog->priv->link);
+
+	/* Make sure to remove all the custom widgets for the currently-selected link type */
+	gtk_widget_hide_all (GTK_WIDGET (dialog));
+	destroy_extra_widgets (add_link_dialog);
 }
 
 void
-ald_type_combo_box_changed_cb (GtkComboBox *self, gpointer user_data)
+ald_type_combo_box_changed_cb (GtkComboBox *self, AlmanahAddLinkDialog *add_link_dialog)
 {
 	GtkTreeIter iter;
-	gchar *type;
-	const DiaryLinkType *link_type;
+	gchar *type_id;
+	AlmanahAddLinkDialogPrivate *priv = add_link_dialog->priv;
 
-	destroy_extra_table_widgets ();
+	destroy_extra_widgets (add_link_dialog);
 
 	if (gtk_combo_box_get_active_iter (self, &iter) == FALSE)
 		return;
 
-	gtk_tree_model_get (gtk_combo_box_get_model (self), &iter, 1, &type, -1);
-	link_type = diary_link_get_type (type);
-	gtk_table_resize (diary->ald_table, link_type->columns + 1, 2);
+	gtk_tree_model_get (gtk_combo_box_get_model (self), &iter, 1, &type_id, -1);
 
-	g_assert (link_type != NULL);
-	link_type->build_dialog_func (type, diary->ald_table);
+	if (priv->link != NULL)
+		g_object_unref (priv->link);
 
-	g_free (type);
+	priv->link = almanah_link_new (type_id);
+	almanah_link_build_dialog (priv->link, priv->ald_vbox);
+
+	g_free (type_id);
+}
+
+static void
+ald_show_cb (GtkWidget *widget, AlmanahAddLinkDialog *add_link_dialog)
+{
+	/* Select a default link type */
+	ald_type_combo_box_changed_cb (add_link_dialog->priv->ald_type_combo_box, add_link_dialog);
+}
+
+AlmanahLink *
+almanah_add_link_dialog_get_link (AlmanahAddLinkDialog *self)
+{
+	return g_object_ref (self->priv->link);
 }

Modified: trunk/src/add-link-dialog.h
==============================================================================
--- trunk/src/add-link-dialog.h	(original)
+++ trunk/src/add-link-dialog.h	Fri Oct 10 22:22:19 2008
@@ -1,32 +1,55 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifndef ALMANAH_ADD_LINK_DIALOG_H
+#define ALMANAH_ADD_LINK_DIALOG_H
+
 #include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
 
-#ifndef DIARY_ADD_LINK_DIALOG_H
-#define DIARY_ADD_LINK_DIALOG_H
+#include "link.h"
 
 G_BEGIN_DECLS
 
-void diary_add_link_dialog_setup (GtkBuilder *builder);
-void diary_hide_ald (void);
+#define ALMANAH_TYPE_ADD_LINK_DIALOG		(almanah_add_link_dialog_get_type ())
+#define ALMANAH_ADD_LINK_DIALOG(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_ADD_LINK_DIALOG, AlmanahAddLinkDialog))
+#define ALMANAH_ADD_LINK_DIALOG_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ALMANAH_TYPE_ADD_LINK_DIALOG, AlmanahAddLinkDialogClass))
+#define ALMANAH_IS_ADD_LINK_DIALOG(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ALMANAH_TYPE_ADD_LINK_DIALOG))
+#define ALMANAH_IS_ADD_LINK_DIALOG_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ALMANAH_TYPE_ADD_LINK_DIALOG))
+#define ALMANAH_ADD_LINK_DIALOG_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ALMANAH_TYPE_ADD_LINK_DIALOG, AlmanahAddLinkDialogClass))
+
+typedef struct _AlmanahAddLinkDialogPrivate	AlmanahAddLinkDialogPrivate;
+
+typedef struct {
+	GtkDialog parent;
+	AlmanahAddLinkDialogPrivate *priv;
+} AlmanahAddLinkDialog;
+
+typedef struct {
+	GtkDialogClass parent;
+} AlmanahAddLinkDialogClass;
+
+GType almanah_add_link_dialog_get_type (void);
+AlmanahAddLinkDialog *almanah_add_link_dialog_new (void);
+AlmanahLink *almanah_add_link_dialog_get_link (AlmanahAddLinkDialog *self);
 
 G_END_DECLS
 
-#endif /* !DIARY_ADD_LINK_DIALOG_H */
+#endif /* !ALMANAH_ADD_LINK_DIALOG_H */

Added: trunk/src/entry.c
==============================================================================
--- (empty file)
+++ trunk/src/entry.c	Fri Oct 10 22:22:19 2008
@@ -0,0 +1,203 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Almanah
+ * Copyright (C) Philip Withnall 2008 <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 <glib.h>
+
+#include "entry.h"
+
+static void almanah_entry_init (AlmanahEntry *self);
+static void almanah_entry_finalize (GObject *object);
+static void almanah_entry_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
+static void almanah_entry_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
+
+struct _AlmanahEntryPrivate {
+	GDate date;
+	gchar *content;
+};
+
+enum {
+	PROP_DAY = 1,
+	PROP_MONTH,
+	PROP_YEAR,
+	PROP_CONTENT
+};
+
+G_DEFINE_TYPE (AlmanahEntry, almanah_entry, G_TYPE_OBJECT)
+#define ALMANAH_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_ENTRY, AlmanahEntryPrivate))
+
+static void
+almanah_entry_class_init (AlmanahEntryClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (AlmanahEntryPrivate));
+
+	gobject_class->set_property = almanah_entry_set_property;
+	gobject_class->get_property = almanah_entry_get_property;
+	gobject_class->finalize = almanah_entry_finalize;
+
+	g_object_class_install_property (gobject_class, PROP_DAY,
+				g_param_spec_uint ("day",
+					"Day", "The day for which this is the entry.",
+					1, 31, 1,
+					G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+	g_object_class_install_property (gobject_class, PROP_MONTH,
+				g_param_spec_uint ("month",
+					"Month", "The month for which this is the entry.",
+					1, 12, 1,
+					G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+	g_object_class_install_property (gobject_class, PROP_YEAR,
+				g_param_spec_uint ("year",
+					"Year", "The year for which this is the entry.",
+					1, (1 << 16) - 1, 1,
+					G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+	g_object_class_install_property (gobject_class, PROP_CONTENT,
+				g_param_spec_string ("content",
+					"Content", "The textual content of the entry.",
+					NULL,
+					G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+almanah_entry_init (AlmanahEntry *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_ENTRY, AlmanahEntryPrivate);
+	g_date_clear (&(self->priv->date), 1);
+}
+
+static void
+almanah_entry_finalize (GObject *object)
+{
+	AlmanahEntryPrivate *priv = ALMANAH_ENTRY (object)->priv;
+
+	g_free (priv->content);
+	priv->content = NULL;
+
+	/* Chain up to the parent class */
+	G_OBJECT_CLASS (almanah_entry_parent_class)->finalize (object);
+}
+
+static void
+almanah_entry_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	AlmanahEntryPrivate *priv = ALMANAH_ENTRY (object)->priv;
+
+	switch (property_id) {
+		case PROP_DAY:
+			g_value_set_uint (value, g_date_get_day (&(priv->date)));
+			break;
+		case PROP_MONTH:
+			g_value_set_uint (value, g_date_get_month (&(priv->date)));
+			break;
+		case PROP_YEAR:
+			g_value_set_uint (value, g_date_get_year (&(priv->date)));
+			break;
+		case PROP_CONTENT:
+			g_value_set_string (value, priv->content);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
+}
+
+static void
+almanah_entry_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+	AlmanahEntryPrivate *priv = ALMANAH_ENTRY (object)->priv;
+
+	switch (property_id) {
+		case PROP_DAY:
+			g_date_set_day (&(priv->date), g_value_get_uint (value));
+			break;
+		case PROP_MONTH:
+			g_date_set_month (&(priv->date), g_value_get_uint (value));
+			break;
+		case PROP_YEAR:
+			g_date_set_year (&(priv->date), g_value_get_uint (value));
+			break;
+		case PROP_CONTENT:
+			almanah_entry_set_content (ALMANAH_ENTRY (object), 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;
+	}
+}
+
+AlmanahEntry *
+almanah_entry_new (GDate *date)
+{
+	return g_object_new (ALMANAH_TYPE_ENTRY,
+			     "day", g_date_get_day (date),
+			     "month", g_date_get_month (date),
+			     "year", g_date_get_year (date),
+			     NULL);
+}
+
+void
+almanah_entry_set_content (AlmanahEntry *self, const gchar *content)
+{
+	g_free (self->priv->content);
+	self->priv->content = g_strdup (content);
+	g_object_notify (G_OBJECT (self), "content");
+}
+
+gchar *
+almanah_entry_get_content (AlmanahEntry *self)
+{
+	return g_strdup (self->priv->content);
+}
+
+/* NOTE: Designed for use on the stack */
+void
+almanah_entry_get_date (AlmanahEntry *self, GDate *date)
+{
+	g_date_set_dmy (date,
+			g_date_get_day (&(self->priv->date)),
+			g_date_get_month (&(self->priv->date)),
+			g_date_get_year (&(self->priv->date)));
+}
+
+AlmanahEntryEditability
+almanah_entry_get_editability (AlmanahEntry *self)
+{
+	GDate current_date;
+	gint days_between;
+
+	g_date_set_time_t (&current_date, time (NULL));
+
+	/* Entries can't be edited before they've happened */
+	days_between = g_date_days_between (&(self->priv->date), &current_date);
+
+	if (days_between < 0)
+		return ALMANAH_ENTRY_FUTURE;
+	else if (days_between > ALMANAH_ENTRY_CUTOFF_AGE)
+		return ALMANAH_ENTRY_PAST;
+	else
+		return ALMANAH_ENTRY_EDITABLE;
+}
+
+gboolean
+almanah_entry_is_empty (AlmanahEntry *self)
+{
+	return (self->priv->content == NULL || self->priv->content[0] == '\0') ? TRUE : FALSE;
+}

Added: trunk/src/entry.h
==============================================================================
--- (empty file)
+++ trunk/src/entry.h	Fri Oct 10 22:22:19 2008
@@ -0,0 +1,65 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Almanah
+ * Copyright (C) Philip Withnall 2008 <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_ENTRY_H
+#define ALMANAH_ENTRY_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+	ALMANAH_ENTRY_EDITABLE = 1,
+	ALMANAH_ENTRY_FUTURE = 2,
+	ALMANAH_ENTRY_PAST = 0
+} AlmanahEntryEditability;
+
+/* The number of days after which a diary entry requires confirmation to be edited */
+#define ALMANAH_ENTRY_CUTOFF_AGE 14
+
+#define ALMANAH_TYPE_ENTRY		(almanah_entry_get_type ())
+#define ALMANAH_ENTRY(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_ENTRY, AlmanahEntry))
+#define ALMANAH_ENTRY_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ALMANAH_TYPE_ENTRY, AlmanahEntryClass))
+#define ALMANAH_IS_ENTRY(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ALMANAH_TYPE_ENTRY))
+#define ALMANAH_IS_ENTRY_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ALMANAH_TYPE_ENTRY))
+#define ALMANAH_ENTRY_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ALMANAH_TYPE_ENTRY, AlmanahEntryClass))
+
+typedef struct _AlmanahEntryPrivate	AlmanahEntryPrivate;
+
+typedef struct {
+	GObject parent;
+	AlmanahEntryPrivate *priv;
+} AlmanahEntry;
+
+typedef struct {
+	GObjectClass parent;
+} AlmanahEntryClass;
+
+GType almanah_entry_get_type (void);
+AlmanahEntry *almanah_entry_new (GDate *date);
+void almanah_entry_set_content (AlmanahEntry *self, const gchar *content);
+gchar *almanah_entry_get_content (AlmanahEntry *self);
+void almanah_entry_get_date (AlmanahEntry *self, GDate *date);
+AlmanahEntryEditability almanah_entry_get_editability (AlmanahEntry *self);
+gboolean almanah_entry_is_empty (AlmanahEntry *self);
+
+G_END_DECLS
+
+#endif /* !ALMANAH_ENTRY_H */

Modified: trunk/src/interface.c
==============================================================================
--- trunk/src/interface.c	(original)
+++ trunk/src/interface.c	Fri Oct 10 22:22:19 2008
@@ -27,74 +27,21 @@
 #include "search-dialog.h"
 #include "interface.h"
 
+const gchar *
+diary_get_interface_filename (void)
+{
+	if (g_file_test ("./data/almanah.ui", G_FILE_TEST_EXISTS) == TRUE)
+		return "./data/almanah.ui";
+	else
+		return PACKAGE_DATA_DIR"/almanah/almanah.ui";
+}
+
 GtkWidget *
 diary_create_interface (void)
 {
-	GError *error = NULL;
-	GtkBuilder *builder;
-
-	builder = gtk_builder_new ();
-
-	if (gtk_builder_add_from_file (builder, PACKAGE_DATA_DIR"/almanah/almanah.ui", &error) == FALSE &&
-	    gtk_builder_add_from_file (builder, "./data/almanah.ui", NULL) == FALSE) {
-		/* Show an error */
-		GtkWidget *dialog = gtk_message_dialog_new (NULL,
-				GTK_DIALOG_MODAL,
-				GTK_MESSAGE_ERROR,
-				GTK_BUTTONS_OK,
-				_("UI file \"%s/almanah/almanah.ui\" could not be loaded."), PACKAGE_DATA_DIR);
-		gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), error->message);
-		gtk_dialog_run (GTK_DIALOG (dialog));
-		gtk_widget_destroy (dialog);
-
-		g_error_free (error);
-		g_object_unref (builder);
-		diary_quit ();
-
-		return NULL;
-	}
-
-	gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE);
-	gtk_builder_connect_signals (builder, NULL);
-
-	/* Set up the main window */
-	/* TODO: This is horrible */
-	diary->main_window = GTK_WIDGET (gtk_builder_get_object (builder, "dry_main_window"));
-	diary->entry_view = GTK_TEXT_VIEW (gtk_builder_get_object (builder, "dry_mw_entry_view"));
-	diary->entry_buffer = gtk_text_view_get_buffer (diary->entry_view);
-	diary->calendar = GTK_CALENDAR (gtk_builder_get_object (builder, "dry_mw_calendar"));
-	diary->date_label = GTK_LABEL (gtk_builder_get_object (builder, "dry_mw_date_label"));
-	diary->add_button = GTK_BUTTON (gtk_builder_get_object (builder, "dry_mw_add_button"));
-	diary->remove_button = GTK_BUTTON (gtk_builder_get_object (builder, "dry_mw_remove_button"));
-	diary->view_button = GTK_BUTTON (gtk_builder_get_object (builder, "dry_mw_view_button"));
-	diary->add_action = GTK_ACTION (gtk_builder_get_object (builder, "dry_ui_add_link"));
-	diary->remove_action = GTK_ACTION (gtk_builder_get_object (builder, "dry_ui_remove_link"));
-	diary->links_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "dry_mw_links_store"));
-	diary->links_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (gtk_builder_get_object (builder, "dry_mw_links_tree_view")));
-	diary->link_value_column = GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (builder, "dry_mw_link_value_column"));
-	diary->link_value_renderer = GTK_CELL_RENDERER_TEXT (gtk_builder_get_object (builder, "dry_mw_link_value_renderer"));
-	diary_main_window_setup (builder);
-
-	/* Set up the add link dialogue */
-	diary->add_link_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "dry_add_link_dialog"));
-	diary->ald_type_combo_box = GTK_COMBO_BOX (gtk_builder_get_object (builder, "dry_ald_type_combo_box"));
-	diary->ald_table = GTK_TABLE (gtk_builder_get_object (builder, "dry_ald_table"));
-	diary->ald_type_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "dry_ald_type_store"));
-	diary_add_link_dialog_setup (builder);
-
-	/* Set up the search dialogue */
-	diary->search_dialog = GTK_WIDGET (gtk_builder_get_object (builder, "dry_search_dialog"));
-	diary->sd_search_entry = GTK_ENTRY (gtk_builder_get_object (builder, "dry_sd_search_entry"));
-	diary->sd_results_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "dry_sd_results_store"));
-	diary->sd_results_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (gtk_builder_get_object (builder, "dry_sd_results_tree_view")));
-	diary_search_dialog_setup (builder);
-
-	/* Embolden some labels */
-	diary_interface_embolden_label (GTK_LABEL (gtk_builder_get_object (builder, "dry_mw_calendar_label")));
-	diary_interface_embolden_label (GTK_LABEL (gtk_builder_get_object (builder, "dry_mw_attached_links_label")));
-	diary_interface_embolden_label (GTK_LABEL (gtk_builder_get_object (builder, "dry_sd_results_label")));
-
-	g_object_unref (builder);
+	diary->main_window = GTK_WIDGET (almanah_main_window_new ());
+	diary->add_link_dialog = GTK_WIDGET (almanah_add_link_dialog_new ());
+	diary->search_dialog = GTK_WIDGET (almanah_search_dialog_new ());
 
 	return diary->main_window;
 }
@@ -122,17 +69,19 @@
 {
 	GtkWidget *dialog;
 
-	g_warning (message);
+	g_warning ("%s", message);
 
 	dialog = gtk_message_dialog_new (GTK_WINDOW (parent_window),
 				GTK_DIALOG_MODAL,
 				GTK_MESSAGE_ERROR,
 				GTK_BUTTONS_OK,
-				message);
+				"%s", message);
 	gtk_dialog_run (GTK_DIALOG (dialog));
 	gtk_widget_destroy (dialog);
 }
 
+/* TODO: This exists so that different calendars can be highlighted according to which days have entries
+ * (i.e. the ones on the print dialogue). This should eventually be replaced by a custom calendar widget. */
 void
 diary_calendar_month_changed_cb (GtkCalendar *calendar, gpointer user_data)
 {
@@ -142,7 +91,7 @@
 
 	gtk_calendar_get_date (calendar, &year, &month, NULL);
 	month++;
-	days = diary_storage_manager_get_month_marked_days (diary->storage_manager, year, month);
+	days = almanah_storage_manager_get_month_marked_days (diary->storage_manager, year, month);
 
 	/* TODO: Don't like hard-coding the array length here */
 	gtk_calendar_clear_marks (calendar);

Modified: trunk/src/interface.h
==============================================================================
--- trunk/src/interface.h	(original)
+++ trunk/src/interface.h	Fri Oct 10 22:22:19 2008
@@ -24,6 +24,7 @@
 
 G_BEGIN_DECLS
 
+const gchar *diary_get_interface_filename (void);
 GtkWidget *diary_create_interface (void);
 void diary_interface_embolden_label (GtkLabel *label);
 void diary_interface_error (const gchar *message, GtkWidget *parent_window);

Modified: trunk/src/link.c
==============================================================================
--- trunk/src/link.c	(original)
+++ trunk/src/link.c	Fri Oct 10 22:22:19 2008
@@ -1,142 +1,327 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <glib.h>
-#include <math.h>
 #include <glib/gi18n.h>
+#include <math.h>
 #include <string.h>
 
-#include "main.h"
 #include "link.h"
+#include "main.h"
 
-#define LINK_TYPE(T) gchar *link_##T##_format_value (const DiaryLink *link); \
-gboolean link_##T##_view (const DiaryLink *link); \
-void link_##T##_build_dialog (const gchar *type, GtkTable *dialog_table); \
-void link_##T##_get_values (DiaryLink *link);
-
-/*LINK_TYPE (email)*/
-LINK_TYPE (uri)
-LINK_TYPE (file)
-LINK_TYPE (note)
+typedef struct {
+	gchar *type_id;
+	GType (*type_function) (void);
+} AlmanahLinkType;
+
+/* TODO: This is still a little hacky */
+
+#include "links/file.h"
+#include "links/note.h"
+#include "links/uri.h"
+
+static const AlmanahLinkType link_types[] = {
+	{ "file", &almanah_file_link_get_type },
+	{ "note", &almanah_note_link_get_type },
+	{ "uri", &almanah_uri_link_get_type }
+};
 
-/*
- * IMPORTANT:
- * Make sure this list is kept in alphabetical order by type.
- *
- * To add a link type, add an entry here then add a file in src/links
- * named after the link type, containing the format, view, dialogue-building
- * and value-getting functions referenced in this table.
- * Don't forget to add the function prototypes at the top of *this* file.
- */
-static const DiaryLinkType link_types[] = {
-	/* Type,	Name,			Description,				Icon,				Columns,	Format function,		View function,		Dialogue build function,	Get values function */
-	/*{ "email", 	N_("E-mail"),		N_("An e-mail you sent or received."),	"mail-read",			2,		&link_email_format_value,	&link_email_view,	&link_email_build_dialog,	&link_email_get_values },*/
-
-	/* Translators: These are the names and descriptions of the different link types. */
-	{ "file",	N_("File"),		N_("An attached file."),		"system-file-manager",		1,		&link_file_format_value,	&link_file_view,	&link_file_build_dialog,	&link_file_get_values },
-	{ "note", 	N_("Note"),		N_("A note about an important event."),	"emblem-important",		1,		&link_note_format_value,	&link_note_view,	&link_note_build_dialog,	&link_note_get_values },
-	{ "uri", 	N_("URI"),		N_("A URI of a file or web page."),	"applications-internet",	1,		&link_uri_format_value,		&link_uri_view,		&link_uri_build_dialog,		&link_uri_get_values }
+static void almanah_link_init (AlmanahLink *self);
+static void almanah_link_finalize (GObject *object);
+static void almanah_link_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
+static void almanah_link_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
+
+struct _AlmanahLinkPrivate {
+	gchar *value;
+	gchar *value2;
 };
 
-void
-diary_populate_link_model (GtkListStore *list_store, guint type_column, guint name_column, guint icon_name_column)
+enum {
+	PROP_TYPE_ID = 1,
+	PROP_NAME,
+	PROP_DESCRIPTION,
+	PROP_ICON_NAME,
+	PROP_VALUE,
+	PROP_VALUE2
+};
+
+G_DEFINE_ABSTRACT_TYPE (AlmanahLink, almanah_link, G_TYPE_OBJECT)
+#define ALMANAH_LINK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_LINK, AlmanahLinkPrivate))
+
+static void
+almanah_link_class_init (AlmanahLinkClass *klass)
 {
-	GtkTreeIter iter;
-	guint i;
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-	for (i = 0; i < G_N_ELEMENTS (link_types); i++) {
-		gtk_list_store_append (list_store, &iter);
-		gtk_list_store_set (list_store, &iter,
-				    type_column, link_types[i].type,
-				    name_column, _(link_types[i].name),
-				    icon_name_column, link_types[i].icon_name,
-				    -1);
+	g_type_class_add_private (klass, sizeof (AlmanahLinkPrivate));
+
+	gobject_class->set_property = almanah_link_set_property;
+	gobject_class->get_property = almanah_link_get_property;
+	gobject_class->finalize = almanah_link_finalize;
+
+	g_object_class_install_property (gobject_class, PROP_TYPE_ID,
+				g_param_spec_string ("type-id",
+					"Type ID", "The type ID of this link.",
+					NULL,
+					G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+	g_object_class_install_property (gobject_class, PROP_NAME,
+				g_param_spec_string ("name",
+					"Name", "The human-readable name for this link type.",
+					NULL,
+					G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+	g_object_class_install_property (gobject_class, PROP_DESCRIPTION,
+				g_param_spec_string ("description",
+					"Description", "The human-readable description for this link type.",
+					NULL,
+					G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+	g_object_class_install_property (gobject_class, PROP_ICON_NAME,
+				g_param_spec_string ("icon-name",
+					"Icon Name", "The icon name for this link type.",
+					NULL,
+					G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+	g_object_class_install_property (gobject_class, PROP_VALUE,
+				g_param_spec_string ("value",
+					"Value", "The first value of this link.",
+					NULL,
+					G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+	g_object_class_install_property (gobject_class, PROP_VALUE2,
+				g_param_spec_string ("value2",
+					"Value 2", "The second value of this link.",
+					NULL,
+					G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+almanah_link_init (AlmanahLink *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_LINK, AlmanahLinkPrivate);
+}
+
+static void
+almanah_link_finalize (GObject *object)
+{
+	AlmanahLinkPrivate *priv = ALMANAH_LINK (object)->priv;
+
+	g_free (priv->value);
+	g_free (priv->value2);
+
+	/* Chain up to the parent class */
+	G_OBJECT_CLASS (almanah_link_parent_class)->finalize (object);
+}
+
+static void
+almanah_link_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	AlmanahLinkPrivate *priv = ALMANAH_LINK (object)->priv;
+	AlmanahLinkClass *klass = ALMANAH_LINK_GET_CLASS (object);
+
+	switch (property_id) {
+		case PROP_TYPE_ID:
+			g_value_set_string (value, g_strdup (klass->type_id));
+			break;
+		case PROP_NAME:
+			g_value_set_string (value, g_strdup (klass->name));
+			break;
+		case PROP_DESCRIPTION:
+			g_value_set_string (value, g_strdup (klass->description));
+			break;
+		case PROP_ICON_NAME:
+			g_value_set_string (value, g_strdup (klass->icon_name));
+			break;
+		case PROP_VALUE:
+			g_value_set_string (value, g_strdup (priv->value));
+			break;
+		case PROP_VALUE2:
+			g_value_set_string (value, g_strdup (priv->value2));
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
 	}
 }
 
-gboolean
-diary_validate_link_type (const gchar *type)
+static void
+almanah_link_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
 {
-	return (diary_link_get_type (type) == NULL) ? FALSE : TRUE;
+	AlmanahLinkPrivate *priv = ALMANAH_LINK (object)->priv;
+
+	switch (property_id) {
+		case PROP_VALUE:
+			g_free (priv->value);
+			priv->value = g_value_dup_string (value);
+			break;
+		case PROP_VALUE2:
+			g_free (priv->value2);
+			priv->value2 = g_value_dup_string (value);
+			break;
+		default:
+			/* We don't have any other property... */
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+			break;
+	}
 }
 
-const DiaryLinkType *
-diary_link_get_type (const gchar *type)
+AlmanahLink *
+almanah_link_new (const gchar *type_id)
 {
-	guint lower_limit, upper_limit, temp;
-	gint comparison;
+	guint lower_limit, upper_limit;
 
 	/* Do a binary search */
 	lower_limit = 0;
 	upper_limit = G_N_ELEMENTS (link_types) - 1;
 
-	/* TODO: perhaps use GQuarks to make things less heavy on the strcmps */
-	do {
+	/* TODO: Use GQuarks to make things less heavy on the strcmp()s? */
+	while (TRUE) {
+		guint temp;
+		gint comparison;
+
 		temp = ceil ((lower_limit + upper_limit) / 2);
-		comparison = strcmp (type, link_types[temp].type);
+		comparison = strcmp (type_id, link_types[temp].type_id);
 
 		/* Exit condition */
 		if (lower_limit == upper_limit && comparison != 0)
 			return NULL;
 
-		if (comparison < 0)
+		if (comparison < 0) {
 			upper_limit = temp - 1; /* It's in the lower half */
-		else if (comparison > 0)
+		} else if (comparison > 0) {
 			lower_limit = temp + 1; /* It's in the upper half */
-		else
-			return &(link_types[temp]); /* Match! */
-	} while (TRUE);
+		} else {
+			/* Match! */
+			return g_object_new (link_types[temp].type_function (), NULL);
+		}
+	};
 
 	return NULL;
 }
 
 gchar *
-diary_link_format_value (const DiaryLink *link)
+almanah_link_format_value (AlmanahLink *self)
 {
-	const DiaryLinkType *link_type = diary_link_get_type (link->type);
-	g_assert (link_type != NULL);
-	return link_type->format_value_func (link);
+	AlmanahLinkClass *klass = ALMANAH_LINK_GET_CLASS (self);
+	g_assert (klass->format_value != NULL);
+	return klass->format_value (self);
 }
 
 gboolean
-diary_link_view (const DiaryLink *link)
+almanah_link_view (AlmanahLink *self)
 {
-	const DiaryLinkType *link_type = diary_link_get_type (link->type);
-	g_assert (link_type != NULL);
+	AlmanahLinkClass *klass = ALMANAH_LINK_GET_CLASS (self);
+	g_assert (klass->view != NULL);
 
 	if (diary->debug)
-		g_debug ("Viewing %s link ('%s', '%s')", link->type, link->value, link->value2);
+		g_debug ("Viewing %s link ('%s', '%s')", klass->type_id, self->priv->value, self->priv->value2);
 
-	return link_type->view_func (link);
+	return klass->view (self);
 }
 
 void
-diary_link_build_dialog (const DiaryLinkType *link_type)
+almanah_link_build_dialog (AlmanahLink *self, GtkVBox *parent_vbox)
 {
-	g_assert (link_type != NULL);
-	link_type->build_dialog_func (link_type->type, diary->ald_table);
+	AlmanahLinkClass *klass = ALMANAH_LINK_GET_CLASS (self);
+	g_assert (klass->build_dialog != NULL);
+	return klass->build_dialog (self, parent_vbox);
 }
 
 void
-diary_link_get_values (DiaryLink *link)
+almanah_link_get_values (AlmanahLink *self)
 {
-	const DiaryLinkType *link_type = diary_link_get_type (link->type);
-	g_assert (link_type != NULL);
-	link_type->get_values_func (link);
+	AlmanahLinkClass *klass = ALMANAH_LINK_GET_CLASS (self);
+	g_assert (klass->get_values != NULL);
+	return klass->get_values (self);
 }
+
+void
+almanah_link_populate_model (GtkListStore *list_store, guint type_id_column, guint name_column, guint icon_name_column)
+{
+	GtkTreeIter iter;
+	guint i;
+
+	for (i = 0; i < G_N_ELEMENTS (link_types); i++) {
+		AlmanahLink *link = g_object_new (link_types[i].type_function (), NULL);
+
+		if (link == NULL)
+			continue;
+
+		gtk_list_store_append (list_store, &iter);
+		gtk_list_store_set (list_store, &iter,
+				    type_id_column, link_types[i].type_id,
+				    name_column, almanah_link_get_name (link),
+				    icon_name_column, almanah_link_get_icon_name (link),
+				    -1);
+	}
+}
+
+const gchar *
+almanah_link_get_type_id (AlmanahLink *self)
+{
+	AlmanahLinkClass *klass = ALMANAH_LINK_GET_CLASS (self);
+	return klass->type_id;
+}
+
+const gchar *
+almanah_link_get_name (AlmanahLink *self)
+{
+	AlmanahLinkClass *klass = ALMANAH_LINK_GET_CLASS (self);
+	return klass->name;
+}
+
+const gchar *
+almanah_link_get_description (AlmanahLink *self)
+{
+	AlmanahLinkClass *klass = ALMANAH_LINK_GET_CLASS (self);
+	return klass->description;
+}
+
+const gchar *
+almanah_link_get_icon_name (AlmanahLink *self)
+{
+	AlmanahLinkClass *klass = ALMANAH_LINK_GET_CLASS (self);
+	return klass->icon_name;
+}
+
+gchar *
+almanah_link_get_value (AlmanahLink *self)
+{
+	return g_strdup (self->priv->value);
+}
+
+void
+almanah_link_set_value (AlmanahLink *self, const gchar *value)
+{
+	g_free (self->priv->value);
+	self->priv->value = g_strdup (value);
+}
+
+gchar *
+almanah_link_get_value2 (AlmanahLink *self)
+{
+	return g_strdup (self->priv->value2);
+}
+
+/* TODO: Perhaps an almanah_link_set_values (AlmanahLink *self, const gchar *value, const gchar *value2) API would be better? */
+
+void
+almanah_link_set_value2 (AlmanahLink *self, const gchar *value)
+{
+	g_free (self->priv->value2);
+	self->priv->value2 = g_strdup (value);
+}
+

Modified: trunk/src/link.h
==============================================================================
--- trunk/src/link.h	(original)
+++ trunk/src/link.h	Fri Oct 10 22:22:19 2008
@@ -1,56 +1,75 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifndef ALMANAH_LINK_H
+#define ALMANAH_LINK_H
+
 #include <glib.h>
+#include <glib-object.h>
 #include <gtk/gtk.h>
 
-#ifndef DIARY_LINK_H
-#define DIARY_LINK_H
-
 G_BEGIN_DECLS
 
+#define ALMANAH_TYPE_LINK		(almanah_link_get_type ())
+#define ALMANAH_LINK(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_LINK, AlmanahLink))
+#define ALMANAH_LINK_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ALMANAH_TYPE_LINK, AlmanahLinkClass))
+#define ALMANAH_IS_LINK(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ALMANAH_TYPE_LINK))
+#define ALMANAH_IS_LINK_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ALMANAH_TYPE_LINK))
+#define ALMANAH_LINK_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ALMANAH_TYPE_LINK, AlmanahLinkClass))
+
+typedef struct _AlmanahLinkPrivate	AlmanahLinkPrivate;
+
 typedef struct {
-	gchar *type;
-	gchar *value;
-	gchar *value2;
-} DiaryLink;
+	GObject parent;
+	AlmanahLinkPrivate *priv;
+} AlmanahLink;
 
 typedef struct {
-	gchar *type;
+	GObjectClass parent;
+
+	gchar *type_id;
 	gchar *name;
 	gchar *description;
 	gchar *icon_name;
-	guint columns;
-	gchar *(*format_value_func) (const DiaryLink *link);
-	gboolean (*view_func) (const DiaryLink *link);
-	void (*build_dialog_func) (const gchar *type, GtkTable *dialog_table);
-	void (*get_values_func) (DiaryLink *link);
-} DiaryLinkType;
-
-void diary_populate_link_model (GtkListStore *list_store, guint type_column, guint name_column, guint icon_name_column);
-gboolean diary_validate_link_type (const gchar *type);
-const DiaryLinkType *diary_link_get_type (const gchar *type);
-gchar *diary_link_format_value (const DiaryLink *link);
-gboolean diary_link_view (const DiaryLink *link);
-void diary_link_build_dialog (const DiaryLinkType *link_type);
-void diary_link_get_values (DiaryLink *link);
+
+	gchar *(*format_value) (AlmanahLink *link);
+	gboolean (*view) (AlmanahLink *link);
+	void (*build_dialog) (AlmanahLink *link, GtkVBox *parent_vbox);
+	void (*get_values) (AlmanahLink *link);
+} AlmanahLinkClass;
+
+GType almanah_link_get_type (void);
+AlmanahLink *almanah_link_new (const gchar *type_id);
+gchar *almanah_link_format_value (AlmanahLink *self);
+gboolean almanah_link_view (AlmanahLink *self);
+void almanah_link_build_dialog (AlmanahLink *self, GtkVBox *parent_vbox);
+void almanah_link_get_values (AlmanahLink *self);
+void almanah_link_populate_model (GtkListStore *list_store, guint type_id_column, guint name_column, guint icon_name_column);
+const gchar *almanah_link_get_type_id (AlmanahLink *self);
+const gchar *almanah_link_get_name (AlmanahLink *self);
+const gchar *almanah_link_get_description (AlmanahLink *self);
+const gchar *almanah_link_get_icon_name (AlmanahLink *self);
+gchar *almanah_link_get_value (AlmanahLink *self);
+void almanah_link_set_value (AlmanahLink *self, const gchar *value);
+gchar *almanah_link_get_value2 (AlmanahLink *self);
+void almanah_link_set_value2 (AlmanahLink *self, const gchar *value);
 
 G_END_DECLS
 
-#endif /* !DIARY_LINK_H */
+#endif /* !ALMANAH_LINK_H */

Modified: trunk/src/links/file.c
==============================================================================
--- trunk/src/links/file.c	(original)
+++ trunk/src/links/file.c	Fri Oct 10 22:22:19 2008
@@ -1,63 +1,109 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <glib.h>
-#include <gtk/gtk.h>
 #include <glib/gi18n.h>
-#include <gio/gio.h>
 
+#include "file.h"
+#include "../link.h"
 #include "../interface.h"
 #include "../main.h"
-#include "../link.h"
 
-gchar *
-link_file_format_value (const DiaryLink *link)
+/* TODO: Sort out build so that the links have a separate Makefile */
+
+static void almanah_file_link_init (AlmanahFileLink *self);
+static gchar *file_format_value (AlmanahLink *link);
+static gboolean file_view (AlmanahLink *link);
+static void file_build_dialog (AlmanahLink *link, GtkVBox *parent_vbox);
+static void file_get_values (AlmanahLink *link);
+
+struct _AlmanahFileLinkPrivate {
+	GtkWidget *chooser;
+};
+
+G_DEFINE_TYPE (AlmanahFileLink, almanah_file_link, ALMANAH_TYPE_LINK)
+#define ALMANAH_FILE_LINK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_FILE_LINK, AlmanahFileLinkPrivate))
+
+static void
+almanah_file_link_class_init (AlmanahFileLinkClass *klass)
+{
+	AlmanahLinkClass *link_class = ALMANAH_LINK_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (AlmanahFileLinkPrivate));
+
+	link_class->type_id = "file";
+	link_class->name = _("File");
+	link_class->description = _("An attached file.");
+	link_class->icon_name = "system-file-manager";
+
+	link_class->format_value = file_format_value;
+	link_class->view = file_view;
+	link_class->build_dialog = file_build_dialog;
+	link_class->get_values = file_get_values;
+}
+
+static void
+almanah_file_link_init (AlmanahFileLink *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_FILE_LINK, AlmanahFileLinkPrivate);
+}
+
+static gchar *
+file_format_value (AlmanahLink *link)
 {
-	return g_strdup (link->value);
+	return almanah_link_get_value (link);
 }
 
-gboolean
-link_file_view (const DiaryLink *link)
+static gboolean
+file_view (AlmanahLink *link)
 {
-	if (g_app_info_launch_default_for_uri (link->value, NULL, NULL) == FALSE) {
+	gchar *value = almanah_link_get_value (link);
+
+	if (g_app_info_launch_default_for_uri (value, NULL, NULL) == FALSE) {
+		g_free (value);
 		diary_interface_error (_("Due to an unknown error the file cannot be opened."), diary->main_window);
 		return FALSE;
 	}
+
+	g_free (value);
 	return TRUE;
 }
 
-void
-link_file_build_dialog (const gchar *type, GtkTable *dialog_table)
+static void
+file_build_dialog (AlmanahLink *link, GtkVBox *parent_vbox)
 {
-	GtkWidget *chooser;
+	AlmanahFileLinkPrivate *priv = ALMANAH_FILE_LINK (link)->priv;
 
-	chooser = gtk_file_chooser_button_new (_("Select File"), GTK_FILE_CHOOSER_ACTION_OPEN);
-	gtk_table_attach_defaults (dialog_table, chooser, 1, 3, 2, 3);
-	gtk_widget_show_all (GTK_WIDGET (dialog_table));
+	priv->chooser = gtk_file_chooser_button_new (_("Select File"), GTK_FILE_CHOOSER_ACTION_OPEN);
 
-	g_object_set_data (G_OBJECT (diary->add_link_dialog), "chooser", chooser);
+	gtk_box_pack_start (GTK_BOX (parent_vbox), priv->chooser, TRUE, TRUE, 0);
+	gtk_widget_show_all (GTK_WIDGET (parent_vbox));
 }
 
-void
-link_file_get_values (DiaryLink *link)
+static void
+file_get_values (AlmanahLink *link)
 {
-	GtkFileChooser *chooser = GTK_FILE_CHOOSER (g_object_get_data (G_OBJECT (diary->add_link_dialog), "chooser"));
-	link->value = gtk_file_chooser_get_uri (chooser);
-	link->value2 = NULL;
+	AlmanahFileLinkPrivate *priv = ALMANAH_FILE_LINK (link)->priv;
+	gchar *value = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (priv->chooser));
+
+	almanah_link_set_value (link, value);
+	g_free (value);
+
+	almanah_link_set_value2 (link, NULL);
 }

Added: trunk/src/links/file.h
==============================================================================
--- (empty file)
+++ trunk/src/links/file.h	Fri Oct 10 22:22:19 2008
@@ -0,0 +1,52 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Almanah
+ * Copyright (C) Philip Withnall 2008 <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_FILE_LINK_H
+#define ALMANAH_FILE_LINK_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "../link.h"
+
+G_BEGIN_DECLS
+
+#define ALMANAH_TYPE_FILE_LINK		(almanah_file_link_get_type ())
+#define ALMANAH_FILE_LINK(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_FILE_LINK, AlmanahFileLink))
+#define ALMANAH_FILE_LINK_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ALMANAH_TYPE_FILE_LINK, AlmanahFileLinkClass))
+#define ALMANAH_IS_FILE_LINK(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ALMANAH_TYPE_FILE_LINK))
+#define ALMANAH_IS_FILE_LINK_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ALMANAH_TYPE_FILE_LINK))
+#define ALMANAH_FILE_LINK_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ALMANAH_TYPE_FILE_LINK, AlmanahFileLinkClass))
+
+typedef struct _AlmanahFileLinkPrivate	AlmanahFileLinkPrivate;
+
+typedef struct {
+	AlmanahLink parent;
+	AlmanahFileLinkPrivate *priv;
+} AlmanahFileLink;
+
+typedef struct {
+	AlmanahLinkClass parent;
+} AlmanahFileLinkClass;
+
+GType almanah_file_link_get_type (void);
+
+G_END_DECLS
+
+#endif /* !ALMANAH_FILE_LINK_H */

Modified: trunk/src/links/note.c
==============================================================================
--- trunk/src/links/note.c	(original)
+++ trunk/src/links/note.c	Fri Oct 10 22:22:19 2008
@@ -1,54 +1,96 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <glib.h>
-#include <gtk/gtk.h>
 #include <glib/gi18n.h>
 
+#include "note.h"
+#include "../link.h"
 #include "../interface.h"
 #include "../main.h"
-#include "../link.h"
 
-gchar *
-link_note_format_value (const DiaryLink *link)
+/* TODO: Sort out build so that the links have a separate Makefile */
+
+static void almanah_note_link_init (AlmanahNoteLink *self);
+static gchar *note_format_value (AlmanahLink *link);
+static gboolean note_view (AlmanahLink *link);
+static void note_build_dialog (AlmanahLink *link, GtkVBox *parent_vbox);
+static void note_get_values (AlmanahLink *link);
+
+struct _AlmanahNoteLinkPrivate {
+	GtkWidget *text_view;
+};
+
+G_DEFINE_TYPE (AlmanahNoteLink, almanah_note_link, ALMANAH_TYPE_LINK)
+#define ALMANAH_NOTE_LINK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_NOTE_LINK, AlmanahNoteLinkPrivate))
+
+static void
+almanah_note_link_class_init (AlmanahNoteLinkClass *klass)
 {
-	return g_strdup (link->value);
+	AlmanahLinkClass *link_class = ALMANAH_LINK_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (AlmanahNoteLinkPrivate));
+
+	link_class->type_id = "note";
+	link_class->name = _("Note");
+	link_class->description = _("A note about an important event.");
+	link_class->icon_name = "emblem-important";
+
+	link_class->format_value = note_format_value;
+	link_class->view = note_view;
+	link_class->build_dialog = note_build_dialog;
+	link_class->get_values = note_get_values;
 }
 
-gboolean
-link_note_view (const DiaryLink *link)
+static void
+almanah_note_link_init (AlmanahNoteLink *self)
 {
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_NOTE_LINK, AlmanahNoteLinkPrivate);
+}
+
+static gchar *
+note_format_value (AlmanahLink *link)
+{
+	return almanah_link_get_value (link);
+}
+
+static gboolean
+note_view (AlmanahLink *link)
+{
+	gchar *value = almanah_link_get_value (link);
 	GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (diary->main_window),
 				GTK_DIALOG_DESTROY_WITH_PARENT,
 				GTK_MESSAGE_INFO,
 				GTK_BUTTONS_CLOSE,
-				link->value);
+				"%s", value);
 	gtk_dialog_run (GTK_DIALOG (dialog));
 	gtk_widget_destroy (dialog);
+	g_free (value);
 
 	return TRUE;
 }
 
-void
-link_note_build_dialog (const gchar *type, GtkTable *dialog_table)
+static void
+note_build_dialog (AlmanahLink *link, GtkVBox *parent_vbox)
 {
-	GtkWidget *text_view, *scrolled_window;
+	GtkWidget *scrolled_window;
+	AlmanahNoteLinkPrivate *priv = ALMANAH_NOTE_LINK (link)->priv;
 
 	scrolled_window = gtk_scrolled_window_new (NULL, NULL);
 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
@@ -56,26 +98,27 @@
 					GTK_POLICY_AUTOMATIC);
 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
 					     GTK_SHADOW_IN);
-	text_view = gtk_text_view_new ();
-	gtk_container_add (GTK_CONTAINER (scrolled_window), text_view);
-
-	gtk_table_attach_defaults (dialog_table, scrolled_window, 1, 3, 2, 3);
-	gtk_widget_show_all (GTK_WIDGET (dialog_table));
+	priv->text_view = gtk_text_view_new ();
+	gtk_container_add (GTK_CONTAINER (scrolled_window), priv->text_view);
 
-	g_object_set_data (G_OBJECT (diary->add_link_dialog), "text-view", text_view);
+	gtk_box_pack_start (GTK_BOX (parent_vbox), scrolled_window, TRUE, TRUE, 0);
+	gtk_widget_show_all (GTK_WIDGET (parent_vbox));
 }
 
-void
-link_note_get_values (DiaryLink *link)
+static void
+note_get_values (AlmanahLink *link)
 {
-	GtkTextView *text_view;
+	gchar *value;
 	GtkTextBuffer *buffer;
 	GtkTextIter start_iter, end_iter;
+	AlmanahNoteLinkPrivate *priv = ALMANAH_NOTE_LINK (link)->priv;
 
-	text_view = GTK_TEXT_VIEW (g_object_get_data (G_OBJECT (diary->add_link_dialog), "text-view"));
-	buffer = gtk_text_view_get_buffer (text_view);
+	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->text_view));
 	gtk_text_buffer_get_bounds (buffer, &start_iter, &end_iter);
 
-	link->value = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
-	link->value2 = NULL;
+	value = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
+	almanah_link_set_value (link, value);
+	g_free (value);
+
+	almanah_link_set_value2 (link, NULL);
 }

Added: trunk/src/links/note.h
==============================================================================
--- (empty file)
+++ trunk/src/links/note.h	Fri Oct 10 22:22:19 2008
@@ -0,0 +1,52 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Almanah
+ * Copyright (C) Philip Withnall 2008 <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_NOTE_LINK_H
+#define ALMANAH_NOTE_LINK_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "../link.h"
+
+G_BEGIN_DECLS
+
+#define ALMANAH_TYPE_NOTE_LINK		(almanah_note_link_get_type ())
+#define ALMANAH_NOTE_LINK(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_NOTE_LINK, AlmanahNoteLink))
+#define ALMANAH_NOTE_LINK_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ALMANAH_TYPE_NOTE_LINK, AlmanahNoteLinkClass))
+#define ALMANAH_IS_NOTE_LINK(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ALMANAH_TYPE_NOTE_LINK))
+#define ALMANAH_IS_NOTE_LINK_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ALMANAH_TYPE_NOTE_LINK))
+#define ALMANAH_NOTE_LINK_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ALMANAH_TYPE_NOTE_LINK, AlmanahNoteLinkClass))
+
+typedef struct _AlmanahNoteLinkPrivate	AlmanahNoteLinkPrivate;
+
+typedef struct {
+	AlmanahLink parent;
+	AlmanahNoteLinkPrivate *priv;
+} AlmanahNoteLink;
+
+typedef struct {
+	AlmanahLinkClass parent;
+} AlmanahNoteLinkClass;
+
+GType almanah_note_link_get_type (void);
+
+G_END_DECLS
+
+#endif /* !ALMANAH_NOTE_LINK_H */

Modified: trunk/src/links/uri.c
==============================================================================
--- trunk/src/links/uri.c	(original)
+++ trunk/src/links/uri.c	Fri Oct 10 22:22:19 2008
@@ -1,70 +1,114 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <glib.h>
-#include <gtk/gtk.h>
 #include <glib/gi18n.h>
-#include <gio/gio.h>
 
+#include "uri.h"
+#include "../link.h"
 #include "../interface.h"
 #include "../main.h"
-#include "../link.h"
 
-gchar *
-link_uri_format_value (const DiaryLink *link)
+/* TODO: Sort out build so that the links have a separate Makefile */
+
+static void almanah_uri_link_init (AlmanahURILink *self);
+static gchar *uri_format_value (AlmanahLink *link);
+static gboolean uri_view (AlmanahLink *link);
+static void uri_build_dialog (AlmanahLink *link, GtkVBox *parent_vbox);
+static void uri_get_values (AlmanahLink *link);
+
+struct _AlmanahURILinkPrivate {
+	GtkWidget *entry;
+};
+
+G_DEFINE_TYPE (AlmanahURILink, almanah_uri_link, ALMANAH_TYPE_LINK)
+#define ALMANAH_URI_LINK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_URI_LINK, AlmanahURILinkPrivate))
+
+static void
+almanah_uri_link_class_init (AlmanahURILinkClass *klass)
+{
+	AlmanahLinkClass *link_class = ALMANAH_LINK_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (AlmanahURILinkPrivate));
+
+	link_class->type_id = "uri";
+	link_class->name = _("URI");
+	link_class->description = _("A URI of a file or web page.");
+	link_class->icon_name = "applications-internet";
+
+	link_class->format_value = uri_format_value;
+	link_class->view = uri_view;
+	link_class->build_dialog = uri_build_dialog;
+	link_class->get_values = uri_get_values;
+}
+
+static void
+almanah_uri_link_init (AlmanahURILink *self)
 {
-	return g_strdup (link->value);
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_URI_LINK, AlmanahURILinkPrivate);
 }
 
-gboolean
-link_uri_view (const DiaryLink *link)
+static gchar *
+uri_format_value (AlmanahLink *link)
 {
-	if (g_app_info_launch_default_for_uri (link->value, NULL, NULL) == FALSE) {
+	return almanah_link_get_value (link);
+}
+
+static gboolean
+uri_view (AlmanahLink *link)
+{
+	gchar *value = almanah_link_get_value (link);
+	if (g_app_info_launch_default_for_uri (value, NULL, NULL) == FALSE) {
 		diary_interface_error (_("Due to an unknown error the URI cannot be opened."), diary->main_window);
+		g_free (value);
 		return FALSE;
 	}
+
+	g_free (value);
 	return TRUE;
 }
 
-void
-link_uri_build_dialog (const gchar *type, GtkTable *dialog_table)
+static void
+uri_build_dialog (AlmanahLink *link, GtkVBox *parent_vbox)
 {
-	GtkWidget *label, *entry;
+	GtkWidget *label, *hbox;
+	AlmanahURILinkPrivate *priv = ALMANAH_URI_LINK (link)->priv;
+
+	hbox = gtk_hbox_new (FALSE, 5);
 
 	label = gtk_label_new (_("URI"));
 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
 
-	entry = gtk_entry_new ();
-	gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
-
-	gtk_table_attach_defaults (dialog_table, label, 1, 2, 2, 3);
-	gtk_table_attach_defaults (dialog_table, entry, 2, 3, 2, 3);
+	priv->entry = gtk_entry_new ();
+	gtk_entry_set_activates_default (GTK_ENTRY (priv->entry), TRUE);
+	gtk_box_pack_start (GTK_BOX (hbox), priv->entry, TRUE, TRUE, 0);
 
-	gtk_widget_show_all (GTK_WIDGET (dialog_table));
-
-	g_object_set_data (G_OBJECT (diary->add_link_dialog), "entry", entry);
+	gtk_box_pack_start (GTK_BOX (parent_vbox), hbox, TRUE, TRUE, 0);
+	gtk_widget_show_all (GTK_WIDGET (parent_vbox));
 }
 
-void
-link_uri_get_values (DiaryLink *link)
+static void
+uri_get_values (AlmanahLink *link)
 {
-	GtkEntry *entry = GTK_ENTRY (g_object_get_data (G_OBJECT (diary->add_link_dialog), "entry"));
-	link->value = g_strdup (gtk_entry_get_text (entry));
-	link->value2 = NULL;
+	AlmanahURILinkPrivate *priv = ALMANAH_URI_LINK (link)->priv;
+
+	almanah_link_set_value (link, gtk_entry_get_text (GTK_ENTRY (priv->entry)));
+	almanah_link_set_value2 (link, NULL);
 }

Added: trunk/src/links/uri.h
==============================================================================
--- (empty file)
+++ trunk/src/links/uri.h	Fri Oct 10 22:22:19 2008
@@ -0,0 +1,52 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * Almanah
+ * Copyright (C) Philip Withnall 2008 <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_LINK_H
+#define ALMANAH_URI_LINK_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "../link.h"
+
+G_BEGIN_DECLS
+
+#define ALMANAH_TYPE_URI_LINK		(almanah_uri_link_get_type ())
+#define ALMANAH_URI_LINK(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_URI_LINK, AlmanahURILink))
+#define ALMANAH_URI_LINK_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ALMANAH_TYPE_URI_LINK, AlmanahURILinkClass))
+#define ALMANAH_IS_URI_LINK(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ALMANAH_TYPE_URI_LINK))
+#define ALMANAH_IS_URI_LINK_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ALMANAH_TYPE_URI_LINK))
+#define ALMANAH_URI_LINK_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ALMANAH_TYPE_URI_LINK, AlmanahURILinkClass))
+
+typedef struct _AlmanahURILinkPrivate	AlmanahURILinkPrivate;
+
+typedef struct {
+	AlmanahLink parent;
+	AlmanahURILinkPrivate *priv;
+} AlmanahURILink;
+
+typedef struct {
+	AlmanahLinkClass parent;
+} AlmanahURILinkClass;
+
+GType almanah_uri_link_get_type (void);
+
+G_END_DECLS
+
+#endif /* !ALMANAH_URI_LINK_H */

Modified: trunk/src/main-window.c
==============================================================================
--- trunk/src/main-window.c	(original)
+++ trunk/src/main-window.c	Fri Oct 10 22:22:19 2008
@@ -1,156 +1,325 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <config.h>
+#include <glib.h>
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
 #include <gtkspell/gtkspell.h>
 
+#include "main-window.h"
 #include "main.h"
-#include "storage-manager.h"
-#include "link.h"
-#include "add-link-dialog.h"
 #include "interface.h"
-#include "main-window.h"
+#include "add-link-dialog.h"
 #include "printing.h"
+#include "entry.h"
+#include "storage-manager.h"
+
+static void almanah_main_window_init (AlmanahMainWindow *self);
+static void almanah_main_window_dispose (GObject *object);
+static gboolean mw_delete_event_cb (GtkWindow *window, gpointer user_data);
+static void mw_entry_buffer_cursor_position_changed_cb (GObject *object, GParamSpec *pspec, AlmanahMainWindow *main_window);
+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);
+void mw_calendar_day_selected_cb (GtkCalendar *calendar, AlmanahMainWindow *main_window);
+static void mw_links_selection_changed_cb (GtkTreeSelection *tree_selection, AlmanahMainWindow *main_window);
+static void mw_links_value_data_cb (GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data);
+
+struct _AlmanahMainWindowPrivate {
+	GtkTextView *entry_view;
+	GtkTextBuffer *entry_buffer;
+	GtkCalendar *calendar;
+	GtkLabel *date_label;
+	GtkButton *add_button;
+	GtkButton *remove_button;
+	GtkButton *view_button;
+	GtkAction *add_action;
+	GtkAction *remove_action;
+	GtkListStore *link_store;
+	GtkTreeSelection *links_selection;
+	GtkTreeViewColumn *link_value_column;
+	GtkCellRendererText *link_value_renderer;
+	GtkToggleAction *bold_action;
+	GtkToggleAction *italic_action;
+	GtkToggleAction *underline_action;
+
+	gboolean updating_formatting_actions;
+
+	AlmanahEntry *current_entry;
+};
+
+G_DEFINE_TYPE (AlmanahMainWindow, almanah_main_window, GTK_TYPE_WINDOW)
+#define ALMANAH_MAIN_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_MAIN_WINDOW, AlmanahMainWindowPrivate))
+
+static void
+almanah_main_window_class_init (AlmanahMainWindowClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	g_type_class_add_private (klass, sizeof (AlmanahMainWindowPrivate));
+	gobject_class->dispose = almanah_main_window_dispose;
+}
+
+static void
+almanah_main_window_init (AlmanahMainWindow *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_MAIN_WINDOW, AlmanahMainWindowPrivate);
+
+	gtk_window_set_title (GTK_WINDOW (self), _("Almanah Diary"));
+	g_signal_connect (self, "delete-event", G_CALLBACK (mw_delete_event_cb), NULL);
+}
+
+static void
+almanah_main_window_dispose (GObject *object)
+{
+	AlmanahMainWindowPrivate *priv = ALMANAH_MAIN_WINDOW (object)->priv;
+
+	/* TODO: Free UI objects? */
+	if (priv->current_entry != NULL) {
+		g_object_unref (priv->current_entry);
+		priv->current_entry = NULL;
+	}
+
+	/* Chain up to the parent class */
+	G_OBJECT_CLASS (almanah_main_window_parent_class)->dispose (object);
+}
+
+AlmanahMainWindow *
+almanah_main_window_new (void)
+{
+	GtkBuilder *builder;
+	AlmanahMainWindow *main_window;
+	AlmanahMainWindowPrivate *priv;
+	GError *error = NULL;
+	const gchar *interface_filename = diary_get_interface_filename ();
+	const gchar *object_names[] = {
+		"dry_main_window",
+		"dry_mw_link_store",
+		"dry_mw_view_button_image",
+		"dry_ui_manager",
+		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);
 
-static void save_current_entry ();
-static void add_link_to_current_entry ();
-static void remove_link_from_current_entry ();
+		g_error_free (error);
+		g_object_unref (builder);
+
+		return NULL;
+	}
+
+	gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE);
+	main_window = ALMANAH_MAIN_WINDOW (gtk_builder_get_object (builder, "dry_main_window"));
+	gtk_builder_connect_signals (builder, main_window);
+
+	if (main_window == NULL) {
+		g_object_unref (builder);
+		return NULL;
+	}
+
+	priv = ALMANAH_MAIN_WINDOW (main_window)->priv;
+
+	/* Grab our child widgets */
+	priv->entry_view = GTK_TEXT_VIEW (gtk_builder_get_object (builder, "dry_mw_entry_view"));
+	priv->entry_buffer = gtk_text_view_get_buffer (priv->entry_view);
+	priv->calendar = GTK_CALENDAR (gtk_builder_get_object (builder, "dry_mw_calendar"));
+	priv->date_label = GTK_LABEL (gtk_builder_get_object (builder, "dry_mw_date_label"));
+	priv->add_button = GTK_BUTTON (gtk_builder_get_object (builder, "dry_mw_add_button"));
+	priv->remove_button = GTK_BUTTON (gtk_builder_get_object (builder, "dry_mw_remove_button"));
+	priv->view_button = GTK_BUTTON (gtk_builder_get_object (builder, "dry_mw_view_button"));
+	priv->add_action = GTK_ACTION (gtk_builder_get_object (builder, "dry_ui_add_link"));
+	priv->remove_action = GTK_ACTION (gtk_builder_get_object (builder, "dry_ui_remove_link"));
+	priv->link_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "dry_mw_link_store"));
+	priv->links_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (gtk_builder_get_object (builder, "dry_mw_links_tree_view")));
+	priv->link_value_column = GTK_TREE_VIEW_COLUMN (gtk_builder_get_object (builder, "dry_mw_link_value_column"));
+	priv->link_value_renderer = GTK_CELL_RENDERER_TEXT (gtk_builder_get_object (builder, "dry_mw_link_value_renderer"));
+	priv->bold_action = GTK_TOGGLE_ACTION (gtk_builder_get_object (builder, "dry_ui_bold"));;
+	priv->italic_action = GTK_TOGGLE_ACTION (gtk_builder_get_object (builder, "dry_ui_italic"));
+	priv->underline_action = GTK_TOGGLE_ACTION (gtk_builder_get_object (builder, "dry_ui_underline"));
+
+	/* Set up text formatting */
+	gtk_text_buffer_create_tag (priv->entry_buffer, "bold", 
+				    "weight", PANGO_WEIGHT_BOLD, 
+				    NULL);
+	gtk_text_buffer_create_tag (priv->entry_buffer, "italic",
+				    "style", PANGO_STYLE_ITALIC,
+				    NULL);
+	gtk_text_buffer_create_tag (priv->entry_buffer, "underline",
+				    "underline", PANGO_UNDERLINE_SINGLE,
+				    NULL);
+
+	/* Set up spell checking */
+	if (gtkspell_new_attach (priv->entry_view, NULL, &error) == FALSE) {
+		gchar *error_message = g_strdup_printf (_("The spelling checker could not be initialized: %s"), error->message);
+		diary_interface_error (error_message, NULL);
+		g_free (error_message);
+	}
 
-void mw_calendar_day_selected_cb (GtkCalendar *calendar, gpointer user_data);
-void mw_links_selection_changed_cb (GtkTreeSelection *tree_selection, gpointer user_data);
-void mw_links_value_data_cb (GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data);
+	/* Make sure we're notified if the cursor moves position so we can check the tag stack */
+	g_signal_connect (priv->entry_buffer, "notify::cursor-position", G_CALLBACK (mw_entry_buffer_cursor_position_changed_cb), main_window);
+
+	/* Connect up the formatting actions */
+	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);
+
+	/* Select the current day and month */
+	diary_calendar_month_changed_cb (priv->calendar, NULL);
+	mw_calendar_day_selected_cb (priv->calendar, main_window);
+
+	/* Set up the treeview */
+	g_signal_connect (priv->links_selection, "changed", G_CALLBACK (mw_links_selection_changed_cb), main_window);
+	gtk_tree_view_column_set_cell_data_func (priv->link_value_column, GTK_CELL_RENDERER (priv->link_value_renderer), mw_links_value_data_cb, NULL, NULL);
+
+	/* Prettify the UI */
+	diary_interface_embolden_label (GTK_LABEL (gtk_builder_get_object (builder, "dry_mw_calendar_label")));
+	diary_interface_embolden_label (GTK_LABEL (gtk_builder_get_object (builder, "dry_mw_attached_links_label")));
+
+	g_object_unref (builder);
+
+	return main_window;
+}
 
 static void
-save_current_entry ()
+save_current_entry (AlmanahMainWindow *self)
 {
 	GtkTextIter start_iter, end_iter;
 	gchar *entry_text;
-	guint year, month, day;
+	GDate date;
+	AlmanahMainWindowPrivate *priv = self->priv;
 
-	g_assert (diary->entry_buffer != NULL);
+	g_assert (priv->entry_buffer != NULL);
 
 	/* Don't save if it hasn't been/can't be edited */
-	if (gtk_text_view_get_editable (diary->entry_view) == FALSE ||
-	    gtk_text_buffer_get_modified (diary->entry_buffer) == FALSE)
+	if (priv->current_entry == NULL ||
+	    gtk_text_view_get_editable (priv->entry_view) == FALSE ||
+	    gtk_text_buffer_get_modified (priv->entry_buffer) == FALSE)
 		return;
 
 	/* Save the entry */
-	gtk_text_buffer_get_bounds (diary->entry_buffer, &start_iter, &end_iter);
-	entry_text = gtk_text_buffer_get_text (diary->entry_buffer, &start_iter, &end_iter, FALSE);
+	gtk_text_buffer_get_bounds (priv->entry_buffer, &start_iter, &end_iter);
+	entry_text = gtk_text_buffer_get_text (priv->entry_buffer, &start_iter, &end_iter, FALSE);
+	almanah_entry_set_content (priv->current_entry, entry_text);
+	g_free (entry_text);
 
-	gtk_calendar_get_date (diary->calendar, &year, &month, &day);
-	month++;
+	/* TODO: Serialise the buffer contents instead of just grabbing the text, so we can
+	 * keep tags between saves. Could use gtk_text_buffer_register_serialize_tagset() et al
+	 * for this, but could also add a more general framework for serialisation, which would aid
+	 * output/export to other formats from the program. */
+
+	almanah_entry_get_date (priv->current_entry, &date);
 
 	/* Mark the day on the calendar if the entry was non-empty (and deleted)
 	 * and update the state of the add link button. */
-	if (diary_storage_manager_set_entry (diary->storage_manager, year, month, day, entry_text) == FALSE) {
-		gtk_calendar_unmark_day (diary->calendar, day);
+	if (almanah_storage_manager_set_entry (diary->storage_manager, priv->current_entry) == FALSE) {
+		/* TODO: This sort of thing should be done by connecting to signals from the storage manager */
+		gtk_calendar_unmark_day (priv->calendar, g_date_get_day (&date));
 
-		gtk_widget_set_sensitive (GTK_WIDGET (diary->add_button), FALSE);
-		gtk_action_set_sensitive (diary->add_action, FALSE);
+		gtk_widget_set_sensitive (GTK_WIDGET (priv->add_button), FALSE);
+		gtk_action_set_sensitive (priv->add_action, FALSE);
 	} else {
-		gtk_calendar_mark_day (diary->calendar, day);
+		gtk_calendar_mark_day (priv->calendar, g_date_get_day (&date));
 
-		gtk_widget_set_sensitive (GTK_WIDGET (diary->add_button), TRUE);
-		gtk_action_set_sensitive (diary->add_action, TRUE);
+		gtk_widget_set_sensitive (GTK_WIDGET (priv->add_button), TRUE);
+		gtk_action_set_sensitive (priv->add_action, TRUE);
 	}
 
-	gtk_text_buffer_set_modified (diary->entry_buffer, FALSE);
-	g_free (entry_text);
+	gtk_text_buffer_set_modified (priv->entry_buffer, FALSE);
 }
 
 static void
-add_link_to_current_entry ()
+add_link_to_current_entry (AlmanahMainWindow *self)
 {
-	guint year, month, day;
 	GtkTreeIter iter;
-	const DiaryLinkType *link_type;
-	gchar *type;
-	DiaryLink link;
+	AlmanahMainWindowPrivate *priv = self->priv;
 
-	g_assert (diary->entry_buffer != NULL);
-	g_assert (gtk_text_buffer_get_char_count (diary->entry_buffer) != 0);
+	g_assert (priv->entry_buffer != NULL);
+	g_assert (gtk_text_buffer_get_char_count (priv->entry_buffer) != 0);
 
 	/* Ensure that something is selected and its widgets displayed */
-	g_signal_emit_by_name (diary->ald_type_combo_box, "changed", NULL, NULL);
+	/* TODO: Find a replacement for: g_signal_emit_by_name (diary->ald_type_combo_box, "changed", NULL, NULL);*/
 	gtk_widget_show_all (diary->add_link_dialog);
 
 	if (gtk_dialog_run (GTK_DIALOG (diary->add_link_dialog)) == GTK_RESPONSE_OK) {
-		if (gtk_combo_box_get_active_iter (diary->ald_type_combo_box, &iter) == FALSE)
-			return;
+		guint year, month, day;
+		GDate date;
+		AlmanahLink *link = almanah_add_link_dialog_get_link (ALMANAH_ADD_LINK_DIALOG (diary->add_link_dialog));
 
-		/* Get the link type, then the values entered in the dialogue (specific to the type) */
-		gtk_tree_model_get (GTK_TREE_MODEL (diary->ald_type_store), &iter, 1, &type, -1);
-		link_type = diary_link_get_type (type);
-		g_assert (link_type != NULL);
-		link.type = type;
-		link_type->get_values_func (&link);
+		if (link == NULL)
+			return;
 
 		/* Add to the DB */
-		gtk_calendar_get_date (diary->calendar, &year, &month, &day);
+		/* TODO: Clean this date stuff up and separate it out into its own function */
+		gtk_calendar_get_date (priv->calendar, &year, &month, &day);
 		month++;
-		diary_storage_manager_add_entry_link (diary->storage_manager,
-						      year, month, day,
-						      type,
-						      link.value,
-						      link.value2);
+		g_date_set_dmy (&date, day, month, year);
+
+		almanah_storage_manager_add_entry_link (diary->storage_manager, &date, link);
 
 		/* Add to the treeview */
-		gtk_list_store_append (diary->links_store, &iter);
-		gtk_list_store_set (diary->links_store, &iter,
-				    0, type,
-				    1, link.value,
-				    2, link.value2,
-				    3, link_type->icon_name,
+		gtk_list_store_append (priv->link_store, &iter);
+		gtk_list_store_set (priv->link_store, &iter,
+				    0, almanah_link_get_type_id (link),
+				    1, almanah_link_get_value (link),
+				    2, almanah_link_get_value2 (link),
+				    3, almanah_link_get_icon_name (link),
 				    -1);
 
-		g_free (type);
-		g_free (link.value);
-		g_free (link.value2);
+		g_object_unref (link);
 	}
-	diary_hide_ald ();
 }
 
 static void
-remove_link_from_current_entry ()
+remove_link_from_current_entry (AlmanahMainWindow *self)
 {
 	gchar *link_type;
 	guint year, month, day;
+	GDate date;
 	GtkTreeIter iter;
 	GtkTreeModel *model;
 	GList *links;
+	AlmanahMainWindowPrivate *priv = self->priv;
 
-	g_assert (diary->entry_buffer != NULL);
-	g_assert (gtk_text_buffer_get_char_count (diary->entry_buffer) != 0);
+	g_assert (priv->entry_buffer != NULL);
+	g_assert (gtk_text_buffer_get_char_count (priv->entry_buffer) != 0);
 
-	links = gtk_tree_selection_get_selected_rows (diary->links_selection, &model);
-	gtk_calendar_get_date (diary->calendar, &year, &month, &day);
+	links = gtk_tree_selection_get_selected_rows (priv->links_selection, &model);
+	gtk_calendar_get_date (priv->calendar, &year, &month, &day);
 	month++;
+	g_date_set_dmy (&date, day, month, year);
 
 	for (; links != NULL; links = links->next) {
 		gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) links->data);
 		gtk_tree_model_get (model, &iter, 0, &link_type, -1);
 
 		/* Remove it from the DB */
-		diary_storage_manager_remove_entry_link (diary->storage_manager, year, month, day, link_type);
+		almanah_storage_manager_remove_entry_link (diary->storage_manager, &date, link_type);
 
 		/* Remove it from the treeview */
 		gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
@@ -162,36 +331,77 @@
 }
 
 void
-diary_main_window_setup (GtkBuilder *builder)
+almanah_main_window_select_date (AlmanahMainWindow *self, GDate *date)
 {
-	GError *error = NULL;
+	gtk_calendar_select_month (self->priv->calendar, g_date_get_month (date) - 1, g_date_get_year (date));
+	gtk_calendar_select_day (self->priv->calendar, g_date_get_day (date));
+}
 
-	/* Select the current day and month */
-	diary_calendar_month_changed_cb (diary->calendar, NULL);
-	mw_calendar_day_selected_cb (diary->calendar, NULL);
+static void
+mw_entry_buffer_cursor_position_changed_cb (GObject *object, GParamSpec *pspec, AlmanahMainWindow *main_window)
+{
+	GtkTextIter iter;
+	AlmanahMainWindowPrivate *priv = main_window->priv;
+	GSList *tag_list = NULL;
+	gboolean bold_toggled = FALSE, italic_toggled = FALSE, underline_toggled = FALSE;
+
+	/* Only get the tag list if there's no selection (just an insertion cursor),
+	 * since we want the buttons untoggled if there's a selection. */
+	if (gtk_text_buffer_get_selection_bounds (priv->entry_buffer, &iter, NULL) == FALSE)
+		tag_list = gtk_text_iter_get_tags (&iter);
+
+	/* Block signal handlers for the formatting actions while we're executing,
+	 * so formatting doesn't get unwittingly changed. */
+	priv->updating_formatting_actions = TRUE;
+
+	while (tag_list != NULL) {
+		gchar *tag_name;
+		GtkToggleAction *action = NULL;
+
+		g_object_get (tag_list->data, "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;
+		}
 
-	/* Set up the treeview */
-	g_signal_connect (diary->links_selection, "changed", (GCallback) mw_links_selection_changed_cb, NULL);
-	gtk_tree_view_column_set_cell_data_func (diary->link_value_column, GTK_CELL_RENDERER (diary->link_value_renderer), mw_links_value_data_cb, NULL, NULL);
+		if (action) {
+			/* Force the toggle status on the action */
+			gtk_toggle_action_set_active (action, TRUE);
+		} else {
+			/* Print a warning about the unknown tag */
+			g_message (_("Unknown or duplicate text tag \"%s\" in entry. Ignoring."), tag_name);
+		}
 
-	if (gtkspell_new_attach (diary->entry_view, NULL, &error) == FALSE) {
-		gchar *error_message = g_strdup_printf (_("The spelling checker could not be initialized: %s"), error->message);
-		diary_interface_error (error_message, NULL);
-		g_free (error_message);
+		g_free (tag_name);
+		tag_list = tag_list->next;
 	}
-}
 
-void
-mw_select_date (GDate *date)
-{
-	gtk_calendar_select_month (diary->calendar, g_date_get_month (date) - 1, g_date_get_year (date));
-	gtk_calendar_select_day (diary->calendar, g_date_get_day (date));
+	g_slist_free (tag_list);
+
+	/* Untoggle the remaining actions */
+	if (bold_toggled == FALSE)
+		gtk_toggle_action_set_active (priv->bold_action, FALSE);
+	if (italic_toggled == FALSE)
+		gtk_toggle_action_set_active (priv->italic_action, FALSE);
+	if (underline_toggled == FALSE)
+		gtk_toggle_action_set_active (priv->underline_action, FALSE);
+
+	/* Unblock signals */
+	priv->updating_formatting_actions = FALSE;
 }
 
-gboolean
+static gboolean
 mw_delete_event_cb (GtkWindow *window, gpointer user_data)
 {
-	save_current_entry ();
+	save_current_entry (ALMANAH_MAIN_WINDOW (window));
 	diary_quit ();
 
 	return TRUE;
@@ -204,54 +414,81 @@
 }
 
 void
-mw_quit_activate_cb (GtkAction *action, gpointer user_data)
+mw_quit_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	save_current_entry ();
+	save_current_entry (main_window);
 	diary_quit ();
 }
 
 void
-mw_cut_activate_cb (GtkAction *action, gpointer user_data)
+mw_cut_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	GtkClipboard *clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (diary->main_window)), GDK_SELECTION_CLIPBOARD);
-	gtk_text_buffer_cut_clipboard (diary->entry_buffer, clipboard, TRUE);
+	GtkClipboard *clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (main_window)), GDK_SELECTION_CLIPBOARD);
+	gtk_text_buffer_cut_clipboard (main_window->priv->entry_buffer, clipboard, TRUE);
 }
 
 void
-mw_copy_activate_cb (GtkAction *action, gpointer user_data)
+mw_copy_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	GtkClipboard *clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (diary->main_window)), GDK_SELECTION_CLIPBOARD);
-	gtk_text_buffer_copy_clipboard (diary->entry_buffer, clipboard);
+	GtkClipboard *clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (main_window)), GDK_SELECTION_CLIPBOARD);
+	gtk_text_buffer_copy_clipboard (main_window->priv->entry_buffer, clipboard);
 }
 
 void
-mw_paste_activate_cb (GtkAction *action, gpointer user_data)
+mw_paste_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	GtkClipboard *clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (diary->main_window)), GDK_SELECTION_CLIPBOARD);
-	gtk_text_buffer_paste_clipboard (diary->entry_buffer, clipboard, NULL, TRUE);
+	GtkClipboard *clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (GTK_WIDGET (main_window)), GDK_SELECTION_CLIPBOARD);
+	gtk_text_buffer_paste_clipboard (main_window->priv->entry_buffer, clipboard, NULL, TRUE);
 }
 
 void
-mw_delete_activate_cb (GtkAction *action, gpointer user_data)
+mw_delete_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	gtk_text_buffer_delete_selection (diary->entry_buffer, TRUE, TRUE);
+	gtk_text_buffer_delete_selection (main_window->priv->entry_buffer, TRUE, TRUE);
 }
 
 void
 mw_search_activate_cb (GtkAction *action, gpointer user_data)
 {
-	/* Ensure everything's tidy first */
-	gtk_list_store_clear (diary->sd_results_store);
-	gtk_entry_set_text (diary->sd_search_entry, "");
-
-	/* Run the dialogue */
 	gtk_widget_show_all (diary->search_dialog);
 	gtk_dialog_run (GTK_DIALOG (diary->search_dialog));
-	gtk_widget_hide_all (diary->search_dialog);
+}
+
+static void
+apply_formatting (AlmanahMainWindow *self, const gchar *tag_name, gboolean applying)
+{
+	GtkTextIter start, end;
+
+	gtk_text_buffer_get_selection_bounds (self->priv->entry_buffer, &start, &end);
+	if (applying == TRUE)
+		gtk_text_buffer_apply_tag_by_name (self->priv->entry_buffer, tag_name, &start, &end);
+	else
+		gtk_text_buffer_remove_tag_by_name (self->priv->entry_buffer, tag_name, &start, &end);
+}
+
+static void
+mw_bold_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window)
+{
+	if (main_window->priv->updating_formatting_actions == FALSE)
+		apply_formatting (main_window, "bold", gtk_toggle_action_get_active (action));
+}
+
+static void
+mw_italic_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window)
+{
+	if (main_window->priv->updating_formatting_actions == FALSE)
+		apply_formatting (main_window, "italic", gtk_toggle_action_get_active (action));
+}
+
+static void
+mw_underline_toggled_cb (GtkToggleAction *action, AlmanahMainWindow *main_window)
+{
+	if (main_window->priv->updating_formatting_actions == FALSE)
+		apply_formatting (main_window, "underline", gtk_toggle_action_get_active (action));
 }
 
 void
-mw_about_activate_cb (GtkAction *action, gpointer user_data)
+mw_about_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
 	gchar *license, *description;
 	guint entry_count, link_count, character_count;
@@ -262,16 +499,16 @@
 		NULL
 	};
 	const gchar *license_parts[] = {
-		N_("Diary is free software: you can redistribute it and/or modify "
+		N_("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."),
-		N_("Diary is distributed in the hope that it will be useful, "
+		N_("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."),
 		N_("You should have received a copy of the GNU General Public License "
-		   "along with Diary.  If not, see <http://www.gnu.org/licenses/>."),
+		   "along with Almanah.  If not, see <http://www.gnu.org/licenses/>."),
 	};
 
 	license = g_strjoin ("\n\n",
@@ -280,13 +517,13 @@
 			  _(license_parts[2]),
 			  NULL);
 
-	diary_storage_manager_get_statistics (diary->storage_manager, &entry_count, &link_count, &character_count);
+	almanah_storage_manager_get_statistics (diary->storage_manager, &entry_count, &link_count, &character_count);
 	description = g_strdup_printf (_("A helpful diary keeper, storing %u entries with %u links and a total of %u characters."),
 				      entry_count,
 				      link_count,
 				      character_count);
 
-	gtk_show_about_dialog (GTK_WINDOW (diary->main_window),
+	gtk_show_about_dialog (GTK_WINDOW (main_window),
 				"version", VERSION,
 				"copyright", _("Copyright \xc2\xa9 2008 Philip Withnall"),
 				"comments", description,
@@ -309,36 +546,36 @@
 }
 
 void
-mw_jump_to_today_activate_cb (GtkAction *action, gpointer user_data)
+mw_jump_to_today_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
 	GDate current_date;
 	g_date_set_time_t (&current_date, time (NULL));
-	mw_select_date (&current_date);
+	almanah_main_window_select_date (main_window, &current_date);
 }
 
 void
-mw_add_link_activate_cb (GtkAction *action, gpointer user_data)
+mw_add_link_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	add_link_to_current_entry ();
+	add_link_to_current_entry (main_window);
 }
 
 void
-mw_remove_link_activate_cb (GtkAction *action, gpointer user_data)
+mw_remove_link_activate_cb (GtkAction *action, AlmanahMainWindow *main_window)
 {
-	remove_link_from_current_entry ();
+	remove_link_from_current_entry (main_window);
 }
 
 void
-mw_calendar_day_selected_cb (GtkCalendar *calendar, gpointer user_data)
+mw_calendar_day_selected_cb (GtkCalendar *calendar, AlmanahMainWindow *main_window)
 {
 	GDate calendar_date;
-	gchar calendar_string[100], *entry_text;
+	gchar calendar_string[100];
 	guint year, month, day;
-	DiaryLink **links;
+	AlmanahLink **links;
 	guint i;
 	GtkTreeIter iter;
-	const DiaryLinkType *link_type;
 	GtkSpell *gtkspell;
+	AlmanahMainWindowPrivate *priv = main_window->priv;
 
 	/* Update the date label */
 	gtk_calendar_get_date (calendar, &year, &month, &day);
@@ -347,55 +584,63 @@
 
 	/* Translators: This is a strftime()-format string for the date displayed at the top of the main window. */
 	g_date_strftime (calendar_string, sizeof (calendar_string), _("%A, %e %B %Y"), &calendar_date);
-	gtk_label_set_markup (diary->date_label, calendar_string);
-	diary_interface_embolden_label (diary->date_label);
+	gtk_label_set_markup (priv->date_label, calendar_string);
+	diary_interface_embolden_label (priv->date_label);
 
 	/* Update the entry */
-	entry_text = diary_storage_manager_get_entry (diary->storage_manager, year, month, day);
-	gtk_text_view_set_editable (diary->entry_view, diary_storage_manager_entry_is_editable (diary->storage_manager, year, month, day) != DIARY_ENTRY_FUTURE ? TRUE : FALSE);
-	gtk_text_buffer_set_modified (diary->entry_buffer, FALSE);
-
-	if (entry_text != NULL) {
-		gtk_text_buffer_set_text (diary->entry_buffer, entry_text, -1);
-		gtk_widget_set_sensitive (GTK_WIDGET (diary->add_button), TRUE);
-		gtk_action_set_sensitive (diary->add_action, TRUE);
+	if (priv->current_entry != NULL)
+		g_object_unref (priv->current_entry);
+	priv->current_entry = almanah_storage_manager_get_entry (diary->storage_manager, &calendar_date);
+	if (priv->current_entry == NULL)
+		priv->current_entry = almanah_entry_new (&calendar_date);
+
+	gtk_text_view_set_editable (priv->entry_view, almanah_entry_get_editability (priv->current_entry) != ALMANAH_ENTRY_FUTURE ? TRUE : FALSE);
+	gtk_text_buffer_set_modified (priv->entry_buffer, FALSE);
+
+	if (almanah_entry_is_empty (priv->current_entry) == FALSE) {
+		gchar *entry_content = almanah_entry_get_content (priv->current_entry);
+		gtk_text_buffer_set_text (priv->entry_buffer, entry_content, -1);
+		g_free (entry_content);
+
+		gtk_widget_set_sensitive (GTK_WIDGET (priv->add_button), TRUE);
+		gtk_action_set_sensitive (priv->add_action, TRUE);
 	} else {
-		gtk_text_buffer_set_text (diary->entry_buffer, "", -1);
-		gtk_widget_set_sensitive (GTK_WIDGET (diary->add_button), FALSE);
-		gtk_action_set_sensitive (diary->add_action, FALSE);
-	}
-	gtk_widget_set_sensitive (GTK_WIDGET (diary->remove_button), FALSE); /* Only sensitive if something's selected */
-	gtk_action_set_sensitive (diary->remove_action, FALSE);
-	gtk_widget_set_sensitive (GTK_WIDGET (diary->view_button), FALSE);
+		gtk_text_buffer_set_text (priv->entry_buffer, "", -1);
+		gtk_widget_set_sensitive (GTK_WIDGET (priv->add_button), FALSE);
+		gtk_action_set_sensitive (priv->add_action, FALSE);
+	}
 
-	g_free (entry_text);
+	gtk_widget_set_sensitive (GTK_WIDGET (priv->remove_button), FALSE); /* Only sensitive if something's selected */
+	gtk_action_set_sensitive (priv->remove_action, FALSE);
+	gtk_widget_set_sensitive (GTK_WIDGET (priv->view_button), FALSE);
 
 	/* Ensure the spell-checking is updated */
-	gtkspell = gtkspell_get_from_text_view (diary->entry_view);
-	gtkspell_recheck_all (gtkspell);
+	gtkspell = gtkspell_get_from_text_view (priv->entry_view);
+	if (gtkspell)
+		gtkspell_recheck_all (gtkspell);
 
 	/* List the entry's links */
-	gtk_list_store_clear (diary->links_store);
-	links = diary_storage_manager_get_entry_links (diary->storage_manager, year, month, day);
+	gtk_list_store_clear (priv->link_store);
+	links = almanah_storage_manager_get_entry_links (diary->storage_manager, &calendar_date);
 
 	i = 0;
 	while (links[i] != NULL) {
-		link_type = diary_link_get_type (links[i]->type);
+		gchar *value, *value2;
 
-		if (link_type != NULL) {
-			gtk_list_store_append (diary->links_store, &iter);
-			gtk_list_store_set (diary->links_store, &iter,
-					    0, links[i]->type,
-					    1, links[i]->value,
-					    2, links[i]->value2,
-					    3, link_type->icon_name,
-					    -1);
-		}
+		value = almanah_link_get_value (links[i]);
+		value2 = almanah_link_get_value2 (links[i]);
 
-		g_free (links[i]->type);
-		g_free (links[i]->value);
-		g_free (links[i]->value2);
-		g_slice_free (DiaryLink, links[i]);
+		gtk_list_store_append (priv->link_store, &iter);
+		gtk_list_store_set (priv->link_store, &iter,
+				    0, almanah_link_get_type_id (links[i]),
+				    1, value,
+				    2, value2,
+				    3, almanah_link_get_icon_name (links[i]),
+				    -1);
+
+		g_free (value);
+		g_free (value2);
+		g_object_unref (links[i]);
 
 		i++;
 	}
@@ -403,95 +648,130 @@
 	g_free (links);
 }
 
-void
-mw_links_selection_changed_cb (GtkTreeSelection *tree_selection, gpointer user_data)
+static void
+mw_links_selection_changed_cb (GtkTreeSelection *tree_selection, AlmanahMainWindow *main_window)
 {
+	AlmanahMainWindowPrivate *priv = main_window->priv;
+
 	if (gtk_tree_selection_count_selected_rows (tree_selection) == 0) {
-		gtk_widget_set_sensitive (GTK_WIDGET (diary->remove_button), FALSE);
-		gtk_widget_set_sensitive (GTK_WIDGET (diary->view_button), FALSE);
-		gtk_action_set_sensitive (diary->remove_action, FALSE);
+		gtk_widget_set_sensitive (GTK_WIDGET (priv->remove_button), FALSE);
+		gtk_widget_set_sensitive (GTK_WIDGET (priv->view_button), FALSE);
+		gtk_action_set_sensitive (priv->remove_action, FALSE);
 	} else {
-		gtk_widget_set_sensitive (GTK_WIDGET (diary->remove_button), TRUE);
-		gtk_widget_set_sensitive (GTK_WIDGET (diary->view_button), TRUE);
-		gtk_action_set_sensitive (diary->remove_action, TRUE);
+		gtk_widget_set_sensitive (GTK_WIDGET (priv->remove_button), TRUE);
+		gtk_widget_set_sensitive (GTK_WIDGET (priv->view_button), TRUE);
+		gtk_action_set_sensitive (priv->remove_action, TRUE);
 	}
 }
 
-void
+static void
 mw_links_value_data_cb (GtkTreeViewColumn *column, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
 {
-	gchar *new_value;
-	DiaryLink link;
+	gchar *new_value, *value, *value2, *type;
+	AlmanahLink *link;
 
-	gtk_tree_model_get (model, iter, 0, &(link.type), 1, &(link.value), 2, &(link.value2), -1);
+	/* TODO: Should really create a new model to render AlmanahLinks --- or at least attach the approprite AlmanahLink to each tree model row */
 
-	new_value = diary_link_format_value (&link);
+	gtk_tree_model_get (model, iter,
+			    0, &type,
+			    1, &value,
+			    2, &value2,
+			    -1);
+
+	link = almanah_link_new (type);
+	almanah_link_set_value (link, value);
+	almanah_link_set_value2 (link, value2);
+
+	new_value = almanah_link_format_value (link);
 	g_object_set (renderer, "text", new_value, NULL);
 	g_free (new_value);
 
-	g_free (link.type);
-	g_free (link.value);
-	g_free (link.value2);
+	g_free (type);
+	g_free (value);
+	g_free (value2);
+	g_object_unref (link);
 }
 
 void
-mw_links_tree_view_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data)
+mw_links_tree_view_row_activated_cb (GtkTreeView *tree_view, GtkTreePath *path, GtkTreeViewColumn *column, AlmanahMainWindow *main_window)
 {
-	DiaryLink link;
+	AlmanahLink *link;
+	gchar *value, *value2, *type;
 	GtkTreeIter iter;
 
-	gtk_tree_model_get_iter (GTK_TREE_MODEL (diary->links_store), &iter, path);
-	gtk_tree_model_get (GTK_TREE_MODEL (diary->links_store), &iter, 0, &(link.type), 1, &(link.value), 2, &(link.value2), -1);
+	gtk_tree_model_get_iter (GTK_TREE_MODEL (main_window->priv->link_store), &iter, path);
+	gtk_tree_model_get (GTK_TREE_MODEL (main_window->priv->link_store), &iter,
+			    0, &type,
+			    1, &value,
+			    2, &value2,
+			    -1);
+
+	link = almanah_link_new (type);
+	almanah_link_set_value (link, value);
+	almanah_link_set_value2 (link, value2);
 
 	/* NOTE: Link types should display their own errors, so one won't be displayed here. */
-	diary_link_view (&link);
+	almanah_link_view (link);
 
-	g_free (link.type);
-	g_free (link.value);
-	g_free (link.value2);
+	g_free (type);
+	g_free (value);
+	g_free (value2);
+	g_object_unref (link);
 }
 
 gboolean
-mw_entry_view_focus_out_event_cb (GtkWidget *entry_view, GdkEventFocus *event, gpointer user_data)
+mw_entry_view_focus_out_event_cb (GtkWidget *entry_view, GdkEventFocus *event, AlmanahMainWindow *main_window)
 {
-	save_current_entry ();
+	save_current_entry (main_window);
 	return FALSE;
 }
 
 void
-mw_add_button_clicked_cb (GtkButton *button, gpointer user_data)
+mw_add_button_clicked_cb (GtkButton *button, AlmanahMainWindow *main_window)
 {
-	add_link_to_current_entry ();
+	add_link_to_current_entry (main_window);
 }
 
 void
-mw_remove_button_clicked_cb (GtkButton *button, gpointer user_data)
+mw_remove_button_clicked_cb (GtkButton *button, AlmanahMainWindow *main_window)
 {
-	remove_link_from_current_entry ();
+	remove_link_from_current_entry (main_window);
 }
 
 void
-mw_view_button_clicked_cb (GtkButton *button, gpointer user_data)
+mw_view_button_clicked_cb (GtkButton *button, AlmanahMainWindow *main_window)
 {
-	DiaryLink link;
-	GtkTreeIter iter;
 	GList *links;
 	GtkTreeModel *model;
 
-	links = gtk_tree_selection_get_selected_rows (diary->links_selection, &model);
+	links = gtk_tree_selection_get_selected_rows (main_window->priv->links_selection, &model);
 
 	for (; links != NULL; links = links->next) {
+		AlmanahLink *link;
+		gchar *value, *value2, *type;
+		GtkTreeIter iter;
+
 		gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) links->data);
-		gtk_tree_model_get (model, &iter, 0, &(link.type), 1, &(link.value), 2, &(link.value2), -1);
+		gtk_tree_model_get (model, &iter,
+				    0, &type,
+				    1, &value,
+				    2, &value2,
+				    -1);
+
+		link = almanah_link_new (type);
+		almanah_link_set_value (link, value);
+		almanah_link_set_value2 (link, value2);
 
 		/* NOTE: Link types should display their own errors, so one won't be displayed here. */
-		diary_link_view (&link);
+		almanah_link_view (link);
 
-		g_free (link.type);
-		g_free (link.value);
-		g_free (link.value2);
+		g_free (type);
+		g_free (value);
+		g_free (value2);
+		g_object_unref (link);
 
 		gtk_tree_path_free (links->data);
 	}
+
 	g_list_free (links);
 }

Modified: trunk/src/main-window.h
==============================================================================
--- trunk/src/main-window.h	(original)
+++ trunk/src/main-window.h	Fri Oct 10 22:22:19 2008
@@ -1,33 +1,53 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <glib.h>
-#include <gtk/gtk.h>
+#ifndef ALMANAH_MAIN_WINDOW_H
+#define ALMANAH_MAIN_WINDOW_H
 
-#ifndef DIARY_MAIN_WINDOW_H
-#define DIARY_MAIN_WINDOW_H
+#include <glib.h>
+#include <glib-object.h>
 
 G_BEGIN_DECLS
 
-void diary_main_window_setup (GtkBuilder *builder);
-void mw_select_date (GDate *date);
+#define ALMANAH_TYPE_MAIN_WINDOW		(almanah_main_window_get_type ())
+#define ALMANAH_MAIN_WINDOW(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_MAIN_WINDOW, AlmanahMainWindow))
+#define ALMANAH_MAIN_WINDOW_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ALMANAH_TYPE_MAIN_WINDOW, AlmanahMainWindowClass))
+#define ALMANAH_IS_MAIN_WINDOW(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ALMANAH_TYPE_MAIN_WINDOW))
+#define ALMANAH_IS_MAIN_WINDOW_CLASS(k)		(G_TYPE_CHECK_CLASS_TYPE ((k), ALMANAH_TYPE_MAIN_WINDOW))
+#define ALMANAH_MAIN_WINDOW_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ALMANAH_TYPE_MAIN_WINDOW, AlmanahMainWindowClass))
+
+typedef struct _AlmanahMainWindowPrivate	AlmanahMainWindowPrivate;
+
+typedef struct {
+	GtkWindow parent;
+	AlmanahMainWindowPrivate *priv;
+} AlmanahMainWindow;
+
+typedef struct {
+	GtkWindowClass parent;
+} AlmanahMainWindowClass;
+
+GType almanah_main_window_get_type (void);
+AlmanahMainWindow *almanah_main_window_new (void);
+void almanah_main_window_setup (AlmanahMainWindow *self, GtkBuilder *builder);
+void almanah_main_window_select_date (AlmanahMainWindow *self, GDate *date);
 
 G_END_DECLS
 
-#endif /* !DIARY_MAIN_WINDOW_H */
+#endif /* !ALMANAH_MAIN_WINDOW_H */

Modified: trunk/src/main.c
==============================================================================
--- trunk/src/main.c	(original)
+++ trunk/src/main.c	Fri Oct 10 22:22:19 2008
@@ -33,7 +33,7 @@
 diary_quit (void)
 {
 	diary->quitting = TRUE;
-	diary_storage_manager_disconnect (diary->storage_manager);
+	almanah_storage_manager_disconnect (diary->storage_manager);
 
 	gtk_widget_destroy (diary->add_link_dialog);
 	gtk_widget_destroy (diary->search_dialog);
@@ -119,10 +119,10 @@
 
 	/* Open the DB */
 	db_filename = g_build_filename (g_get_user_data_dir (), "diary.db", NULL);
-	diary->storage_manager = diary_storage_manager_new (db_filename);
+	diary->storage_manager = almanah_storage_manager_new (db_filename);
 	g_free (db_filename);
 
-	diary_storage_manager_connect (diary->storage_manager);
+	almanah_storage_manager_connect (diary->storage_manager);
 
 	/* Create and show the interface */
 	diary_create_interface ();

Modified: trunk/src/main.h
==============================================================================
--- trunk/src/main.h	(original)
+++ trunk/src/main.h	Fri Oct 10 22:22:19 2008
@@ -32,35 +32,16 @@
 G_BEGIN_DECLS
 
 typedef struct {
-	DiaryStorageManager *storage_manager;
+	AlmanahStorageManager *storage_manager;
 #ifdef ENABLE_ENCRYPTION
 	GConfClient *gconf_client;
 #endif /* ENABLE_ENCRYPTION */
 
 	GtkWidget *main_window;
-	GtkTextView *entry_view;
-	GtkTextBuffer *entry_buffer;
-	GtkCalendar *calendar;
-	GtkLabel *date_label;
-	GtkButton *add_button;
-	GtkButton *remove_button;
-	GtkButton *view_button;
-	GtkAction *add_action;
-	GtkAction *remove_action;
-	GtkListStore *links_store;
-	GtkTreeSelection *links_selection;
-	GtkTreeViewColumn *link_value_column;
-	GtkCellRendererText *link_value_renderer;
-
 	GtkWidget *add_link_dialog;
-	GtkComboBox *ald_type_combo_box;
-	GtkTable *ald_table;
-	GtkListStore *ald_type_store;
-
 	GtkWidget *search_dialog;
-	GtkEntry *sd_search_entry;
-	GtkListStore *sd_results_store;
-	GtkTreeSelection *sd_results_selection;
+
+	GdkAtom native_serialisation_atom;
 
 	gboolean debug;
 	gboolean quitting;

Modified: trunk/src/printing.c
==============================================================================
--- trunk/src/printing.c	(original)
+++ trunk/src/printing.c	Fri Oct 10 22:22:19 2008
@@ -44,7 +44,8 @@
 static gboolean
 print_entry (GtkPrintOperation *operation, GtkPrintContext *context, DiaryPrintOperation *diary_operation)
 {
-	gchar *entry, title[100], *title_markup;
+	AlmanahEntry *entry;
+	gchar title[100], *title_markup;
 	PangoLayout *title_layout = NULL, *entry_layout;
 	PangoLayoutLine *entry_line;
 	PangoRectangle logical_extents;
@@ -53,10 +54,6 @@
 	gdouble title_y = 0, entry_y;
 	cairo_t *cr = NULL;
 
-	entry = diary_storage_manager_get_entry (diary->storage_manager, g_date_get_year (diary_operation->current_date),
-									 g_date_get_month (diary_operation->current_date),
-									 g_date_get_day (diary_operation->current_date));
-
 	if (diary_operation->current_line == 0) {
 		/* Set up the title layout */
 		title_layout = gtk_print_context_create_pango_layout (context);
@@ -78,13 +75,19 @@
 	pango_layout_set_width (entry_layout, gtk_print_context_get_width (context) * PANGO_SCALE);
 	pango_layout_set_ellipsize (entry_layout, PANGO_ELLIPSIZE_NONE);
 
-	if (entry == NULL) {
-		entry = g_strdup_printf ("<i>%s</i>", _("No entry for this date."));
-		pango_layout_set_markup (entry_layout, entry, -1);
+	entry = almanah_storage_manager_get_entry (diary->storage_manager, diary_operation->current_date);
+
+	if (almanah_entry_is_empty (entry)) {
+		gchar *entry_text = g_strdup_printf ("<i>%s</i>", _("No entry for this date."));
+		pango_layout_set_markup (entry_layout, entry_text, -1);
 	} else {
-		pango_layout_set_text (entry_layout, entry, -1);
+		gchar *entry_text = almanah_entry_get_content (entry);
+		pango_layout_set_text (entry_layout, entry_text, -1);
+		g_free (entry_text);
 	}
 
+	g_object_unref (entry);
+
 	/* Check we're not orphaning things */
 	entry_line = pango_layout_get_line_readonly (entry_layout, MIN (pango_layout_get_line_count (entry_layout), diary_operation->current_line + MAX_ORPHANS) - 1);
 	pango_layout_line_get_pixel_extents (entry_line, NULL, &logical_extents);
@@ -94,7 +97,6 @@
 		if (title_layout != NULL)
 			g_object_unref (title_layout);
 		g_object_unref (entry_layout);
-		g_free (entry);
 
 		diary_operation->current_line = 0;
 
@@ -124,7 +126,6 @@
 			if (title_layout != NULL)
 				g_object_unref (title_layout);
 			g_object_unref (entry_layout);
-			g_free (entry);
 
 			diary_operation->current_line = i;
 
@@ -147,7 +148,6 @@
 	if (title_layout != NULL)
 		g_object_unref (title_layout);
 	g_object_unref (entry_layout);
-	g_free (entry);
 
 	diary_operation->current_line = 0;
 

Modified: trunk/src/search-dialog.c
==============================================================================
--- trunk/src/search-dialog.c	(original)
+++ trunk/src/search-dialog.c	Fri Oct 10 22:22:19 2008
@@ -1,59 +1,149 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * 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 "main.h"
-#include "storage-manager.h"
 #include "search-dialog.h"
+#include "interface.h"
+#include "main.h"
 #include "main-window.h"
 
+static void almanah_search_dialog_init (AlmanahSearchDialog *self);
+static void sd_response_cb (GtkDialog *dialog, gint response_id, AlmanahSearchDialog *search_dialog);
+static void sd_results_selection_changed_cb (GtkTreeSelection *tree_selection, GtkWidget *button);
+
+struct _AlmanahSearchDialogPrivate {
+	GtkEntry *sd_search_entry;
+	GtkListStore *sd_results_store;
+	GtkTreeSelection *sd_results_selection;
+};
+
+G_DEFINE_TYPE (AlmanahSearchDialog, almanah_search_dialog, GTK_TYPE_DIALOG)
+#define ALMANAH_SEARCH_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_SEARCH_DIALOG, AlmanahSearchDialogPrivate))
+
 static void
-results_selection_changed_cb (GtkTreeSelection *tree_selection, GtkWidget *button)
+almanah_search_dialog_class_init (AlmanahSearchDialogClass *klass)
 {
-	gtk_widget_set_sensitive (button, gtk_tree_selection_count_selected_rows (tree_selection) == 0 ? FALSE : TRUE);
+	g_type_class_add_private (klass, sizeof (AlmanahSearchDialogPrivate));
 }
 
-void
-diary_search_dialog_setup (GtkBuilder *builder)
+static void
+almanah_search_dialog_init (AlmanahSearchDialog *self)
 {
-	g_signal_connect (diary->sd_results_selection, "changed", (GCallback) results_selection_changed_cb,
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_SEARCH_DIALOG, AlmanahSearchDialogPrivate);
+
+	g_signal_connect (self, "response", G_CALLBACK (sd_response_cb), self);
+	gtk_dialog_set_has_separator (GTK_DIALOG (self), FALSE);
+	gtk_window_set_modal (GTK_WINDOW (self), FALSE);
+	gtk_window_set_title (GTK_WINDOW (self), _("Search"));
+}
+
+AlmanahSearchDialog *
+almanah_search_dialog_new (void)
+{
+	GtkBuilder *builder;
+	AlmanahSearchDialog *search_dialog;
+	AlmanahSearchDialogPrivate *priv;
+	GError *error = NULL;
+	const gchar *interface_filename = diary_get_interface_filename ();
+	const gchar *object_names[] = {
+		"dry_search_dialog",
+		"dry_sd_search_button_image",
+		"dry_sd_results_store",
+		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);
+	search_dialog = ALMANAH_SEARCH_DIALOG (gtk_builder_get_object (builder, "dry_search_dialog"));
+	gtk_builder_connect_signals (builder, search_dialog);
+
+	if (search_dialog == NULL) {
+		g_object_unref (builder);
+		return NULL;
+	}
+
+	priv = ALMANAH_SEARCH_DIALOG (search_dialog)->priv;
+
+	/* Grab our child widgets */
+	priv->sd_search_entry = GTK_ENTRY (gtk_builder_get_object (builder, "dry_sd_search_entry"));
+	priv->sd_results_store = GTK_LIST_STORE (gtk_builder_get_object (builder, "dry_sd_results_store"));
+	priv->sd_results_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (gtk_builder_get_object (builder, "dry_sd_results_tree_view")));
+
+	g_signal_connect (priv->sd_results_selection, "changed", G_CALLBACK (sd_results_selection_changed_cb),
 			  gtk_builder_get_object (builder, "dry_sd_view_button"));
+
+	/* Prettify the UI */
+	diary_interface_embolden_label (GTK_LABEL (gtk_builder_get_object (builder, "dry_sd_results_label")));
+
+	g_object_unref (builder);
+
+	return search_dialog;
 }
 
-void
-sd_destroy_cb (GtkWindow *window, gpointer user_data)
+static void
+sd_results_selection_changed_cb (GtkTreeSelection *tree_selection, GtkWidget *button)
 {
-	gtk_widget_hide_all (diary->search_dialog);
+	gtk_widget_set_sensitive (button, gtk_tree_selection_count_selected_rows (tree_selection) == 0 ? FALSE : TRUE);
+}
+
+static void
+sd_response_cb (GtkDialog *dialog, gint response_id, AlmanahSearchDialog *search_dialog)
+{
+	/* Ensure everything's tidy before we leave the room */
+	gtk_list_store_clear (search_dialog->priv->sd_results_store);
+	gtk_entry_set_text (search_dialog->priv->sd_search_entry, "");
+
+	gtk_widget_hide_all (GTK_WIDGET (dialog));
 }
 
 void
-sd_search_button_clicked_cb (GtkButton *self, gpointer user_data)
+sd_search_button_clicked_cb (GtkButton *self, AlmanahSearchDialog *search_dialog)
 {
 	GDate *results;
 	guint result_count, i;
 	GtkTreeIter iter;
+	AlmanahSearchDialogPrivate *priv = search_dialog->priv;
 
-	result_count = diary_storage_manager_search_entries (diary->storage_manager,
-							     gtk_entry_get_text (diary->sd_search_entry), &results);
+	result_count = almanah_storage_manager_search_entries (diary->storage_manager,
+							       gtk_entry_get_text (priv->sd_search_entry), &results);
 
 	for (i = 0; i < result_count; i++) {
 		gchar formatted_date[100];
@@ -61,8 +151,8 @@
 		/* Translators: This is a strftime()-format string for the dates displayed in search results. */
 		g_date_strftime (formatted_date, sizeof (formatted_date), _("%A, %e %B %Y"), &results[i]);
 
-		gtk_list_store_append (diary->sd_results_store, &iter);
-		gtk_list_store_set (diary->sd_results_store, &iter,
+		gtk_list_store_append (priv->sd_results_store, &iter);
+		gtk_list_store_set (priv->sd_results_store, &iter,
 				    0, g_date_get_day (&results[i]),
 				    1, g_date_get_month (&results[i]),
 				    2, g_date_get_year (&results[i]),
@@ -86,7 +176,7 @@
 			    -1);
 
 	g_date_set_dmy (&date, day, month, year);
-	mw_select_date (&date);
+	almanah_main_window_select_date (ALMANAH_MAIN_WINDOW (diary->main_window), &date);
 }
 
 void
@@ -101,11 +191,11 @@
 }
 
 void
-sd_view_button_clicked_cb (GtkButton *self, gpointer user_data)
+sd_view_button_clicked_cb (GtkButton *self, AlmanahSearchDialog *search_dialog)
 {
 	GtkTreeIter iter;
 	GtkTreeModel *model;
 
-	if (gtk_tree_selection_get_selected (diary->sd_results_selection, &model, &iter) == TRUE)
+	if (gtk_tree_selection_get_selected (search_dialog->priv->sd_results_selection, &model, &iter) == TRUE)
 		select_date (model, &iter);
 }

Modified: trunk/src/search-dialog.h
==============================================================================
--- trunk/src/search-dialog.h	(original)
+++ trunk/src/search-dialog.h	Fri Oct 10 22:22:19 2008
@@ -1,31 +1,51 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <glib.h>
+#ifndef ALMANAH_SEARCH_DIALOG_H
+#define ALMANAH_SEARCH_DIALOG_H
 
-#ifndef DIARY_SEARCH_DIALOG_H
-#define DIARY_SEARCH_DIALOG_H
+#include <glib.h>
+#include <glib-object.h>
 
 G_BEGIN_DECLS
 
-void diary_search_dialog_setup (GtkBuilder *builder);
+#define ALMANAH_TYPE_SEARCH_DIALOG		(almanah_search_dialog_get_type ())
+#define ALMANAH_SEARCH_DIALOG(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_SEARCH_DIALOG, AlmanahSearchDialog))
+#define ALMANAH_SEARCH_DIALOG_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), ALMANAH_TYPE_SEARCH_DIALOG, AlmanahSearchDialogClass))
+#define ALMANAH_IS_SEARCH_DIALOG(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ALMANAH_TYPE_SEARCH_DIALOG))
+#define ALMANAH_IS_SEARCH_DIALOG_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ALMANAH_TYPE_SEARCH_DIALOG))
+#define ALMANAH_SEARCH_DIALOG_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ALMANAH_TYPE_SEARCH_DIALOG, AlmanahSearchDialogClass))
+
+typedef struct _AlmanahSearchDialogPrivate	AlmanahSearchDialogPrivate;
+
+typedef struct {
+	GtkDialog parent;
+	AlmanahSearchDialogPrivate *priv;
+} AlmanahSearchDialog;
+
+typedef struct {
+	GtkDialogClass parent;
+} AlmanahSearchDialogClass;
+
+GType almanah_search_dialog_get_type (void);
+AlmanahSearchDialog *almanah_search_dialog_new (void);
 
 G_END_DECLS
 
-#endif /* !DIARY_SEARCH_DIALOG_H */
+#endif /* !ALMANAH_SEARCH_DIALOG_H */

Modified: trunk/src/storage-manager.c
==============================================================================
--- trunk/src/storage-manager.c	(original)
+++ trunk/src/storage-manager.c	Fri Oct 10 22:22:19 2008
@@ -1,20 +1,20 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
@@ -30,18 +30,20 @@
 #endif /* ENABLE_ENCRYPTION */
 
 #include "main.h"
+/* TODO: Remove dependency on interface.h --- use GErrors better */
 #include "interface.h"
+#include "entry.h"
 #include "link.h"
 #include "storage-manager.h"
 
 #define ENCRYPTION_KEY_GCONF_PATH "/desktop/pgp/default_key"
 
-static void diary_storage_manager_init (DiaryStorageManager *self);
-static void diary_storage_manager_finalize (GObject *object);
-static void diary_storage_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
-static void diary_storage_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
+static void almanah_storage_manager_init (AlmanahStorageManager *self);
+static void almanah_storage_manager_finalize (GObject *object);
+static void almanah_storage_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
+static void almanah_storage_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
 
-struct _DiaryStorageManagerPrivate {
+struct _AlmanahStorageManagerPrivate {
 	gchar *filename, *plain_filename;
 	sqlite3 *connection;
 	gboolean decrypted;
@@ -51,25 +53,25 @@
 	PROP_FILENAME = 1
 };
 
-G_DEFINE_TYPE (DiaryStorageManager, diary_storage_manager, G_TYPE_OBJECT)
-#define DIARY_STORAGE_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), DIARY_TYPE_STORAGE_MANAGER, DiaryStorageManagerPrivate))
+G_DEFINE_TYPE (AlmanahStorageManager, almanah_storage_manager, G_TYPE_OBJECT)
+#define ALMANAH_STORAGE_MANAGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ALMANAH_TYPE_STORAGE_MANAGER, AlmanahStorageManagerPrivate))
 
 GQuark
-diary_storage_manager_error_quark (void)
+almanah_storage_manager_error_quark (void)
 {
-  return g_quark_from_static_string ("diary-storage-manager-error-quark");
+	return g_quark_from_static_string ("almanah-storage-manager-error-quark");
 }
 
 static void
-diary_storage_manager_class_init (DiaryStorageManagerClass *klass)
+almanah_storage_manager_class_init (AlmanahStorageManagerClass *klass)
 {
 	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-	g_type_class_add_private (klass, sizeof (DiaryStorageManagerPrivate));
+	g_type_class_add_private (klass, sizeof (AlmanahStorageManagerPrivate));
 
-	gobject_class->set_property = diary_storage_manager_set_property;
-	gobject_class->get_property = diary_storage_manager_get_property;
-	gobject_class->finalize = diary_storage_manager_finalize;
+	gobject_class->set_property = almanah_storage_manager_set_property;
+	gobject_class->get_property = almanah_storage_manager_get_property;
+	gobject_class->finalize = almanah_storage_manager_finalize;
 
 	g_object_class_install_property (gobject_class, PROP_FILENAME,
 				g_param_spec_string ("filename",
@@ -79,44 +81,44 @@
 }
 
 static void
-diary_storage_manager_init (DiaryStorageManager *self)
+almanah_storage_manager_init (AlmanahStorageManager *self)
 {
-	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, DIARY_TYPE_STORAGE_MANAGER, DiaryStorageManagerPrivate);
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, ALMANAH_TYPE_STORAGE_MANAGER, AlmanahStorageManagerPrivate);
 	self->priv->filename = NULL;
 	self->priv->plain_filename = NULL;
 	self->priv->decrypted = FALSE;
 }
 
 /**
- * diary_storage_manager_new:
+ * almanah_storage_manager_new:
  * @filename: database filename to open
  *
- * Creates a new #DiaryStorageManager, connected to the given database @filename.
+ * Creates a new #AlmanahStorageManager, connected to the given database @filename.
  *
- * Return value: the new #DiaryStorageManager
+ * Return value: the new #AlmanahStorageManager
  **/
-DiaryStorageManager *
-diary_storage_manager_new (const gchar *filename)
+AlmanahStorageManager *
+almanah_storage_manager_new (const gchar *filename)
 {
-	return g_object_new (DIARY_TYPE_STORAGE_MANAGER, "filename", filename, NULL);
+	return g_object_new (ALMANAH_TYPE_STORAGE_MANAGER, "filename", filename, NULL);
 }
 
 static void
-diary_storage_manager_finalize (GObject *object)
+almanah_storage_manager_finalize (GObject *object)
 {
-	DiaryStorageManagerPrivate *priv = DIARY_STORAGE_MANAGER_GET_PRIVATE (object);
+	AlmanahStorageManagerPrivate *priv = ALMANAH_STORAGE_MANAGER (object)->priv;
 
 	g_free (priv->filename);
 	g_free (priv->plain_filename);
 
 	/* Chain up to the parent class */
-	G_OBJECT_CLASS (diary_storage_manager_parent_class)->finalize (object);
+	G_OBJECT_CLASS (almanah_storage_manager_parent_class)->finalize (object);
 }
 
 static void
-diary_storage_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+almanah_storage_manager_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
 {
-	DiaryStorageManagerPrivate *priv = DIARY_STORAGE_MANAGER_GET_PRIVATE (object);
+	AlmanahStorageManagerPrivate *priv = ALMANAH_STORAGE_MANAGER (object)->priv;
 
 	switch (property_id) {
 	  	case PROP_FILENAME:
@@ -130,9 +132,9 @@
 }
 
 static void
-diary_storage_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+almanah_storage_manager_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
 {
-	DiaryStorageManagerPrivate *priv = DIARY_STORAGE_MANAGER_GET_PRIVATE (object);
+	AlmanahStorageManagerPrivate *priv = ALMANAH_STORAGE_MANAGER (object)->priv;
 
 	switch (property_id) {
 		case PROP_FILENAME:
@@ -147,7 +149,7 @@
 }
 
 static void
-create_tables (DiaryStorageManager *self)
+create_tables (AlmanahStorageManager *self)
 {
 	/* Dates are stored in ISO 8601 format...sort of */
 	guint i;
@@ -160,7 +162,7 @@
 
 	i = 0;
 	while (queries[i] != NULL)
-		diary_storage_manager_query_async (self, queries[i++], NULL, NULL);
+		almanah_storage_manager_query_async (self, queries[i++], NULL, NULL);
 }
 
 #ifdef ENABLE_ENCRYPTION
@@ -173,14 +175,14 @@
 } CipherOperation;
 
 static gboolean
-prepare_gpgme (DiaryStorageManager *self, gboolean encrypting, CipherOperation *operation, GError **error)
+prepare_gpgme (AlmanahStorageManager *self, gboolean encrypting, CipherOperation *operation, GError **error)
 {
 	gpgme_error_t gpgme_error;
 
 	/* Check OpenPGP's supported */
 	gpgme_error = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP);
 	if (gpgme_error != GPG_ERR_NO_ERROR) {
-		g_set_error (error, DIARY_STORAGE_MANAGER_ERROR, DIARY_STORAGE_MANAGER_ERROR_UNSUPPORTED,
+		g_set_error (error, ALMANAH_STORAGE_MANAGER_ERROR, ALMANAH_STORAGE_MANAGER_ERROR_UNSUPPORTED,
 			     _("GPGME doesn't support OpenPGP: %s"),
 			     gpgme_strerror (gpgme_error));
 		return FALSE;
@@ -189,7 +191,7 @@
 	/* Set up for the operation */
 	gpgme_error = gpgme_new (&(operation->context));
 	if (gpgme_error != GPG_ERR_NO_ERROR) {
-		g_set_error (error, DIARY_STORAGE_MANAGER_ERROR, DIARY_STORAGE_MANAGER_ERROR_CREATING_CONTEXT,
+		g_set_error (error, ALMANAH_STORAGE_MANAGER_ERROR, ALMANAH_STORAGE_MANAGER_ERROR_CREATING_CONTEXT,
 			     _("Error creating cipher context: %s"),
 			     gpgme_strerror (gpgme_error));
 		return FALSE;
@@ -203,7 +205,7 @@
 }
 
 static gboolean
-open_db_files (DiaryStorageManager *self, gboolean encrypting, CipherOperation *operation, GError **error)
+open_db_files (AlmanahStorageManager *self, gboolean encrypting, CipherOperation *operation, GError **error)
 {
 	GError *io_error = NULL;
 	gpgme_error_t gpgme_error;
@@ -218,7 +220,7 @@
 	/* Pass it to GPGME */
 	gpgme_error = gpgme_data_new_from_fd (&(operation->gpgme_cipher), g_io_channel_unix_get_fd (operation->cipher_io_channel));
 	if (gpgme_error != GPG_ERR_NO_ERROR) {
-		g_set_error (error, DIARY_STORAGE_MANAGER_ERROR, DIARY_STORAGE_MANAGER_ERROR_OPENING_FILE,
+		g_set_error (error, ALMANAH_STORAGE_MANAGER_ERROR, ALMANAH_STORAGE_MANAGER_ERROR_OPENING_FILE,
 			     _("Error opening encrypted database file \"%s\": %s"),
 			     self->priv->filename,
 			     gpgme_strerror (gpgme_error));
@@ -238,7 +240,7 @@
 	/* Pass it to GPGME */
 	gpgme_error = gpgme_data_new_from_fd (&(operation->gpgme_plain), g_io_channel_unix_get_fd (operation->plain_io_channel));
 	if (gpgme_error != GPG_ERR_NO_ERROR) {
-		g_set_error (error, DIARY_STORAGE_MANAGER_ERROR, DIARY_STORAGE_MANAGER_ERROR_OPENING_FILE,
+		g_set_error (error, ALMANAH_STORAGE_MANAGER_ERROR, ALMANAH_STORAGE_MANAGER_ERROR_OPENING_FILE,
 			     _("Error opening plain database file \"%s\": %s"),
 			     self->priv->plain_filename,
 			     gpgme_strerror (gpgme_error));
@@ -288,7 +290,7 @@
 }
 
 static gboolean
-decrypt_database (DiaryStorageManager *self, GError **error)
+decrypt_database (AlmanahStorageManager *self, GError **error)
 {
 	GError *preparation_error = NULL;
 	CipherOperation *operation;
@@ -308,7 +310,7 @@
 	gpgme_error = gpgme_op_decrypt_verify (operation->context, operation->gpgme_cipher, operation->gpgme_plain);
 	if (gpgme_error != GPG_ERR_NO_ERROR) {
 		cipher_operation_free (operation);
-		g_set_error (error, DIARY_STORAGE_MANAGER_ERROR, DIARY_STORAGE_MANAGER_ERROR_DECRYPTING,
+		g_set_error (error, ALMANAH_STORAGE_MANAGER_ERROR, ALMANAH_STORAGE_MANAGER_ERROR_DECRYPTING,
 			     _("Error decrypting database: %s"),
 			     gpgme_strerror (gpgme_error));
 		return FALSE;
@@ -321,7 +323,7 @@
 }
 
 static gboolean
-encrypt_database (DiaryStorageManager *self, const gchar *encryption_key, GError **error)
+encrypt_database (AlmanahStorageManager *self, const gchar *encryption_key, GError **error)
 {
 	GError *preparation_error = NULL;
 	CipherOperation *operation;
@@ -341,7 +343,7 @@
 	gpgme_error = gpgme_get_key (operation->context, encryption_key, &gpgme_keys[0], FALSE);
 	if (gpgme_error != GPG_ERR_NO_ERROR || gpgme_keys[0] == NULL) {
 		cipher_operation_free (operation);
-		g_set_error (error, DIARY_STORAGE_MANAGER_ERROR, DIARY_STORAGE_MANAGER_ERROR_GETTING_KEY,
+		g_set_error (error, ALMANAH_STORAGE_MANAGER_ERROR, ALMANAH_STORAGE_MANAGER_ERROR_GETTING_KEY,
 			     _("Error getting encryption key: %s"),
 			     gpgme_strerror (gpgme_error));
 		return FALSE;
@@ -362,7 +364,7 @@
 	if (gpgme_error != GPG_ERR_NO_ERROR) {
 		cipher_operation_free (operation);
 
-		g_set_error (error, DIARY_STORAGE_MANAGER_ERROR, DIARY_STORAGE_MANAGER_ERROR_ENCRYPTING,
+		g_set_error (error, ALMANAH_STORAGE_MANAGER_ERROR, ALMANAH_STORAGE_MANAGER_ERROR_ENCRYPTING,
 			     _("Error encrypting database: %s"),
 			     gpgme_strerror (gpgme_error));
 		return FALSE;
@@ -373,7 +375,7 @@
 
 	/* Delete the plain file and wait for the idle function to quit us */
 	if (g_unlink (self->priv->plain_filename) != 0) {
-		g_set_error (error, DIARY_STORAGE_MANAGER_ERROR, DIARY_STORAGE_MANAGER_ERROR_ENCRYPTING,
+		g_set_error (error, ALMANAH_STORAGE_MANAGER_ERROR, ALMANAH_STORAGE_MANAGER_ERROR_ENCRYPTING,
 			     _("Could not delete plain database file \"%s\"."),
 			     self->priv->plain_filename);
 		return FALSE;
@@ -411,7 +413,7 @@
 #endif /* ENABLE_ENCRYPTION */
 
 void
-diary_storage_manager_connect (DiaryStorageManager *self)
+almanah_storage_manager_connect (AlmanahStorageManager *self)
 {
 #ifdef ENABLE_ENCRYPTION
 	/* If we're decrypting, don't bother if the cipher file doesn't exist
@@ -422,7 +424,7 @@
 		/* If both files exist, throw an error. We can't be sure which is the corrupt one,
 		 * and attempting to go any further may jeopardise the good one. */
 		if (g_file_test (self->priv->plain_filename, G_FILE_TEST_IS_REGULAR) == TRUE) {
-			gchar *error_message = g_strdup_printf (_("Both an encrypted and plaintext version of the database exist as \"%s\" and \"%s\", and one is likely corrupt. Please delete the corrupt one (i.e. one which is 0KiB in size) before continuing. If neither file is 0KiB, the problem will most likely have been caused by Diary being unable to encrypt the database, so you should move the first file."),
+			gchar *error_message = g_strdup_printf (_("Both an encrypted and plaintext version of the database exist as \"%s\" and \"%s\", and one is likely corrupt. Please delete the corrupt one (i.e. one which is 0KiB in size) before continuing. If neither file is 0KiB, the problem will most likely have been caused by Almanah being unable to encrypt the database, so you should move the first file."),
 							self->priv->filename, 
 							self->priv->plain_filename);
 			diary_interface_error (error_message, diary->main_window);
@@ -460,7 +462,7 @@
 }
 
 void
-diary_storage_manager_disconnect (DiaryStorageManager *self)
+almanah_storage_manager_disconnect (AlmanahStorageManager *self)
 {
 #ifdef ENABLE_ENCRYPTION
 	gchar *encryption_key;
@@ -479,7 +481,7 @@
 #ifdef ENABLE_ENCRYPTION
 	encryption_key = get_encryption_key ();
 	if (encryption_key == NULL) {
-		g_message (_("Error getting encryption key: GConf key \"%s\" invalid or empty. Your diary will not be encrypted; please install Seahorse and set up a default key, or ignore this message."), ENCRYPTION_KEY_GCONF_PATH);
+		g_message (_("Error getting encryption key: GConf key \"%s\" invalid or empty. Your almanah will not be encrypted; please install Seahorse and set up a default key, or ignore this message."), ENCRYPTION_KEY_GCONF_PATH);
 		if (diary->quitting == TRUE)
 			diary_quit_real ();
 		return;
@@ -487,10 +489,10 @@
 
 	/* Encrypt the plain DB file */
 	if (encrypt_database (self, encryption_key, &error) != TRUE) {
-		if (error->code == DIARY_STORAGE_MANAGER_ERROR_GETTING_KEY) {
+		if (error->code == ALMANAH_STORAGE_MANAGER_ERROR_GETTING_KEY) {
 			/* Log an error about being unable to get the key
 			 * then continue without encrypting. */
-			g_warning (error->message);
+			g_warning ("%s", error->message);
 		} else {
 			/* Display an error */
 			diary_interface_error (error->message, diary->main_window);
@@ -506,19 +508,19 @@
 #endif /* ENABLE_ENCRYPTION */
 }
 
-DiaryQueryResults *
-diary_storage_manager_query (DiaryStorageManager *self, const gchar *query, ...)
+AlmanahQueryResults *
+almanah_storage_manager_query (AlmanahStorageManager *self, const gchar *query, ...)
 {
-	DiaryStorageManagerPrivate *priv = DIARY_STORAGE_MANAGER_GET_PRIVATE (self);
+	AlmanahStorageManagerPrivate *priv = self->priv;
 	gchar *error_message, *new_query;
 	va_list params;
-	DiaryQueryResults *results;
+	AlmanahQueryResults *results;
 
 	va_start (params, query);
 	new_query = sqlite3_vmprintf (query, params);
 	va_end (params);
 
-	results = g_slice_new (DiaryQueryResults);
+	results = g_slice_new (AlmanahQueryResults);
 
 	if (diary->debug)
 		g_debug ("Database query: %s", new_query);
@@ -536,16 +538,16 @@
 }
 
 void
-diary_storage_manager_free_results (DiaryQueryResults *results)
+almanah_storage_manager_free_results (AlmanahQueryResults *results)
 {
 	sqlite3_free_table (results->data);
-	g_slice_free (DiaryQueryResults, results);
+	g_slice_free (AlmanahQueryResults, results);
 }
 
 gboolean
-diary_storage_manager_query_async (DiaryStorageManager *self, const gchar *query, const DiaryQueryCallback callback, gpointer user_data, ...)
+almanah_storage_manager_query_async (AlmanahStorageManager *self, const gchar *query, const AlmanahQueryCallback callback, gpointer user_data, ...)
 {
-	DiaryStorageManagerPrivate *priv = DIARY_STORAGE_MANAGER_GET_PRIVATE (self);
+	AlmanahStorageManagerPrivate *priv = self->priv;
 	gchar *error_message, *new_query;
 	va_list params;
 
@@ -569,18 +571,18 @@
 }
 
 gboolean
-diary_storage_manager_get_statistics (DiaryStorageManager *self, guint *entry_count, guint *link_count, guint *character_count)
+almanah_storage_manager_get_statistics (AlmanahStorageManager *self, guint *entry_count, guint *link_count, guint *character_count)
 {
-	DiaryQueryResults *results;
+	AlmanahQueryResults *results;
 
 	/* Get the number of entries and the number of letters */
-	results = diary_storage_manager_query (self, "SELECT COUNT (year), SUM (LENGTH (content)) FROM entries");
+	results = almanah_storage_manager_query (self, "SELECT COUNT (year), SUM (LENGTH (content)) FROM entries");
 	if (results->rows != 1) {
 		*entry_count = 0;
 		*character_count = 0;
 		*link_count = 0;
 
-		diary_storage_manager_free_results (results);
+		almanah_storage_manager_free_results (results);
 		return FALSE;
 	} else {
 		*entry_count = atoi (results->data[2]);
@@ -592,119 +594,121 @@
 
 		*character_count = atoi (results->data[3]);
 	}
-	diary_storage_manager_free_results (results);
+	almanah_storage_manager_free_results (results);
 
 	/* Get the number of links */
-	results = diary_storage_manager_query (self, "SELECT COUNT (year) FROM entry_links");
+	results = almanah_storage_manager_query (self, "SELECT COUNT (year) FROM entry_links");
 	if (results->rows != 1) {
 		*link_count = 0;
 
-		diary_storage_manager_free_results (results);
+		almanah_storage_manager_free_results (results);
 		return FALSE;
 	} else {
 		*link_count = atoi (results->data[1]);
 	}
-	diary_storage_manager_free_results (results);
+	almanah_storage_manager_free_results (results);
 
 	return TRUE;
 }
 
 gboolean
-diary_storage_manager_entry_exists (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day)
+almanah_storage_manager_entry_exists (AlmanahStorageManager *self, GDate *date)
 {
-	DiaryQueryResults *results;
+	AlmanahQueryResults *results;
 	gboolean exists = FALSE;
 
-	results = diary_storage_manager_query (self, "SELECT day FROM entries WHERE year = %u AND month = %u AND day = %u LIMIT 1", year, month, day);
+	results = almanah_storage_manager_query (self, "SELECT day FROM entries WHERE year = %u AND month = %u AND day = %u LIMIT 1",
+					       g_date_get_year (date),
+					       g_date_get_month (date),
+					       g_date_get_day (date));
 
 	if (results->rows == 1)
 		exists = TRUE;
 
-	diary_storage_manager_free_results (results);
-	return exists;
-}
-
-DiaryEntryEditable
-diary_storage_manager_entry_is_editable (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day)
-{
-	GDate current_date, entry_date;
-	gint days_between;
-
-	g_date_set_time_t (&current_date, time (NULL));
-	g_date_set_dmy (&entry_date, day, month, year);
+	almanah_storage_manager_free_results (results);
 
-	/* Entries can't be edited before they've happened */
-	days_between = g_date_days_between (&entry_date, &current_date);
-
-	if (days_between < 0)
-		return DIARY_ENTRY_FUTURE;
-	else if (days_between > DIARY_ENTRY_CUTOFF_AGE)
-		return DIARY_ENTRY_PAST;
-	else
-		return DIARY_ENTRY_EDITABLE;
+	return exists;
 }
 
-/* NOTE: Free results with g_free */
-gchar *
-diary_storage_manager_get_entry (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day)
+/**
+ * almanah_storage_manager_get_entry:
+ * @self: a #AlmanahStorageManager
+ * @date: the date of the entry
+ *
+ * Gets the entry for the specified day from the database.
+ * If an entry can't be found it will return %NULL.
+ *
+ * Return value: an #AlmanahEntry or %NULL
+ **/
+AlmanahEntry *
+almanah_storage_manager_get_entry (AlmanahStorageManager *self, GDate *date)
 {
-	gchar *content;
-	DiaryQueryResults *results;
+	AlmanahQueryResults *results;
+	AlmanahEntry *entry;
 
-	results = diary_storage_manager_query (self, "SELECT content FROM entries WHERE year = %u AND month = %u AND day = %u", year, month, day);
+	results = almanah_storage_manager_query (self, "SELECT content FROM entries WHERE year = %u AND month = %u AND day = %u",
+						 g_date_get_year (date),
+						 g_date_get_month (date),
+						 g_date_get_day (date));
 
 	if (results->rows != 1) {
 		/* Invalid number of rows returned. */
-		diary_storage_manager_free_results (results);
+		almanah_storage_manager_free_results (results);
 		return NULL;
 	}
 
-	content = g_strdup (results->data[1]);
-	diary_storage_manager_free_results (results);
+	entry = almanah_entry_new (date);
+	almanah_entry_set_content (entry, results->data[1]);
+	almanah_storage_manager_free_results (results);
 
-	return content;
+	return entry;
 }
 
 /**
- * diary_storage_manager_set_entry:
- * @self: a #DiaryStorageManager
- * @year: the entry's year
- * @month: the entry's month
- * @day: the entry's day
- * @content: the content for the entry
+ * almanah_storage_manager_set_entry:
+ * @self: a #AlmanahStorageManager
+ * @entry: an #AlmanahEntry
  *
- * Saves the @content for the specified entry in the database. If
- * @content is empty or %NULL, it will ask if the user wants to delete
+ * Saves the specified @entry in the database. If the @entry
+ * content is empty or %NULL, it will ask if the user wants to delete
  * the entry for that date. It will return %TRUE if the content is
  * non-empty, and %FALSE otherwise.
  *
  * Return value: %TRUE if the entry is non-empty
  **/
 gboolean
-diary_storage_manager_set_entry (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day, const gchar *content)
+almanah_storage_manager_set_entry (AlmanahStorageManager *self, AlmanahEntry *entry)
 {
-	gboolean entry_exists = diary_storage_manager_entry_exists (self, year, month, day);
-	DiaryEntryEditable editability = diary_storage_manager_entry_is_editable (self, year, month, day);
+	GDate date;
+	gchar *content;
+	gboolean entry_exists;
+	AlmanahEntryEditability editability;
+
+	almanah_entry_get_date (entry, &date);
+	entry_exists = almanah_storage_manager_entry_exists (self, &date);
+	editability = almanah_entry_get_editability (entry);
+	content = almanah_entry_get_content (entry);
 
 	/* Make sure they're editable: don't allow entries in the future to be edited,
 	 * but allow entries in the past to be added or edited, as long as permission is given.
 	 * If an entry is being deleted, permission must be given for that as a priority. */
-	if (editability == DIARY_ENTRY_FUTURE) {
+	if (editability == ALMANAH_ENTRY_FUTURE) {
+		g_free (content);
 		return TRUE;
-	} else if (editability == DIARY_ENTRY_PAST &&
+	} else if (editability == ALMANAH_ENTRY_PAST &&
 		   content != NULL && content[0] != '\0') {
-		GDate date;
 		gchar date_string[100];
 		GtkWidget *dialog;
 
-		g_date_set_dmy (&date, day, month, year);
+		g_free (content);
+
 		g_date_strftime (date_string, sizeof (date_string), "%A, %e %B %Y", &date);
 
 		dialog = gtk_message_dialog_new (GTK_WINDOW (diary->main_window),
 							    GTK_DIALOG_MODAL,
 							    GTK_MESSAGE_QUESTION,
 							    GTK_BUTTONS_NONE,
-							    _("Are you sure you want to edit this diary entry for %s?"),
+							    _("Are you sure you want to edit this almanah entry for %s?"),
 							    date_string);
 		gtk_dialog_add_buttons (GTK_DIALOG (dialog),
 					GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
@@ -720,18 +724,18 @@
 		gtk_widget_destroy (dialog);
 	} else if (entry_exists == TRUE &&
 		   (content == NULL || content[0] == '\0')) {
-		GDate date;
 		gchar date_string[100];
 		GtkWidget *dialog;
 
-		g_date_set_dmy (&date, day, month, year);
+		g_free (content);
+
 		g_date_strftime (date_string, sizeof (date_string), "%A, %e %B %Y", &date);
 
 		dialog = gtk_message_dialog_new (GTK_WINDOW (diary->main_window),
 							    GTK_DIALOG_MODAL,
 							    GTK_MESSAGE_QUESTION,
 							    GTK_BUTTONS_NONE,
-							    _("Are you sure you want to delete this diary entry for %s?"),
+							    _("Are you sure you want to delete this almanah entry for %s?"),
 							    date_string);
 		gtk_dialog_add_buttons (GTK_DIALOG (dialog),
 					GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
@@ -744,23 +748,32 @@
 			return FALSE;
 		}
 
-		diary_storage_manager_query_async (self, "DELETE FROM entries WHERE year = %u AND month = %u AND day = %u", NULL, NULL, year, month, day);
+		almanah_storage_manager_query_async (self, "DELETE FROM entries WHERE year = %u AND month = %u AND day = %u", NULL, NULL,
+						     g_date_get_year (&date),
+						     g_date_get_month (&date),
+						     g_date_get_day (&date));
 		gtk_widget_destroy (dialog);
 
 		return FALSE;
 	} else if (entry_exists == FALSE &&
 		   (content == NULL || content[0] == '\0')) {
+		g_free (content);
 		return FALSE;
 	}
 
-	diary_storage_manager_query_async (self, "REPLACE INTO entries (year, month, day, content) VALUES (%u, %u, %u, '%q')", NULL, NULL, year, month, day, content);
+	almanah_storage_manager_query_async (self, "REPLACE INTO entries (year, month, day, content) VALUES (%u, %u, %u, '%q')", NULL, NULL,
+					   g_date_get_year (&date),
+					   g_date_get_month (&date),
+					   g_date_get_day (&date),
+					   content);
+	g_free (content);
 
 	return TRUE;
 }
 
 /**
- * diary_storage_manager_search_entries:
- * @self: a #DiaryStorageManager
+ * almanah_storage_manager_search_entries:
+ * @self: a #AlmanahStorageManager
  * @search_string: string for which to search in entry content
  * @matches: return location for the results
  *
@@ -774,16 +787,16 @@
  * Return value: number of results
  **/
 guint
-diary_storage_manager_search_entries (DiaryStorageManager *self, const gchar *search_string, GDate *matches[])
+almanah_storage_manager_search_entries (AlmanahStorageManager *self, const gchar *search_string, GDate *matches[])
 {
-	DiaryQueryResults *results;
+	AlmanahQueryResults *results;
 	guint i;
 
-	results = diary_storage_manager_query (self, "SELECT day, month, year FROM entries WHERE content LIKE '%%%q%%'", search_string);
+	results = almanah_storage_manager_query (self, "SELECT day, month, year FROM entries WHERE content LIKE '%%%q%%'", search_string);
 
 	/* No results? */
 	if (results->rows < 1) {
-		diary_storage_manager_free_results (results);
+		almanah_storage_manager_free_results (results);
 		*matches = NULL;
 		return 0;
 	}
@@ -798,73 +811,103 @@
 				(GDateYear) atoi (results->data[(i + 1) * results->columns + 2]));
 	}
 
-	diary_storage_manager_free_results (results);
+	almanah_storage_manager_free_results (results);
 
 	return i;
 }
 
 /* NOTE: Free results with g_slice_free */
 gboolean *
-diary_storage_manager_get_month_marked_days (DiaryStorageManager *self, GDateYear year, GDateMonth month)
+almanah_storage_manager_get_month_marked_days (AlmanahStorageManager *self, GDateYear year, GDateMonth month)
 {
-	DiaryQueryResults *results;
+	AlmanahQueryResults *results;
 	guint i;
 	gboolean *days = g_slice_alloc0 (sizeof (gboolean) * 32);
 
-	results = diary_storage_manager_query (self, "SELECT day FROM entries WHERE year = %u AND month = %u", year, month);
+	results = almanah_storage_manager_query (self, "SELECT day FROM entries WHERE year = %u AND month = %u", year, month);
 
 	for (i = 1; i <= results->rows; i++)
 		days[atoi (results->data[i])] = TRUE;
 
-	diary_storage_manager_free_results (results);
+	almanah_storage_manager_free_results (results);
 
 	return days;
 }
 
-/* NOTE: Free array with g_free and each element with g_slice_free, *after* freeing ->type and ->value with g_free */
-DiaryLink **
-diary_storage_manager_get_entry_links (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day)
+/* NOTE: Free array with g_free and each element with g_object_unref */
+AlmanahLink **
+almanah_storage_manager_get_entry_links (AlmanahStorageManager *self, GDate *date)
 {
-	DiaryQueryResults *results;
-	DiaryLink **links;
+	AlmanahQueryResults *results;
+	AlmanahLink **links;
 	guint i;
 
-	results = diary_storage_manager_query (self, "SELECT link_type, link_value, link_value2 FROM entry_links WHERE year = %u AND month = %u AND day = %u", year, month, day);
+	results = almanah_storage_manager_query (self, "SELECT link_type, link_value, link_value2 FROM entry_links WHERE year = %u AND month = %u AND day = %u",
+						 g_date_get_year (date),
+						 g_date_get_month (date),
+						 g_date_get_day (date));
 
 	if (results->rows == 0) {
-		diary_storage_manager_free_results (results);
+		almanah_storage_manager_free_results (results);
 		/* Return empty array */
-		links = (DiaryLink**) g_new (gpointer, 1);
+		links = (AlmanahLink**) g_new (AlmanahLink*, 1);
 		links[0] = NULL;
 		return links;
 	}
 
-	links = (DiaryLink**) g_new (gpointer, results->rows + 1);
+	links = (AlmanahLink**) g_new (AlmanahLink*, results->rows + 1);
 	for (i = 0; i < results->rows; i++) {
-		links[i] = g_slice_new (DiaryLink);
-		links[i]->type = g_strdup (results->data[(i + 1) * results->columns]);
-		links[i]->value = g_strdup (results->data[(i + 1) * results->columns + 1]);
-		links[i]->value2 = g_strdup (results->data[(i + 1) * results->columns + 2]);
+		links[i] = almanah_link_new (results->data[(i + 1) * results->columns]);
+		almanah_link_set_value (links[i], results->data[(i + 1) * results->columns + 1]);
+		almanah_link_set_value2 (links[i], results->data[(i + 1) * results->columns + 2]);
 	}
 	links[i] = NULL;
 
-	diary_storage_manager_free_results (results);
+	almanah_storage_manager_free_results (results);
 
 	return links;
 }
 
 gboolean
-diary_storage_manager_add_entry_link (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day, const gchar *link_type, const gchar *link_value, const gchar *link_value2)
+almanah_storage_manager_add_entry_link (AlmanahStorageManager *self, GDate *date, AlmanahLink *link)
 {
-	g_assert (diary_validate_link_type (link_type));
-	if (link_value2 == NULL)
-		return diary_storage_manager_query_async (self, "REPLACE INTO entry_links (year, month, day, link_type, link_value) VALUES (%u, %u, %u, '%q', '%q')", NULL, NULL, year, month, day, link_type, link_value);
-	else
-		return diary_storage_manager_query_async (self, "REPLACE INTO entry_links (year, month, day, link_type, link_value, link_value2) VALUES (%u, %u, %u, '%q', '%q', '%q')", NULL, NULL, year, month, day, link_type, link_value, link_value2);
+	gboolean return_value;
+	gchar *value, *value2;
+	const gchar *type_id;
+
+	type_id = almanah_link_get_type_id (link);
+	value = almanah_link_get_value (link);
+	value2 = almanah_link_get_value2 (link);
+
+	if (value2 == NULL) {
+		return_value = almanah_storage_manager_query_async (self, "REPLACE INTO entry_links (year, month, day, link_type, link_value) VALUES (%u, %u, %u, '%q', '%q')", NULL, NULL,
+								    g_date_get_year (date),
+								    g_date_get_month (date),
+								    g_date_get_day (date),
+								    type_id,
+								    value);
+	} else {
+		return_value = almanah_storage_manager_query_async (self, "REPLACE INTO entry_links (year, month, day, link_type, link_value, link_value2) VALUES (%u, %u, %u, '%q', '%q', '%q')", NULL, NULL,
+								    g_date_get_year (date),
+								    g_date_get_month (date),
+								    g_date_get_day (date),
+								    type_id,
+								    value,
+								    value2);
+	}
+
+	g_free (value);
+	g_free (value2);
+
+	return return_value;
 }
 
 gboolean
-diary_storage_manager_remove_entry_link (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day, const gchar *link_type)
+almanah_storage_manager_remove_entry_link (AlmanahStorageManager *self, GDate *date, const gchar *link_type_id)
 {
-	return diary_storage_manager_query_async (self, "DELETE FROM entry_links WHERE year = %u AND month = %u AND day = %u AND link_type = '%q'", NULL, NULL, year, month, day, link_type);
+	return almanah_storage_manager_query_async (self, "DELETE FROM entry_links WHERE year = %u AND month = %u AND day = %u AND link_type = '%q'", NULL, NULL,
+						    g_date_get_year (date),
+						    g_date_get_month (date),
+						    g_date_get_day (date),
+						    link_type_id);
 }

Modified: trunk/src/storage-manager.h
==============================================================================
--- trunk/src/storage-manager.h	(original)
+++ trunk/src/storage-manager.h	Fri Oct 10 22:22:19 2008
@@ -1,103 +1,93 @@
 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 /*
- * Diary
+ * Almanah
  * Copyright (C) Philip Withnall 2008 <philip tecnocode co uk>
  * 
- * Diary is free software: you can redistribute it and/or modify
+ * 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.
  *
- * Diary is distributed in the hope that it will be useful,
+ * 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 Diary.  If not, see <http://www.gnu.org/licenses/>.
+ * along with Almanah.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef DIARY_STORAGE_MANAGER_H
-#define DIARY_STORAGE_MANAGER_H
+#ifndef ALMANAH_STORAGE_MANAGER_H
+#define ALMANAH_STORAGE_MANAGER_H
 
 #include <glib.h>
 #include <glib-object.h>
 
+#include "entry.h"
 #include "link.h"
 
 G_BEGIN_DECLS
 
-#define DIARY_TYPE_STORAGE_MANAGER		(diary_storage_manager_get_type ())
-#define DIARY_STORAGE_MANAGER_ERROR		(diary_storage_manager_error_quark ())
-#define DIARY_STORAGE_MANAGER(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), DIARY_TYPE_STORAGE_MANAGER, DiaryStorageManager))
-#define DIARY_STORAGE_MANAGER_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), DIARY_TYPE_STORAGE_MANAGER, DiaryStorageManagerClass))
-#define DIARY_IS_STORAGE_MANAGER(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), DIARY_TYPE_STORAGE_MANAGER))
-#define DIARY_IS_STORAGE_MANAGER_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), DIARY_TYPE_STORAGE_MANAGER))
-#define DIARY_STORAGE_MANAGER_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), DIARY_TYPE_STORAGE_MANAGER, DiaryStorageManagerClass))
+#define ALMANAH_TYPE_STORAGE_MANAGER		(almanah_storage_manager_get_type ())
+#define ALMANAH_STORAGE_MANAGER_ERROR		(almanah_storage_manager_error_quark ())
+#define ALMANAH_STORAGE_MANAGER(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), ALMANAH_TYPE_STORAGE_MANAGER, AlmanahStorageManager))
+#define ALMANAH_STORAGE_MANAGER_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), ALMANAH_TYPE_STORAGE_MANAGER, AlmanahStorageManagerClass))
+#define ALMANAH_IS_STORAGE_MANAGER(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), ALMANAH_TYPE_STORAGE_MANAGER))
+#define ALMANAH_IS_STORAGE_MANAGER_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), ALMANAH_TYPE_STORAGE_MANAGER))
+#define ALMANAH_STORAGE_MANAGER_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), ALMANAH_TYPE_STORAGE_MANAGER, AlmanahStorageManagerClass))
 
-typedef struct _DiaryStorageManagerPrivate	DiaryStorageManagerPrivate;
+typedef struct _AlmanahStorageManagerPrivate	AlmanahStorageManagerPrivate;
 
 typedef struct {
 	GObject parent;
-	DiaryStorageManagerPrivate *priv;
-} DiaryStorageManager;
+	AlmanahStorageManagerPrivate *priv;
+} AlmanahStorageManager;
 
 typedef struct {
 	GObjectClass parent;
-} DiaryStorageManagerClass;
+} AlmanahStorageManagerClass;
 
 typedef enum {
-	DIARY_STORAGE_MANAGER_ERROR_UNSUPPORTED,
-	DIARY_STORAGE_MANAGER_ERROR_OPENING_FILE,
-	DIARY_STORAGE_MANAGER_ERROR_CREATING_CONTEXT,
-	DIARY_STORAGE_MANAGER_ERROR_DECRYPTING,
-	DIARY_STORAGE_MANAGER_ERROR_ENCRYPTING,
-	DIARY_STORAGE_MANAGER_ERROR_GETTING_KEY
-} DiaryStorageManagerError;
+	ALMANAH_STORAGE_MANAGER_ERROR_UNSUPPORTED,
+	ALMANAH_STORAGE_MANAGER_ERROR_OPENING_FILE,
+	ALMANAH_STORAGE_MANAGER_ERROR_CREATING_CONTEXT,
+	ALMANAH_STORAGE_MANAGER_ERROR_DECRYPTING,
+	ALMANAH_STORAGE_MANAGER_ERROR_ENCRYPTING,
+	ALMANAH_STORAGE_MANAGER_ERROR_GETTING_KEY
+} AlmanahStorageManagerError;
 
-typedef enum {
-	DIARY_ENTRY_EDITABLE = 1,
-	DIARY_ENTRY_FUTURE = 2,
-	DIARY_ENTRY_PAST = 0
-} DiaryEntryEditable;
-
-/* The number of days after which a diary entry requires confirmation to be edited */
-#define DIARY_ENTRY_CUTOFF_AGE 14
-
-typedef gint (*DiaryQueryCallback) (gpointer user_data, gint columns, gchar **data, gchar **column_names);
+typedef gint (*AlmanahQueryCallback) (gpointer user_data, gint columns, gchar **data, gchar **column_names);
 
 typedef struct {
 	gchar **data;
 	gint rows;
 	gint columns;
-} DiaryQueryResults;
+} AlmanahQueryResults;
 
-GType diary_storage_manager_get_type (void);
-GQuark diary_storage_manager_error_quark (void);
-DiaryStorageManager *diary_storage_manager_new (const gchar *filename);
+GType almanah_storage_manager_get_type (void);
+GQuark almanah_storage_manager_error_quark (void);
+AlmanahStorageManager *almanah_storage_manager_new (const gchar *filename);
 
-void diary_storage_manager_connect (DiaryStorageManager *self);
-void diary_storage_manager_disconnect (DiaryStorageManager *self);
+void almanah_storage_manager_connect (AlmanahStorageManager *self);
+void almanah_storage_manager_disconnect (AlmanahStorageManager *self);
 
-DiaryQueryResults *diary_storage_manager_query (DiaryStorageManager *self, const gchar *query, ...);
-void diary_storage_manager_free_results (DiaryQueryResults *results);
-gboolean diary_storage_manager_query_async (DiaryStorageManager *self, const gchar *query, const DiaryQueryCallback callback, gpointer user_data, ...);
+AlmanahQueryResults *almanah_storage_manager_query (AlmanahStorageManager *self, const gchar *query, ...);
+void almanah_storage_manager_free_results (AlmanahQueryResults *results);
+gboolean almanah_storage_manager_query_async (AlmanahStorageManager *self, const gchar *query, const AlmanahQueryCallback callback, gpointer user_data, ...);
 
-/* TODO: Surely just passing in GDates to these functions would be easier? */
-gboolean diary_storage_manager_get_statistics (DiaryStorageManager *self, guint *entry_count, guint *link_count, guint *character_count);
+gboolean almanah_storage_manager_get_statistics (AlmanahStorageManager *self, guint *entry_count, guint *link_count, guint *character_count);
 
-gboolean diary_storage_manager_entry_exists (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day);
-DiaryEntryEditable diary_storage_manager_entry_is_editable (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day);
-gchar *diary_storage_manager_get_entry (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day);
-gboolean diary_storage_manager_set_entry (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day, const gchar *content);
-guint diary_storage_manager_search_entries (DiaryStorageManager *self, const gchar *search_string, GDate *matches[]);
+gboolean almanah_storage_manager_entry_exists (AlmanahStorageManager *self, GDate *date);
+AlmanahEntry *almanah_storage_manager_get_entry (AlmanahStorageManager *self, GDate *date);
+gboolean almanah_storage_manager_set_entry (AlmanahStorageManager *self, AlmanahEntry *entry);
+guint almanah_storage_manager_search_entries (AlmanahStorageManager *self, const gchar *search_string, GDate *matches[]);
 
-gboolean *diary_storage_manager_get_month_marked_days (DiaryStorageManager *self, GDateYear year, GDateMonth month);
+gboolean *almanah_storage_manager_get_month_marked_days (AlmanahStorageManager *self, GDateYear year, GDateMonth month);
 
-DiaryLink **diary_storage_manager_get_entry_links (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day);
-gboolean diary_storage_manager_add_entry_link (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day, const gchar *link_type, const gchar *link_value, const gchar *link_value2);
-gboolean diary_storage_manager_remove_entry_link (DiaryStorageManager *self, GDateYear year, GDateMonth month, GDateDay day, const gchar *link_type);
+AlmanahLink **almanah_storage_manager_get_entry_links (AlmanahStorageManager *self, GDate *date);
+gboolean almanah_storage_manager_add_entry_link (AlmanahStorageManager *self, GDate *date, AlmanahLink *link);
+gboolean almanah_storage_manager_remove_entry_link (AlmanahStorageManager *self, GDate *date, const gchar *link_type_id);
 
 G_END_DECLS
 
-#endif /* !DIARY_STORAGE_MANAGER_H */
+#endif /* !ALMANAH_STORAGE_MANAGER_H */



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