summaryrefslogtreecommitdiff
path: root/mate-panel/panel-ditem-editor.c
diff options
context:
space:
mode:
Diffstat (limited to 'mate-panel/panel-ditem-editor.c')
-rw-r--r--mate-panel/panel-ditem-editor.c1804
1 files changed, 1804 insertions, 0 deletions
diff --git a/mate-panel/panel-ditem-editor.c b/mate-panel/panel-ditem-editor.c
new file mode 100644
index 00000000..e00f124e
--- /dev/null
+++ b/mate-panel/panel-ditem-editor.c
@@ -0,0 +1,1804 @@
+/*
+ * panel-ditem-editor.c:
+ *
+ * Copyright (C) 2004, 2006 Vincent Untz
+ *
+ * The Mate Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This 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 Library General Public
+ * License along with the Mate Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Vincent Untz <[email protected]>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+#include <libpanel-util/panel-icon-chooser.h>
+#include <libpanel-util/panel-keyfile.h>
+#include <libpanel-util/panel-show.h>
+#include <libpanel-util/panel-xdg.h>
+
+#include "panel-ditem-editor.h"
+#include "panel-icon-names.h"
+#include "panel-util.h"
+#include "panel-marshal.h"
+
+struct _PanelDItemEditorPrivate
+{
+ /* we keep a ditem around, since we can never have absolutely
+ everything in the display so we load a file, or get a ditem,
+ sync the display and ref the ditem */
+ GKeyFile *key_file;
+ gboolean free_key_file;
+ /* the revert ditem will only contain relevant keys */
+ GKeyFile *revert_key_file;
+
+ gboolean reverting;
+ gboolean dirty;
+ guint save_timeout;
+
+ char *uri; /* file location */
+ gboolean type_directory;
+ gboolean new_file;
+ gboolean combo_setuped;
+
+ PanelDitemSaveUri save_uri;
+ gpointer save_uri_data;
+
+ GtkWidget *table;
+ GtkWidget *type_label;
+ GtkWidget *type_combo;
+ GtkWidget *name_label;
+ GtkWidget *name_entry;
+ GtkWidget *command_hbox;
+ GtkWidget *command_label;
+ GtkWidget *command_entry;
+ GtkWidget *command_browse_button;
+ GtkWidget *command_browse_filechooser;
+ GtkWidget *comment_label;
+ GtkWidget *comment_entry;
+ GtkWidget *icon_chooser;
+
+ GtkWidget *help_button;
+ GtkWidget *revert_button;
+ GtkWidget *close_button;
+ GtkWidget *cancel_button;
+ GtkWidget *ok_button;
+};
+
+/* Time in seconds after which we save the file on the disk */
+#define SAVE_FREQUENCY 2
+
+enum {
+ REVERT_BUTTON
+};
+
+typedef enum {
+ PANEL_DITEM_EDITOR_TYPE_NULL,
+ PANEL_DITEM_EDITOR_TYPE_APPLICATION,
+ PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION,
+ PANEL_DITEM_EDITOR_TYPE_LINK,
+ PANEL_DITEM_EDITOR_TYPE_DIRECTORY
+} PanelDItemEditorType;
+
+enum {
+ COLUMN_TEXT,
+ COLUMN_TYPE,
+ NUMBER_COLUMNS
+};
+
+typedef struct {
+ const char *name;
+ const char *show_for;
+ PanelDItemEditorType type;
+} ComboItem;
+
+static ComboItem type_items [] = {
+ { N_("Application"), "Application",
+ PANEL_DITEM_EDITOR_TYPE_APPLICATION },
+ { N_("Application in Terminal"), "Application",
+ PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION },
+ { N_("Location"), "Link",
+ PANEL_DITEM_EDITOR_TYPE_LINK },
+ /* FIXME: hack hack hack: we will remove this item from the combo
+ * box if we show it */
+ { NULL, "Directory",
+ PANEL_DITEM_EDITOR_TYPE_DIRECTORY }
+};
+
+typedef struct {
+ const char *key;
+ GType type;
+ gboolean default_value;
+ gboolean locale;
+} RevertKey;
+
+static RevertKey revert_keys [] = {
+ { "Type", G_TYPE_STRING, FALSE, FALSE },
+ { "Terminal", G_TYPE_BOOLEAN, FALSE, FALSE },
+ { "Exec", G_TYPE_STRING, FALSE, FALSE },
+ { "URL", G_TYPE_STRING, FALSE, FALSE },
+ /* locale keys */
+ { "Icon", G_TYPE_STRING, FALSE, TRUE },
+ { "Name", G_TYPE_STRING, FALSE, TRUE },
+ { "Comment", G_TYPE_STRING, FALSE, TRUE },
+ { "X-MATE-FullName", G_TYPE_STRING, FALSE, TRUE },
+ /* C version of those keys */
+ { "Icon", G_TYPE_STRING, FALSE, FALSE },
+ { "Name", G_TYPE_STRING, FALSE, FALSE },
+ { "Comment", G_TYPE_STRING, FALSE, FALSE },
+ { "X-MATE-FullName", G_TYPE_STRING, FALSE, FALSE }
+};
+
+enum {
+ SAVED,
+ CHANGED,
+ NAME_CHANGED,
+ COMMAND_CHANGED,
+ COMMENT_CHANGED,
+ ICON_CHANGED,
+ ERROR_REPORTED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_KEYFILE,
+ PROP_URI,
+ PROP_TYPEDIRECTORY
+};
+
+static guint ditem_edit_signals[LAST_SIGNAL] = { 0 };
+
+#define PANEL_DITEM_EDITOR_GET_PRIVATE(o) (PANEL_DITEM_EDITOR (o)->priv)
+
+G_DEFINE_TYPE (PanelDItemEditor, panel_ditem_editor, GTK_TYPE_DIALOG)
+
+static void panel_ditem_editor_setup_ui (PanelDItemEditor *dialog);
+
+static void type_combo_changed (PanelDItemEditor *dialog);
+
+static void response_cb (GtkDialog *dialog,
+ gint response_id);
+
+static void setup_icon_chooser (PanelDItemEditor *dialog,
+ const char *icon_name);
+
+static gboolean panel_ditem_editor_save (PanelDItemEditor *dialog,
+ gboolean report_errors);
+static gboolean panel_ditem_editor_save_timeout (gpointer data);
+static void panel_ditem_editor_revert (PanelDItemEditor *dialog);
+
+static void panel_ditem_editor_key_file_loaded (PanelDItemEditor *dialog);
+static gboolean panel_ditem_editor_load_uri (PanelDItemEditor *dialog,
+ GError **error);
+
+static void panel_ditem_editor_set_key_file (PanelDItemEditor *dialog,
+ GKeyFile *key_file);
+
+static gboolean panel_ditem_editor_get_type_directory (PanelDItemEditor *dialog);
+static void panel_ditem_editor_set_type_directory (PanelDItemEditor *dialog,
+ gboolean type_directory);
+
+
+static PanelDItemEditorType
+map_type_from_desktop_item (const char *type,
+ gboolean terminal)
+{
+ if (type == NULL)
+ return PANEL_DITEM_EDITOR_TYPE_NULL;
+ else if (!strcmp (type, "Application")) {
+ if (terminal)
+ return PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION;
+ else
+ return PANEL_DITEM_EDITOR_TYPE_APPLICATION;
+ } else if (!strcmp (type, "Link"))
+ return PANEL_DITEM_EDITOR_TYPE_LINK;
+ else if (!strcmp (type, "Directory"))
+ return PANEL_DITEM_EDITOR_TYPE_DIRECTORY;
+ else
+ return PANEL_DITEM_EDITOR_TYPE_NULL;
+}
+
+static GObject *
+panel_ditem_editor_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *obj;
+ PanelDItemEditor *dialog;
+ GFile *file;
+ gboolean loaded;
+ char *desktop_type;
+
+ obj = G_OBJECT_CLASS (panel_ditem_editor_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties);
+
+ dialog = PANEL_DITEM_EDITOR (obj);
+
+ if (dialog->priv->key_file) {
+ panel_ditem_editor_key_file_loaded (dialog);
+ dialog->priv->new_file = FALSE;
+ dialog->priv->free_key_file = FALSE;
+ loaded = TRUE;
+ } else {
+ dialog->priv->key_file = panel_key_file_new_desktop ();
+ if (dialog->priv->type_directory)
+ panel_key_file_set_string (dialog->priv->key_file,
+ "Type", "Directory");
+ dialog->priv->free_key_file = TRUE;
+ loaded = FALSE;
+ }
+
+ if (!loaded && dialog->priv->uri) {
+ file = g_file_new_for_uri (dialog->priv->uri);
+ if (g_file_query_exists (file, NULL)) {
+ //FIXME what if there's an error?
+ panel_ditem_editor_load_uri (dialog, NULL);
+ dialog->priv->new_file = FALSE;
+ } else {
+ dialog->priv->new_file = TRUE;
+ }
+ g_object_unref (file);
+ } else {
+ dialog->priv->new_file = !loaded;
+ }
+
+ dialog->priv->dirty = FALSE;
+
+ desktop_type = panel_key_file_get_string (dialog->priv->key_file,
+ "Type");
+ if (desktop_type && !strcmp (desktop_type, "Directory"))
+ dialog->priv->type_directory = TRUE;
+ g_free (desktop_type);
+
+ panel_ditem_editor_setup_ui (dialog);
+
+ if (dialog->priv->new_file)
+ setup_icon_chooser (dialog, NULL);
+
+ return obj;
+}
+
+static void
+panel_ditem_editor_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PanelDItemEditor *dialog;
+
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (object));
+
+ dialog = PANEL_DITEM_EDITOR (object);
+
+ switch (prop_id) {
+ case PROP_KEYFILE:
+ g_value_set_pointer (value, panel_ditem_editor_get_key_file (dialog));
+ break;
+ case PROP_URI:
+ g_value_set_string (value, panel_ditem_editor_get_uri (dialog));
+ break;
+ case PROP_TYPEDIRECTORY:
+ g_value_set_boolean (value, panel_ditem_editor_get_type_directory (dialog));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_ditem_editor_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PanelDItemEditor *dialog;
+
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (object));
+
+ dialog = PANEL_DITEM_EDITOR (object);
+
+ switch (prop_id) {
+ case PROP_KEYFILE:
+ panel_ditem_editor_set_key_file (dialog,
+ g_value_get_pointer (value));
+ break;
+ case PROP_URI:
+ panel_ditem_editor_set_uri (dialog,
+ g_value_get_string (value));
+ break;
+ case PROP_TYPEDIRECTORY:
+ panel_ditem_editor_set_type_directory (dialog,
+ g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+panel_ditem_editor_destroy (GtkObject *object)
+{
+ PanelDItemEditor *dialog;
+
+ dialog = PANEL_DITEM_EDITOR (object);
+
+ /* If there was a timeout, then something changed after last save,
+ * so we must save again now */
+ if (dialog->priv->save_timeout) {
+ g_source_remove (dialog->priv->save_timeout);
+ dialog->priv->save_timeout = 0;
+ panel_ditem_editor_save (dialog, FALSE);
+ }
+
+ /* remember, destroy can be run multiple times! */
+
+ if (dialog->priv->free_key_file && dialog->priv->key_file != NULL)
+ g_key_file_free (dialog->priv->key_file);
+ dialog->priv->key_file = NULL;
+
+ if (dialog->priv->revert_key_file != NULL)
+ g_key_file_free (dialog->priv->revert_key_file);
+ dialog->priv->revert_key_file = NULL;
+
+ if (dialog->priv->uri != NULL)
+ g_free (dialog->priv->uri);
+ dialog->priv->uri = NULL;
+
+ GTK_OBJECT_CLASS (panel_ditem_editor_parent_class)->destroy (object);
+}
+
+static void
+panel_ditem_editor_class_init (PanelDItemEditorClass *class)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+ GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (class);
+
+ gobject_class->constructor = panel_ditem_editor_constructor;
+ gobject_class->get_property = panel_ditem_editor_get_property;
+ gobject_class->set_property = panel_ditem_editor_set_property;
+
+ gtkobject_class->destroy = panel_ditem_editor_destroy;
+
+ g_type_class_add_private (class,
+ sizeof (PanelDItemEditorPrivate));
+
+ ditem_edit_signals[SAVED] =
+ g_signal_new ("saved",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ ditem_edit_signals[CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ ditem_edit_signals[NAME_CHANGED] =
+ g_signal_new ("name_changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ name_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ ditem_edit_signals[COMMAND_CHANGED] =
+ g_signal_new ("command_changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ command_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ ditem_edit_signals[COMMENT_CHANGED] =
+ g_signal_new ("comment_changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ comment_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ ditem_edit_signals[ICON_CHANGED] =
+ g_signal_new ("icon_changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ icon_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ ditem_edit_signals[ERROR_REPORTED] =
+ g_signal_new ("error_reported",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PanelDItemEditorClass,
+ error_reported),
+ NULL,
+ NULL,
+ panel_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING, G_TYPE_STRING);
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_KEYFILE,
+ g_param_spec_pointer ("keyfile",
+ "Key File",
+ "A key file containing the data from the .desktop file",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_URI,
+ g_param_spec_string ("uri",
+ "URI",
+ "The URI of the .desktop file",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ gobject_class,
+ PROP_TYPEDIRECTORY,
+ g_param_spec_boolean ("type-directory",
+ "Type Directory",
+ "Whether the edited file is a .directory file or not",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static GtkWidget *
+label_new_with_mnemonic (const char *text)
+{
+ GtkWidget *label;
+ char *bold;
+
+ bold = g_strdup_printf ("<b>%s</b>", text);
+ label = gtk_label_new_with_mnemonic (bold);
+ g_free (bold);
+
+ gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
+
+ gtk_widget_show (label);
+
+ return label;
+}
+
+static inline void
+table_attach_label (GtkTable *table,
+ GtkWidget *label,
+ int left,
+ int right,
+ int top,
+ int bottom)
+{
+ gtk_table_attach (table, label, left, right, top, bottom,
+ GTK_FILL, GTK_FILL,
+ 0, 0);
+}
+
+static inline void
+table_attach_entry (GtkTable *table,
+ GtkWidget *entry,
+ int left,
+ int right,
+ int top,
+ int bottom)
+{
+ gtk_table_attach (table, entry, left, right, top, bottom,
+ GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL,
+ 0, 0);
+}
+
+static void
+setup_combo (GtkWidget *combo_box,
+ ComboItem *items,
+ int nb_items,
+ const char *for_type)
+{
+ GtkListStore *model;
+ GtkTreeIter iter;
+ GtkCellRenderer *renderer;
+ int i;
+
+ model = gtk_list_store_new (NUMBER_COLUMNS,
+ G_TYPE_STRING,
+ G_TYPE_INT);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box),
+ GTK_TREE_MODEL (model));
+
+ for (i = 0; i < nb_items; i++) {
+ if (for_type && strcmp (for_type, items [i].show_for))
+ continue;
+
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ COLUMN_TEXT, _(items [i].name),
+ COLUMN_TYPE, items [i].type,
+ -1);
+ }
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box),
+ renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box),
+ renderer, "text", COLUMN_TEXT, NULL);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), 0);
+}
+
+static PanelDItemEditorType
+panel_ditem_editor_get_item_type (PanelDItemEditor *dialog)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ PanelDItemEditorType type;
+
+ if (dialog->priv->type_directory)
+ return PANEL_DITEM_EDITOR_TYPE_DIRECTORY;
+
+ if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (dialog->priv->type_combo),
+ &iter))
+ return PANEL_DITEM_EDITOR_TYPE_NULL;
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->priv->type_combo));
+ gtk_tree_model_get (model, &iter, COLUMN_TYPE, &type, -1);
+
+ return type;
+}
+
+static void
+panel_ditem_editor_make_ui (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorPrivate *priv;
+ GtkWidget *dialog_vbox;
+
+ priv = dialog->priv;
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+
+ dialog_vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+ gtk_box_set_spacing (GTK_BOX (dialog_vbox), 2);
+
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+
+ priv->table = gtk_table_new (4, 3, FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (priv->table), 5);
+ gtk_table_set_row_spacings (GTK_TABLE (priv->table), 6);
+ gtk_table_set_col_spacings (GTK_TABLE (priv->table), 12);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox),
+ priv->table, TRUE, TRUE, 0);
+ gtk_widget_show (priv->table);
+
+ /* Type */
+ priv->type_label = label_new_with_mnemonic (_("_Type:"));
+ priv->type_combo = gtk_combo_box_new ();
+ gtk_widget_show (priv->type_combo);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->type_label),
+ priv->type_combo);
+
+ /* Name */
+ priv->name_label = label_new_with_mnemonic (_("_Name:"));
+ priv->name_entry = gtk_entry_new ();
+ gtk_widget_show (priv->name_entry);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->name_label),
+ priv->name_entry);
+
+ /* Icon */
+ priv->icon_chooser = panel_icon_chooser_new (NULL);
+ panel_icon_chooser_set_fallback_icon_name (PANEL_ICON_CHOOSER (priv->icon_chooser),
+ PANEL_ICON_LAUNCHER);
+ gtk_table_attach (GTK_TABLE (priv->table), priv->icon_chooser,
+ 0, 1, 0, 2,
+ 0, 0, 0, 0);
+ gtk_widget_show (priv->icon_chooser);
+
+ /* Command */
+ priv->command_label = label_new_with_mnemonic ("");
+
+ priv->command_hbox = gtk_hbox_new (FALSE, 12);
+ gtk_widget_show (priv->command_hbox);
+
+ priv->command_entry = gtk_entry_new ();
+ gtk_box_pack_start (GTK_BOX (priv->command_hbox),
+ priv->command_entry,
+ TRUE, TRUE, 0);
+ gtk_widget_show (priv->command_entry);
+
+ priv->command_browse_button = gtk_button_new_with_mnemonic (_("_Browse..."));
+ gtk_box_pack_start (GTK_BOX (priv->command_hbox),
+ priv->command_browse_button,
+ FALSE, FALSE, 0);
+ gtk_widget_show (priv->command_browse_button);
+
+ /* Comment */
+ priv->comment_label = label_new_with_mnemonic (_("Co_mment:"));
+ priv->comment_entry = gtk_entry_new ();
+ gtk_widget_show (priv->comment_entry);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->comment_label),
+ priv->comment_entry);
+
+ priv->help_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_HELP,
+ GTK_RESPONSE_HELP);
+ priv->revert_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_REVERT_TO_SAVED,
+ REVERT_BUTTON);
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ REVERT_BUTTON,
+ FALSE);
+ priv->close_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_CLOSE,
+ GTK_RESPONSE_CLOSE);
+ priv->cancel_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL);
+ priv->ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ GTK_STOCK_OK,
+ GTK_RESPONSE_OK);
+
+ /* FIXME: There needs to be a way to edit ALL keys/sections */
+}
+
+static void
+panel_ditem_editor_setup_ui (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorPrivate *priv;
+ PanelDItemEditorType type;
+ gboolean show_combo;
+ GList *focus_chain;
+
+ priv = dialog->priv;
+ type = panel_ditem_editor_get_item_type (dialog);
+
+ if (priv->new_file) {
+ gtk_widget_hide (priv->revert_button);
+ gtk_widget_hide (priv->close_button);
+ gtk_widget_show (priv->cancel_button);
+ gtk_widget_show (priv->ok_button);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK);
+
+ if (!priv->combo_setuped) {
+ setup_combo (priv->type_combo,
+ type_items, G_N_ELEMENTS (type_items),
+ NULL);
+ priv->combo_setuped = TRUE;
+ }
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (priv->type_combo), 0);
+
+ show_combo = !priv->type_directory;
+ } else {
+
+ gtk_widget_show (priv->revert_button);
+ gtk_widget_show (priv->close_button);
+ gtk_widget_hide (priv->cancel_button);
+ gtk_widget_hide (priv->ok_button);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_CLOSE);
+
+ show_combo = (type != PANEL_DITEM_EDITOR_TYPE_LINK) &&
+ (type != PANEL_DITEM_EDITOR_TYPE_DIRECTORY);
+ }
+
+ if (show_combo) {
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ PanelDItemEditorType buf_type;
+
+ table_attach_label (GTK_TABLE (priv->table), priv->type_label,
+ 1, 2, 0, 1);
+ table_attach_entry (GTK_TABLE (priv->table), priv->type_combo,
+ 2, 3, 0, 1);
+
+ table_attach_label (GTK_TABLE (priv->table), priv->name_label,
+ 1, 2, 1, 2);
+ table_attach_entry (GTK_TABLE (priv->table), priv->name_entry,
+ 2, 3, 1, 2);
+
+ table_attach_label (GTK_TABLE (priv->table), priv->command_label,
+ 1, 2, 2, 3);
+ table_attach_entry (GTK_TABLE (priv->table), priv->command_hbox,
+ 2, 3, 2, 3);
+
+ table_attach_label (GTK_TABLE (priv->table), priv->comment_label,
+ 1, 2, 3, 4);
+ table_attach_entry (GTK_TABLE (priv->table), priv->comment_entry,
+ 2, 3, 3, 4);
+
+ /* FIXME: hack hack hack */
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->type_combo));
+ if (!gtk_tree_model_get_iter_first (model, &iter))
+ g_assert_not_reached ();
+ do {
+ gtk_tree_model_get (model, &iter,
+ COLUMN_TYPE, &buf_type, -1);
+ if (buf_type == PANEL_DITEM_EDITOR_TYPE_DIRECTORY) {
+ gtk_list_store_remove (GTK_LIST_STORE (model),
+ &iter);
+ break;
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+ } else if (type == PANEL_DITEM_EDITOR_TYPE_DIRECTORY) {
+ table_attach_label (GTK_TABLE (priv->table), priv->name_label,
+ 1, 2, 0, 1);
+ table_attach_entry (GTK_TABLE (priv->table), priv->name_entry,
+ 2, 3, 0, 1);
+
+ table_attach_label (GTK_TABLE (priv->table), priv->comment_label,
+ 1, 2, 1, 2);
+ table_attach_entry (GTK_TABLE (priv->table), priv->comment_entry,
+ 2, 3, 1, 2);
+ } else {
+ table_attach_label (GTK_TABLE (priv->table), priv->name_label,
+ 1, 2, 0, 1);
+ table_attach_entry (GTK_TABLE (priv->table), priv->name_entry,
+ 2, 3, 0, 1);
+
+ table_attach_label (GTK_TABLE (priv->table), priv->command_label,
+ 1, 2, 1, 2);
+ table_attach_entry (GTK_TABLE (priv->table), priv->command_hbox,
+ 2, 3, 1, 2);
+
+ table_attach_label (GTK_TABLE (priv->table), priv->comment_label,
+ 1, 2, 2, 3);
+ table_attach_entry (GTK_TABLE (priv->table), priv->comment_entry,
+ 2, 3, 2, 3);
+ }
+
+ type_combo_changed (dialog);
+
+ /* set a focus chain since GTK+ doesn't want to put the icon entry
+ * as the first widget in the chain */
+ focus_chain = NULL;
+ focus_chain = g_list_prepend (focus_chain, priv->icon_chooser);
+ focus_chain = g_list_prepend (focus_chain, priv->type_combo);
+ focus_chain = g_list_prepend (focus_chain, priv->name_entry);
+ focus_chain = g_list_prepend (focus_chain, priv->command_hbox);
+ focus_chain = g_list_prepend (focus_chain, priv->comment_entry);
+ focus_chain = g_list_reverse (focus_chain);
+ gtk_container_set_focus_chain (GTK_CONTAINER (priv->table),
+ focus_chain);
+ g_list_free (focus_chain);
+
+ gtk_widget_grab_focus (priv->name_entry);
+}
+
+/*
+ * Will save after SAVE_FREQUENCY milliseconds of no changes. If something is
+ * changed, the save is postponed to another SAVE_FREQUENCY seconds. This seems
+ * to be a saner behaviour than just saving every N seconds.
+ */
+static void
+panel_ditem_editor_changed (PanelDItemEditor *dialog)
+{
+ if (!dialog->priv->new_file) {
+ if (dialog->priv->save_timeout != 0)
+ g_source_remove (dialog->priv->save_timeout);
+
+ dialog->priv->save_timeout = g_timeout_add_seconds (
+ SAVE_FREQUENCY,
+ panel_ditem_editor_save_timeout,
+ dialog);
+
+ /* We can revert to the original state */
+ if (dialog->priv->revert_key_file != NULL)
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ REVERT_BUTTON,
+ TRUE);
+ }
+
+ dialog->priv->dirty = TRUE;
+ g_signal_emit (G_OBJECT (dialog), ditem_edit_signals[CHANGED], 0);
+}
+
+static void
+panel_ditem_editor_activated (PanelDItemEditor *dialog)
+{
+ if (gtk_widget_get_visible (dialog->priv->ok_button))
+ gtk_dialog_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK);
+ else if (gtk_widget_get_visible (dialog->priv->close_button))
+ gtk_dialog_response (GTK_DIALOG (dialog),
+ GTK_RESPONSE_CLOSE);
+}
+
+static void
+panel_ditem_editor_name_changed (PanelDItemEditor *dialog)
+{
+ const char *name;
+
+ name = gtk_entry_get_text (GTK_ENTRY (dialog->priv->name_entry));
+
+ if (!dialog->priv->reverting) {
+ /* When reverting, we don't need to set the content of the key
+ * file; we only want to send a signal. Changing the key file
+ * could actually break the revert since it might overwrite the
+ * old Name value with the X-MATE-FullName value */
+ if (name && name[0])
+ panel_key_file_set_locale_string (dialog->priv->key_file,
+ "Name", name);
+ else
+ panel_key_file_remove_all_locale_key (dialog->priv->key_file,
+ "Name");
+
+ panel_key_file_remove_all_locale_key (dialog->priv->key_file,
+ "X-MATE-FullName");
+ }
+
+ g_signal_emit (G_OBJECT (dialog), ditem_edit_signals[NAME_CHANGED], 0,
+ name);
+}
+
+static void
+panel_ditem_editor_command_changed (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorType type;
+ const char *exec_or_uri;
+ GtkIconTheme *icon_theme;
+ char *icon;
+
+ exec_or_uri = gtk_entry_get_text (GTK_ENTRY (dialog->priv->command_entry));
+
+ if (exec_or_uri && exec_or_uri[0])
+ type = panel_ditem_editor_get_item_type (dialog);
+ else
+ type = PANEL_DITEM_EDITOR_TYPE_NULL;
+
+ switch (type) {
+ case PANEL_DITEM_EDITOR_TYPE_APPLICATION:
+ case PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION:
+ panel_key_file_remove_key (dialog->priv->key_file, "URL");
+ panel_key_file_set_string (dialog->priv->key_file, "Exec",
+ exec_or_uri);
+
+ icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (dialog)));
+ icon = guess_icon_from_exec (icon_theme,
+ dialog->priv->key_file);
+ if (icon) {
+ char *current;
+
+ current = panel_key_file_get_locale_string (dialog->priv->key_file,
+ "Icon");
+
+ if (!current || strcmp (icon, current))
+ setup_icon_chooser (dialog, icon);
+
+ g_free (current);
+ g_free (icon);
+ }
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_LINK:
+ panel_key_file_remove_key (dialog->priv->key_file, "Exec");
+ panel_key_file_set_string (dialog->priv->key_file, "URL",
+ exec_or_uri);
+ break;
+ default:
+ panel_key_file_remove_key (dialog->priv->key_file, "Exec");
+ panel_key_file_remove_key (dialog->priv->key_file, "URL");
+ }
+
+ g_signal_emit (G_OBJECT (dialog), ditem_edit_signals[COMMAND_CHANGED],
+ 0, exec_or_uri);
+}
+
+static void
+panel_ditem_editor_comment_changed (PanelDItemEditor *dialog)
+{
+ const char *comment;
+
+ comment = gtk_entry_get_text (GTK_ENTRY (dialog->priv->comment_entry));
+
+ if (comment && comment[0])
+ panel_key_file_set_locale_string (dialog->priv->key_file,
+ "Comment", comment);
+ else
+ panel_key_file_remove_all_locale_key (dialog->priv->key_file,
+ "Comment");
+
+ g_signal_emit (G_OBJECT (dialog), ditem_edit_signals[COMMENT_CHANGED],
+ 0, comment);
+}
+
+static void
+panel_ditem_editor_icon_changed (PanelDItemEditor *dialog,
+ const char *icon)
+{
+ if (icon)
+ panel_key_file_set_locale_string (dialog->priv->key_file,
+ "Icon", icon);
+ else
+ panel_key_file_remove_all_locale_key (dialog->priv->key_file,
+ "Icon");
+
+ g_signal_emit (G_OBJECT (dialog), ditem_edit_signals[ICON_CHANGED], 0,
+ icon);
+}
+
+static void
+command_browse_chooser_response (GtkFileChooser *chooser,
+ gint response_id,
+ PanelDItemEditor *dialog)
+{
+ char *uri;
+ char *text;
+
+ if (response_id == GTK_RESPONSE_ACCEPT) {
+ switch (panel_ditem_editor_get_item_type (dialog)) {
+ case PANEL_DITEM_EDITOR_TYPE_APPLICATION:
+ case PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION:
+ text = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
+ uri = panel_util_make_exec_uri_for_desktop (text);
+ g_free (text);
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_LINK:
+ uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (chooser));
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ gtk_entry_set_text (GTK_ENTRY (dialog->priv->command_entry),
+ uri);
+ g_free (uri);
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (chooser));
+ dialog->priv->command_browse_filechooser = NULL;
+}
+
+static void
+update_chooser_for_type (PanelDItemEditor *dialog)
+{
+ const char *title;
+ gboolean local_only;
+ GtkWidget *chooser;
+
+ if (!dialog->priv->command_browse_filechooser)
+ return;
+
+ switch (panel_ditem_editor_get_item_type (dialog)) {
+ case PANEL_DITEM_EDITOR_TYPE_APPLICATION:
+ case PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION:
+ title = _("Choose an application...");
+ local_only = TRUE;
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_LINK:
+ title = _("Choose a file...");
+ local_only = FALSE;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ chooser = dialog->priv->command_browse_filechooser;
+
+ gtk_window_set_title (GTK_WINDOW (chooser),
+ title);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser),
+ local_only);
+}
+
+static void
+command_browse_button_clicked (PanelDItemEditor *dialog)
+{
+ GtkWidget *chooser;
+
+ if (dialog->priv->command_browse_filechooser) {
+ gtk_window_present (GTK_WINDOW (dialog->priv->command_browse_filechooser));
+ return;
+ }
+
+ chooser = gtk_file_chooser_dialog_new ("", GTK_WINDOW (dialog),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN,
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (chooser), TRUE);
+
+ g_signal_connect (chooser, "response",
+ G_CALLBACK (command_browse_chooser_response), dialog);
+
+ dialog->priv->command_browse_filechooser = chooser;
+ update_chooser_for_type (dialog);
+
+ gtk_widget_show (chooser);
+}
+
+static void
+panel_ditem_editor_connect_signals (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorPrivate *priv;
+
+ priv = dialog->priv;
+
+#define CONNECT_CHANGED(widget, callback) \
+ g_signal_connect_swapped (G_OBJECT (widget), "changed", \
+ G_CALLBACK (callback), \
+ dialog); \
+ g_signal_connect_swapped (G_OBJECT (widget), "changed", \
+ G_CALLBACK (panel_ditem_editor_changed), \
+ dialog);
+
+ CONNECT_CHANGED (priv->type_combo, type_combo_changed);
+ CONNECT_CHANGED (priv->name_entry, panel_ditem_editor_name_changed);
+ CONNECT_CHANGED (priv->command_entry, panel_ditem_editor_command_changed);
+ CONNECT_CHANGED (priv->comment_entry, panel_ditem_editor_comment_changed);
+ CONNECT_CHANGED (priv->icon_chooser, panel_ditem_editor_icon_changed);
+
+ g_signal_connect_swapped (priv->name_entry, "activate",
+ G_CALLBACK (panel_ditem_editor_activated),
+ dialog);
+ g_signal_connect_swapped (priv->command_entry, "activate",
+ G_CALLBACK (panel_ditem_editor_activated),
+ dialog);
+ g_signal_connect_swapped (priv->comment_entry, "activate",
+ G_CALLBACK (panel_ditem_editor_activated),
+ dialog);
+
+ g_signal_connect_swapped (priv->command_browse_button, "clicked",
+ G_CALLBACK (command_browse_button_clicked),
+ dialog);
+
+ /* We do a signal connection here rather than overriding the method in
+ * class_init because GtkDialog::response is a RUN_LAST signal. We
+ * want *our* handler to be run *first*, regardless of whether the user
+ * installs response handlers of his own.
+ */
+ g_signal_connect (dialog, "response", G_CALLBACK (response_cb), NULL);
+}
+
+static void
+panel_ditem_editor_block_signals (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorPrivate *priv;
+
+ priv = dialog->priv;
+
+#define BLOCK_CHANGED(widget, callback) \
+ g_signal_handlers_block_by_func (G_OBJECT (widget), \
+ G_CALLBACK (callback), \
+ dialog); \
+ g_signal_handlers_block_by_func (G_OBJECT (widget), \
+ G_CALLBACK (panel_ditem_editor_changed), \
+ dialog);
+ BLOCK_CHANGED (priv->type_combo, type_combo_changed);
+ BLOCK_CHANGED (priv->name_entry, panel_ditem_editor_name_changed);
+ BLOCK_CHANGED (priv->command_entry, panel_ditem_editor_command_changed);
+ BLOCK_CHANGED (priv->comment_entry, panel_ditem_editor_comment_changed);
+ BLOCK_CHANGED (priv->icon_chooser, panel_ditem_editor_icon_changed);
+}
+
+static void
+panel_ditem_editor_unblock_signals (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorPrivate *priv;
+
+ priv = dialog->priv;
+
+#define UNBLOCK_CHANGED(widget, callback) \
+ g_signal_handlers_unblock_by_func (G_OBJECT (widget), \
+ G_CALLBACK (callback), \
+ dialog); \
+ g_signal_handlers_unblock_by_func (G_OBJECT (widget), \
+ G_CALLBACK (panel_ditem_editor_changed), \
+ dialog);
+ UNBLOCK_CHANGED (priv->type_combo, type_combo_changed);
+ UNBLOCK_CHANGED (priv->name_entry, panel_ditem_editor_name_changed);
+ UNBLOCK_CHANGED (priv->command_entry, panel_ditem_editor_command_changed);
+ UNBLOCK_CHANGED (priv->comment_entry, panel_ditem_editor_comment_changed);
+ UNBLOCK_CHANGED (priv->icon_chooser, panel_ditem_editor_icon_changed);
+}
+
+static void
+panel_ditem_editor_init (PanelDItemEditor *dialog)
+{
+ PanelDItemEditorPrivate *priv;
+
+ priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog,
+ PANEL_TYPE_DITEM_EDITOR,
+ PanelDItemEditorPrivate);
+
+ dialog->priv = priv;
+
+ priv->key_file = NULL;
+ priv->free_key_file = FALSE;
+ priv->revert_key_file = NULL;
+ priv->reverting = FALSE;
+ priv->dirty = FALSE;
+ priv->save_timeout = 0;
+ priv->uri = NULL;
+ priv->type_directory = FALSE;
+ priv->new_file = TRUE;
+ priv->save_uri = NULL;
+ priv->save_uri_data = NULL;
+ priv->combo_setuped = FALSE;
+ priv->command_browse_filechooser = NULL;
+
+ panel_ditem_editor_make_ui (dialog);
+ panel_ditem_editor_connect_signals (dialog);
+}
+
+static void
+type_combo_changed (PanelDItemEditor *dialog)
+{
+ const char *text;
+ char *bold;
+
+ switch (panel_ditem_editor_get_item_type (dialog)) {
+ case PANEL_DITEM_EDITOR_TYPE_APPLICATION:
+ text = _("Comm_and:");
+ if (dialog->priv->combo_setuped) {
+ panel_key_file_set_string (dialog->priv->key_file,
+ "Type", "Application");
+ panel_key_file_set_boolean (dialog->priv->key_file,
+ "Terminal", FALSE);
+ }
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION:
+ text = _("Comm_and:");
+ if (dialog->priv->combo_setuped) {
+ panel_key_file_set_string (dialog->priv->key_file,
+ "Type", "Application");
+ panel_key_file_set_boolean (dialog->priv->key_file,
+ "Terminal", TRUE);
+ }
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_LINK:
+ text = _("_Location:");
+ if (dialog->priv->combo_setuped) {
+ panel_key_file_set_string (dialog->priv->key_file,
+ "Type", "Link");
+ panel_key_file_remove_key (dialog->priv->key_file,
+ "Terminal");
+ }
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_DIRECTORY:
+ if (dialog->priv->combo_setuped) {
+ panel_key_file_set_string (dialog->priv->key_file,
+ "Type", "Directory");
+ }
+ return;
+ default:
+ g_assert_not_reached ();
+ }
+
+ bold = g_strdup_printf ("<b>%s</b>", text);
+ gtk_label_set_markup_with_mnemonic (GTK_LABEL (dialog->priv->command_label),
+ bold);
+ g_free (bold);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (dialog->priv->command_label),
+ dialog->priv->command_entry);
+
+ update_chooser_for_type (dialog);
+}
+
+static void
+setup_icon_chooser (PanelDItemEditor *dialog,
+ const char *icon_name)
+{
+ char *buffer;
+
+ if (!icon_name || icon_name[0] == '\0') {
+ if (dialog->priv->type_directory) {
+ buffer = g_strdup (PANEL_ICON_FOLDER);
+ } else {
+ buffer = g_strdup (PANEL_ICON_LAUNCHER);
+ }
+ } else {
+ buffer = g_strdup (icon_name);
+ }
+
+ panel_icon_chooser_set_icon (PANEL_ICON_CHOOSER (dialog->priv->icon_chooser),
+ buffer);
+
+ g_free (buffer);
+}
+
+/* Conform display to ditem */
+void
+panel_ditem_editor_sync_display (PanelDItemEditor *dialog)
+{
+ char *type;
+ PanelDItemEditorType editor_type;
+ gboolean run_in_terminal;
+ GKeyFile *key_file;
+ char *buffer;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ PanelDItemEditorType buf_type;
+
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ key_file = dialog->priv->key_file;
+
+ /* Name */
+ buffer = panel_key_file_get_locale_string (key_file, "X-MATE-FullName");
+ if (!buffer)
+ buffer = panel_key_file_get_locale_string (key_file, "Name");
+ gtk_entry_set_text (GTK_ENTRY (dialog->priv->name_entry),
+ buffer ? buffer : "");
+ g_free (buffer);
+
+ /* Type */
+ type = panel_key_file_get_string (key_file, "Type");
+ if (!dialog->priv->combo_setuped) {
+ setup_combo (dialog->priv->type_combo,
+ type_items, G_N_ELEMENTS (type_items),
+ type);
+ dialog->priv->combo_setuped = TRUE;
+ }
+
+ run_in_terminal = panel_key_file_get_boolean (key_file, "Terminal",
+ FALSE);
+ editor_type = map_type_from_desktop_item (type, run_in_terminal);
+ g_free (type);
+
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->priv->type_combo));
+ if (!gtk_tree_model_get_iter_first (model, &iter))
+ g_assert_not_reached ();
+ do {
+ gtk_tree_model_get (model, &iter, COLUMN_TYPE, &buf_type, -1);
+ if (editor_type == buf_type) {
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (dialog->priv->type_combo),
+ &iter);
+ break;
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ g_assert (editor_type == buf_type ||
+ editor_type == PANEL_DITEM_EDITOR_TYPE_NULL);
+
+ /* Command */
+ if (editor_type == PANEL_DITEM_EDITOR_TYPE_LINK)
+ buffer = panel_key_file_get_string (key_file, "URL");
+ else if (editor_type == PANEL_DITEM_EDITOR_TYPE_APPLICATION ||
+ editor_type == PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION)
+ buffer = panel_key_file_get_string (key_file, "Exec");
+ else
+ buffer = NULL;
+
+ gtk_entry_set_text (GTK_ENTRY (dialog->priv->command_entry),
+ buffer ? buffer : "");
+ g_free (buffer);
+
+ /* Comment */
+ buffer = panel_key_file_get_locale_string (key_file, "Comment");
+ gtk_entry_set_text (GTK_ENTRY (dialog->priv->comment_entry),
+ buffer ? buffer : "");
+ g_free (buffer);
+
+
+ /* Icon */
+ buffer = panel_key_file_get_locale_string (key_file, "Icon");
+ setup_icon_chooser (dialog, buffer);
+ g_free (buffer);
+
+ if (dialog->priv->save_timeout != 0) {
+ g_source_remove (dialog->priv->save_timeout);
+ dialog->priv->save_timeout = 0;
+ }
+}
+
+static gboolean
+panel_ditem_editor_save (PanelDItemEditor *dialog,
+ gboolean report_errors)
+{
+ GKeyFile *key_file;
+ const char *const_buf;
+ GError *error;
+
+ g_return_val_if_fail (dialog != NULL, FALSE);
+ g_return_val_if_fail (dialog->priv->save_uri != NULL ||
+ dialog->priv->uri != NULL, FALSE);
+
+ if (dialog->priv->save_timeout != 0)
+ g_source_remove (dialog->priv->save_timeout);
+ dialog->priv->save_timeout = 0;
+
+ if (!dialog->priv->dirty)
+ return TRUE;
+
+ /* Verify that the required informations are set */
+ const_buf = gtk_entry_get_text (GTK_ENTRY (dialog->priv->name_entry));
+ if (const_buf == NULL || const_buf [0] == '\0') {
+ if (report_errors) {
+ if (!dialog->priv->type_directory)
+ g_signal_emit (G_OBJECT (dialog),
+ ditem_edit_signals[ERROR_REPORTED], 0,
+ _("Could not save launcher"),
+ _("The name of the launcher is not set."));
+ else
+ g_signal_emit (G_OBJECT (dialog),
+ ditem_edit_signals[ERROR_REPORTED], 0,
+ _("Could not save directory properties"),
+ _("The name of the directory is not set."));
+ }
+ return FALSE;
+ }
+
+ const_buf = gtk_entry_get_text (GTK_ENTRY (dialog->priv->command_entry));
+ if (!dialog->priv->type_directory &&
+ (const_buf == NULL || const_buf [0] == '\0')) {
+ PanelDItemEditorType type;
+ char *err;
+
+ type = panel_ditem_editor_get_item_type (dialog);
+
+ switch (type) {
+ case PANEL_DITEM_EDITOR_TYPE_APPLICATION:
+ case PANEL_DITEM_EDITOR_TYPE_TERMINAL_APPLICATION:
+ err = _("The command of the launcher is not set.");
+ break;
+ case PANEL_DITEM_EDITOR_TYPE_LINK:
+ err = _("The location of the launcher is not set.");
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (report_errors)
+ g_signal_emit (G_OBJECT (dialog),
+ ditem_edit_signals[ERROR_REPORTED], 0,
+ _("Could not save launcher"), err);
+ return FALSE;
+ }
+
+ key_file = dialog->priv->key_file;
+
+ panel_key_file_ensure_C_key (key_file, "Name");
+ panel_key_file_ensure_C_key (key_file, "Comment");
+ panel_key_file_ensure_C_key (key_file, "Icon");
+
+ if (dialog->priv->save_uri) {
+ char *uri;
+
+ uri = dialog->priv->save_uri (dialog,
+ dialog->priv->save_uri_data);
+
+ if (uri) {
+ panel_ditem_editor_set_uri (dialog, uri);
+ g_free (uri);
+ }
+ }
+
+ /* And now, try to save */
+ error = NULL;
+ panel_key_file_to_file (dialog->priv->key_file,
+ dialog->priv->uri,
+ &error);
+ if (error != NULL) {
+ if (report_errors)
+ g_signal_emit (G_OBJECT (dialog),
+ ditem_edit_signals[ERROR_REPORTED], 0,
+ _("Could not save launcher"),
+ error->message);
+ g_error_free (error);
+ return FALSE;
+ } else {
+ g_signal_emit (G_OBJECT (dialog),
+ ditem_edit_signals[SAVED], 0);
+ }
+
+ dialog->priv->dirty = FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+panel_ditem_editor_save_timeout (gpointer data)
+{
+ PanelDItemEditor *dialog;
+
+ dialog = PANEL_DITEM_EDITOR (data);
+ panel_ditem_editor_save (dialog, FALSE);
+
+ return FALSE;
+}
+
+static void
+response_cb (GtkDialog *dialog,
+ gint response_id)
+{
+ GError *error = NULL;
+
+ switch (response_id) {
+ case GTK_RESPONSE_HELP:
+ if (!panel_show_help (gtk_window_get_screen (GTK_WINDOW (dialog)),
+ "user-guide", "gospanel-52", &error)) {
+ g_signal_emit (G_OBJECT (dialog),
+ ditem_edit_signals[ERROR_REPORTED], 0,
+ _("Could not display help document"),
+ error->message);
+ g_error_free (error);
+ }
+ break;
+ case REVERT_BUTTON:
+ panel_ditem_editor_revert (PANEL_DITEM_EDITOR (dialog));
+ gtk_dialog_set_response_sensitive (dialog,
+ REVERT_BUTTON,
+ FALSE);
+ break;
+ case GTK_RESPONSE_OK:
+ case GTK_RESPONSE_CLOSE:
+ if (panel_ditem_editor_save (PANEL_DITEM_EDITOR (dialog), TRUE))
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ break;
+ case GTK_RESPONSE_DELETE_EVENT:
+ if (!PANEL_DITEM_EDITOR (dialog)->priv->new_file)
+ /* We need to revert the changes */
+ gtk_dialog_response (dialog, REVERT_BUTTON);
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ break;
+ case GTK_RESPONSE_CANCEL:
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+panel_ditem_editor_revert (PanelDItemEditor *dialog)
+{
+ int i;
+ char *string;
+ gboolean boolean;
+ GKeyFile *key_file;
+ GKeyFile *revert_key_file;
+
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ dialog->priv->reverting = TRUE;
+
+ key_file = dialog->priv->key_file;
+ revert_key_file = dialog->priv->revert_key_file;
+
+ g_assert (revert_key_file != NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (revert_keys); i++) {
+ if (revert_keys [i].type == G_TYPE_STRING) {
+ if (revert_keys [i].locale) {
+ string = panel_key_file_get_locale_string (
+ revert_key_file,
+ revert_keys [i].key);
+ if (string == NULL)
+ panel_key_file_remove_all_locale_key (
+ key_file,
+ revert_keys [i].key);
+ else
+ panel_key_file_set_locale_string (
+ key_file,
+ revert_keys [i].key,
+ string);
+ } else {
+ string = panel_key_file_get_string (
+ revert_key_file,
+ revert_keys [i].key);
+ if (string == NULL)
+ panel_key_file_remove_key (
+ key_file,
+ revert_keys [i].key);
+ else
+ panel_key_file_set_string (
+ key_file,
+ revert_keys [i].key,
+ string);
+ }
+ g_free (string);
+ } else if (revert_keys [i].type == G_TYPE_BOOLEAN) {
+ boolean = panel_key_file_get_boolean (
+ revert_key_file,
+ revert_keys [i].key,
+ revert_keys [i].default_value);
+ panel_key_file_set_boolean (key_file,
+ revert_keys [i].key,
+ boolean);
+ } else {
+ g_assert_not_reached ();
+ }
+ }
+
+ panel_ditem_editor_sync_display (dialog);
+
+ if (!dialog->priv->new_file) {
+ if (dialog->priv->save_timeout != 0)
+ g_source_remove (dialog->priv->save_timeout);
+
+ dialog->priv->save_timeout = g_timeout_add_seconds (
+ SAVE_FREQUENCY,
+ panel_ditem_editor_save_timeout,
+ dialog);
+ }
+
+ dialog->priv->reverting = FALSE;
+}
+
+static void
+panel_ditem_editor_set_revert (PanelDItemEditor *dialog)
+{
+ int i;
+ char *string;
+ gboolean boolean;
+ GKeyFile *key_file;
+ GKeyFile *revert_key_file;
+
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ key_file = dialog->priv->key_file;
+ if (dialog->priv->revert_key_file)
+ g_key_file_free (dialog->priv->revert_key_file);
+ dialog->priv->revert_key_file = g_key_file_new ();
+ revert_key_file = dialog->priv->revert_key_file;
+
+ for (i = 0; i < G_N_ELEMENTS (revert_keys); i++) {
+ if (revert_keys [i].type == G_TYPE_STRING) {
+ if (revert_keys [i].locale) {
+ string = panel_key_file_get_locale_string (
+ key_file,
+ revert_keys [i].key);
+ if (string != NULL)
+ panel_key_file_set_locale_string (
+ revert_key_file,
+ revert_keys [i].key,
+ string);
+ } else {
+ string = panel_key_file_get_string (
+ key_file,
+ revert_keys [i].key);
+ if (string != NULL)
+ panel_key_file_set_string (
+ revert_key_file,
+ revert_keys [i].key,
+ string);
+ }
+ g_free (string);
+ } else if (revert_keys [i].type == G_TYPE_BOOLEAN) {
+ boolean = panel_key_file_get_boolean (
+ key_file,
+ revert_keys [i].key,
+ revert_keys [i].default_value);
+ panel_key_file_set_boolean (revert_key_file,
+ revert_keys [i].key,
+ boolean);
+ } else {
+ g_assert_not_reached ();
+ }
+ }
+}
+
+static void
+panel_ditem_editor_key_file_loaded (PanelDItemEditor *dialog)
+{
+ /* the user is not changing any value here, so block the signals about
+ * changing a value */
+ panel_ditem_editor_block_signals (dialog);
+ panel_ditem_editor_sync_display (dialog);
+ panel_ditem_editor_unblock_signals (dialog);
+
+ /* This should be after panel_ditem_editor_sync_display ()
+ * so the revert button is insensitive */
+ if (dialog->priv->revert_key_file != NULL)
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+ REVERT_BUTTON,
+ TRUE);
+ else
+ panel_ditem_editor_set_revert (dialog);
+}
+
+static gboolean
+panel_ditem_editor_load_uri (PanelDItemEditor *dialog,
+ GError **error)
+{
+ GKeyFile *key_file;
+
+ g_return_val_if_fail (PANEL_IS_DITEM_EDITOR (dialog), FALSE);
+ g_return_val_if_fail (dialog->priv->uri != NULL, FALSE);
+
+ key_file = g_key_file_new ();
+
+ if (!panel_key_file_load_from_uri (key_file,
+ dialog->priv->uri,
+ G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS,
+ error)) {
+ g_key_file_free (key_file);
+ return FALSE;
+ }
+
+ if (dialog->priv->free_key_file && dialog->priv->key_file)
+ g_key_file_free (dialog->priv->key_file);
+ dialog->priv->key_file = key_file;
+
+ panel_ditem_editor_key_file_loaded (dialog);
+
+ return TRUE;
+}
+
+static GtkWidget *
+panel_ditem_editor_new_full (GtkWindow *parent,
+ GKeyFile *key_file,
+ const char *uri,
+ const char *title,
+ gboolean type_directory)
+{
+ GtkWidget *dialog;
+
+ dialog = g_object_new (PANEL_TYPE_DITEM_EDITOR,
+ "title", title,
+ "keyfile", key_file,
+ "uri", uri,
+ "type-directory", type_directory,
+ NULL);
+
+ if (parent)
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
+
+ return dialog;
+}
+
+GtkWidget *
+panel_ditem_editor_new (GtkWindow *parent,
+ GKeyFile *key_file,
+ const char *uri,
+ const char *title)
+{
+ return panel_ditem_editor_new_full (parent, key_file, uri,
+ title, FALSE);
+}
+
+GtkWidget *
+panel_ditem_editor_new_directory (GtkWindow *parent,
+ GKeyFile *key_file,
+ const char *uri,
+ const char *title)
+{
+ return panel_ditem_editor_new_full (parent, key_file, uri,
+ title, TRUE);
+}
+
+static void
+panel_ditem_editor_set_key_file (PanelDItemEditor *dialog,
+ GKeyFile *key_file)
+{
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ if (dialog->priv->key_file == key_file)
+ return;
+
+ if (dialog->priv->free_key_file && dialog->priv->key_file)
+ g_key_file_free (dialog->priv->key_file);
+ dialog->priv->key_file = key_file;
+
+ g_object_notify (G_OBJECT (dialog), "keyfile");
+}
+
+void
+panel_ditem_editor_set_uri (PanelDItemEditor *dialog,
+ const char *uri)
+{
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ if (!dialog->priv->uri && (!uri || !uri [0]))
+ return;
+
+ if (dialog->priv->uri && uri && uri [0] &&
+ !strcmp (dialog->priv->uri, uri))
+ return;
+
+ if (dialog->priv->uri)
+ g_free (dialog->priv->uri);
+ dialog->priv->uri = NULL;
+
+ if (uri && uri [0])
+ dialog->priv->uri = g_strdup (uri);
+
+ g_object_notify (G_OBJECT (dialog), "uri");
+}
+
+static void
+panel_ditem_editor_set_type_directory (PanelDItemEditor *dialog,
+ gboolean type_directory)
+{
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ if (dialog->priv->type_directory == type_directory)
+ return;
+
+ dialog->priv->type_directory = type_directory;
+
+ g_object_notify (G_OBJECT (dialog), "type-directory");
+}
+
+GKeyFile *
+panel_ditem_editor_get_key_file (PanelDItemEditor *dialog)
+{
+ g_return_val_if_fail (PANEL_IS_DITEM_EDITOR (dialog), NULL);
+
+ return dialog->priv->key_file;
+}
+
+GKeyFile *
+panel_ditem_editor_get_revert_key_file (PanelDItemEditor *dialog)
+{
+ g_return_val_if_fail (PANEL_IS_DITEM_EDITOR (dialog), NULL);
+
+ return dialog->priv->revert_key_file;
+}
+
+const char* panel_ditem_editor_get_uri(PanelDItemEditor* dialog)
+{
+ g_return_val_if_fail(PANEL_IS_DITEM_EDITOR(dialog), NULL);
+
+ return dialog->priv->uri;
+}
+
+static gboolean
+panel_ditem_editor_get_type_directory (PanelDItemEditor *dialog)
+{
+ g_return_val_if_fail (PANEL_IS_DITEM_EDITOR (dialog), FALSE);
+
+ return dialog->priv->type_directory;
+}
+
+void
+panel_ditem_register_save_uri_func (PanelDItemEditor *dialog,
+ PanelDitemSaveUri save_uri,
+ gpointer data)
+{
+ g_return_if_fail (PANEL_IS_DITEM_EDITOR (dialog));
+
+ dialog->priv->save_uri = save_uri;
+ dialog->priv->save_uri_data = data;
+}