Evolution consists of entirely too many small utility libraries, which increases linking and loading time, places a burden on higher layers of the application (e.g. modules) which has to remember to link to all the small in-tree utility libraries, and makes it difficult to generate API documentation for these utility libraries in one Gtk-Doc module. Merge the following utility libraries under the umbrella of libeutil, and enforce a single-include policy on libeutil so we can reorganize the files as desired without disrupting its pseudo-public API. libemail-utils/libemail-utils.la libevolution-utils/libevolution-utils.la filter/libfilter.la widgets/e-timezone-dialog/libetimezonedialog.la widgets/menus/libmenus.la widgets/misc/libemiscwidgets.la widgets/table/libetable.la widgets/text/libetext.la This also merges libedataserverui from the Evolution-Data-Server module, since Evolution is its only consumer nowadays, and I'd like to make some improvements to those APIs without concern for backward-compatibility. And finally, start a Gtk-Doc module for libeutil. It's going to be a project just getting all the symbols _listed_ much less _documented_. But the skeletal structure is in place and I'm off to a good start.
344 lines
9.3 KiB
C
344 lines
9.3 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
|
/*
|
|
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of version 2 of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <gtk/gtk.h>
|
|
#include <glib/gi18n-lib.h>
|
|
|
|
#include <libedataserver/libedataserver.h>
|
|
|
|
#include "e-category-editor.h"
|
|
|
|
#define E_CATEGORY_EDITOR_GET_PRIVATE(obj) \
|
|
(G_TYPE_INSTANCE_GET_PRIVATE \
|
|
((obj), E_TYPE_CATEGORY_EDITOR, ECategoryEditorPrivate))
|
|
|
|
struct _ECategoryEditorPrivate {
|
|
GtkWidget *category_name;
|
|
GtkWidget *category_icon;
|
|
};
|
|
|
|
G_DEFINE_TYPE (ECategoryEditor, e_category_editor, GTK_TYPE_DIALOG)
|
|
|
|
static void
|
|
update_preview (GtkFileChooser *chooser,
|
|
gpointer user_data)
|
|
{
|
|
GtkImage *image;
|
|
gchar *filename;
|
|
|
|
g_return_if_fail (chooser != NULL);
|
|
|
|
image = GTK_IMAGE (gtk_file_chooser_get_preview_widget (chooser));
|
|
g_return_if_fail (image != NULL);
|
|
|
|
filename = gtk_file_chooser_get_preview_filename (chooser);
|
|
|
|
gtk_image_set_from_file (image, filename);
|
|
gtk_file_chooser_set_preview_widget_active (chooser, filename != NULL);
|
|
|
|
g_free (filename);
|
|
}
|
|
|
|
static void
|
|
file_chooser_response (GtkDialog *dialog,
|
|
gint response_id,
|
|
GtkFileChooser *button)
|
|
{
|
|
g_return_if_fail (button != NULL);
|
|
|
|
if (response_id == GTK_RESPONSE_NO)
|
|
gtk_file_chooser_unselect_all (button);
|
|
}
|
|
|
|
static void
|
|
category_editor_category_name_changed (GtkEntry *category_name_entry,
|
|
ECategoryEditor *editor)
|
|
{
|
|
gchar *name;
|
|
|
|
g_return_if_fail (editor != NULL);
|
|
g_return_if_fail (category_name_entry != NULL);
|
|
|
|
name = g_strdup (gtk_entry_get_text (category_name_entry));
|
|
if (name != NULL)
|
|
name = g_strstrip (name);
|
|
|
|
gtk_dialog_set_response_sensitive (
|
|
GTK_DIALOG (editor), GTK_RESPONSE_OK, name && *name);
|
|
|
|
g_free (name);
|
|
}
|
|
|
|
static gchar *
|
|
check_category_name (const gchar *name)
|
|
{
|
|
GString *str = NULL;
|
|
gchar *p = (gchar *) name;
|
|
|
|
str = g_string_new ("");
|
|
while (*p) {
|
|
switch (*p) {
|
|
case ',':
|
|
break;
|
|
default:
|
|
str = g_string_append_c (str, *p);
|
|
}
|
|
p++;
|
|
}
|
|
|
|
p = g_strstrip (g_string_free (str, FALSE));
|
|
|
|
return p;
|
|
}
|
|
|
|
static void
|
|
e_category_editor_class_init (ECategoryEditorClass *class)
|
|
{
|
|
g_type_class_add_private (class, sizeof (ECategoryEditorPrivate));
|
|
}
|
|
|
|
static void
|
|
e_category_editor_init (ECategoryEditor *editor)
|
|
{
|
|
GtkWidget *dialog_content;
|
|
GtkWidget *dialog_action_area;
|
|
GtkGrid *grid_category_properties;
|
|
GtkWidget *label_name;
|
|
GtkWidget *label_icon;
|
|
GtkWidget *category_name;
|
|
GtkWidget *chooser_button;
|
|
GtkWidget *no_image_button;
|
|
GtkWidget *chooser_dialog;
|
|
GtkWidget *preview;
|
|
|
|
editor->priv = E_CATEGORY_EDITOR_GET_PRIVATE (editor);
|
|
|
|
chooser_dialog = gtk_file_chooser_dialog_new (
|
|
_("Category Icon"),
|
|
NULL, GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
|
|
|
|
no_image_button = gtk_button_new_with_mnemonic (_("_No Image"));
|
|
gtk_button_set_image (
|
|
GTK_BUTTON (no_image_button),
|
|
gtk_image_new_from_stock (
|
|
GTK_STOCK_CLOSE, GTK_ICON_SIZE_BUTTON));
|
|
gtk_dialog_add_action_widget (
|
|
GTK_DIALOG (chooser_dialog),
|
|
no_image_button, GTK_RESPONSE_NO);
|
|
gtk_dialog_add_button (
|
|
GTK_DIALOG (chooser_dialog),
|
|
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT);
|
|
gtk_file_chooser_set_local_only (
|
|
GTK_FILE_CHOOSER (chooser_dialog), TRUE);
|
|
gtk_widget_show (no_image_button);
|
|
|
|
g_signal_connect (
|
|
chooser_dialog, "update-preview",
|
|
G_CALLBACK (update_preview), NULL);
|
|
|
|
preview = gtk_image_new ();
|
|
gtk_file_chooser_set_preview_widget (
|
|
GTK_FILE_CHOOSER (chooser_dialog), preview);
|
|
gtk_file_chooser_set_preview_widget_active (
|
|
GTK_FILE_CHOOSER (chooser_dialog), TRUE);
|
|
gtk_widget_show_all (preview);
|
|
|
|
dialog_content = gtk_dialog_get_content_area (GTK_DIALOG (editor));
|
|
|
|
grid_category_properties = GTK_GRID (gtk_grid_new ());
|
|
gtk_box_pack_start (
|
|
GTK_BOX (dialog_content),
|
|
GTK_WIDGET (grid_category_properties), TRUE, TRUE, 0);
|
|
gtk_container_set_border_width (
|
|
GTK_CONTAINER (grid_category_properties), 12);
|
|
gtk_grid_set_row_spacing (grid_category_properties, 6);
|
|
gtk_grid_set_column_spacing (grid_category_properties, 6);
|
|
|
|
label_name = gtk_label_new_with_mnemonic (_("Category _Name"));
|
|
gtk_widget_set_halign (label_name, GTK_ALIGN_FILL);
|
|
gtk_misc_set_alignment (GTK_MISC (label_name), 0, 0.5);
|
|
gtk_grid_attach (grid_category_properties, label_name, 0, 0, 1, 1);
|
|
|
|
category_name = gtk_entry_new ();
|
|
gtk_widget_set_hexpand (category_name, TRUE);
|
|
gtk_widget_set_halign (category_name, GTK_ALIGN_FILL);
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label_name), category_name);
|
|
gtk_grid_attach (grid_category_properties, category_name, 1, 0, 1, 1);
|
|
editor->priv->category_name = category_name;
|
|
|
|
label_icon = gtk_label_new_with_mnemonic (_("Category _Icon"));
|
|
gtk_widget_set_halign (label_icon, GTK_ALIGN_FILL);
|
|
gtk_misc_set_alignment (GTK_MISC (label_icon), 0, 0.5);
|
|
gtk_grid_attach (grid_category_properties, label_icon, 0, 1, 1, 1);
|
|
|
|
chooser_button = GTK_WIDGET (
|
|
gtk_file_chooser_button_new_with_dialog (chooser_dialog));
|
|
gtk_widget_set_hexpand (chooser_button, TRUE);
|
|
gtk_widget_set_halign (chooser_button, GTK_ALIGN_FILL);
|
|
gtk_label_set_mnemonic_widget (GTK_LABEL (label_icon), chooser_button);
|
|
gtk_grid_attach (grid_category_properties, chooser_button, 1, 1, 1, 1);
|
|
editor->priv->category_icon = chooser_button;
|
|
|
|
g_signal_connect (
|
|
chooser_dialog, "response",
|
|
G_CALLBACK (file_chooser_response), chooser_button);
|
|
|
|
dialog_action_area = gtk_dialog_get_action_area (GTK_DIALOG (editor));
|
|
gtk_button_box_set_layout (
|
|
GTK_BUTTON_BOX (dialog_action_area), GTK_BUTTONBOX_END);
|
|
|
|
gtk_dialog_add_buttons (
|
|
GTK_DIALOG (editor),
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
|
|
gtk_dialog_set_default_response (GTK_DIALOG (editor), GTK_RESPONSE_OK);
|
|
gtk_window_set_title (GTK_WINDOW (editor), _("Category Properties"));
|
|
gtk_window_set_type_hint (
|
|
GTK_WINDOW (editor), GDK_WINDOW_TYPE_HINT_DIALOG);
|
|
|
|
gtk_widget_show_all (dialog_content);
|
|
|
|
g_signal_connect (
|
|
category_name, "changed",
|
|
G_CALLBACK (category_editor_category_name_changed), editor);
|
|
|
|
category_editor_category_name_changed (
|
|
GTK_ENTRY (category_name), editor);
|
|
}
|
|
|
|
/**
|
|
* e_categort_editor_new:
|
|
*
|
|
* Creates a new #ECategoryEditor widget.
|
|
*
|
|
* Returns: a new #ECategoryEditor
|
|
*
|
|
* Since: 3.2
|
|
**/
|
|
ECategoryEditor *
|
|
e_category_editor_new ()
|
|
{
|
|
return g_object_new (E_TYPE_CATEGORY_EDITOR, NULL);
|
|
}
|
|
|
|
/**
|
|
* e_category_editor_create_category:
|
|
*
|
|
* Since: 3.2
|
|
**/
|
|
const gchar *
|
|
e_category_editor_create_category (ECategoryEditor *editor)
|
|
{
|
|
GtkEntry *entry;
|
|
GtkFileChooser *file_chooser;
|
|
|
|
g_return_val_if_fail (E_IS_CATEGORY_EDITOR (editor), NULL);
|
|
|
|
entry = GTK_ENTRY (editor->priv->category_name);
|
|
file_chooser = GTK_FILE_CHOOSER (editor->priv->category_icon);
|
|
|
|
do {
|
|
const gchar *category_name;
|
|
const gchar *correct_category_name;
|
|
|
|
if (gtk_dialog_run (GTK_DIALOG (editor)) != GTK_RESPONSE_OK)
|
|
return NULL;
|
|
|
|
category_name = gtk_entry_get_text (entry);
|
|
correct_category_name = check_category_name (category_name);
|
|
|
|
if (e_categories_exist (correct_category_name)) {
|
|
GtkWidget *error_dialog;
|
|
|
|
error_dialog = gtk_message_dialog_new (
|
|
GTK_WINDOW (editor),
|
|
0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
|
|
_("There is already a category '%s' in the "
|
|
"configuration. Please use another name"),
|
|
category_name);
|
|
|
|
gtk_dialog_run (GTK_DIALOG (error_dialog));
|
|
gtk_widget_destroy (error_dialog);
|
|
|
|
/* Now we loop and run the dialog again. */
|
|
|
|
} else {
|
|
gchar *category_icon;
|
|
|
|
category_icon =
|
|
gtk_file_chooser_get_filename (file_chooser);
|
|
e_categories_add (
|
|
correct_category_name, NULL,
|
|
category_icon, TRUE);
|
|
g_free (category_icon);
|
|
|
|
return correct_category_name;
|
|
}
|
|
|
|
} while (TRUE);
|
|
}
|
|
|
|
/**
|
|
* e_category_editor_edit_category:
|
|
*
|
|
* Since: 3.2
|
|
**/
|
|
gboolean
|
|
e_category_editor_edit_category (ECategoryEditor *editor,
|
|
const gchar *category)
|
|
{
|
|
GtkFileChooser *file_chooser;
|
|
const gchar *icon_file;
|
|
|
|
g_return_val_if_fail (E_IS_CATEGORY_EDITOR (editor), FALSE);
|
|
g_return_val_if_fail (category != NULL, FALSE);
|
|
|
|
file_chooser = GTK_FILE_CHOOSER (editor->priv->category_icon);
|
|
|
|
gtk_entry_set_text (GTK_ENTRY (editor->priv->category_name), category);
|
|
gtk_widget_set_sensitive (editor->priv->category_name, FALSE);
|
|
|
|
icon_file = e_categories_get_icon_file_for (category);
|
|
if (icon_file) {
|
|
gtk_file_chooser_set_filename (file_chooser, icon_file);
|
|
update_preview (file_chooser, NULL);
|
|
}
|
|
|
|
if (gtk_dialog_run (GTK_DIALOG (editor)) == GTK_RESPONSE_OK) {
|
|
gchar *category_icon;
|
|
|
|
category_icon = gtk_file_chooser_get_filename (file_chooser);
|
|
e_categories_set_icon_file_for (category, category_icon);
|
|
|
|
gtk_dialog_set_response_sensitive (
|
|
GTK_DIALOG (editor), GTK_RESPONSE_OK, TRUE);
|
|
|
|
g_free (category_icon);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|