summaryrefslogtreecommitdiff
path: root/mate-panel/panel-addto.c
diff options
context:
space:
mode:
authorPerberos <[email protected]>2011-12-01 22:56:10 -0300
committerPerberos <[email protected]>2011-12-01 22:56:10 -0300
commitc51ef797a707f4e2c6f9688d4378f2b0e9898a66 (patch)
tree019ae92bb53c19b30077545cb14743cbd1b57aef /mate-panel/panel-addto.c
downloadmate-panel-c51ef797a707f4e2c6f9688d4378f2b0e9898a66.tar.bz2
mate-panel-c51ef797a707f4e2c6f9688d4378f2b0e9898a66.tar.xz
moving from https://github.com/perberos/mate-desktop-environment
Diffstat (limited to 'mate-panel/panel-addto.c')
-rw-r--r--mate-panel/panel-addto.c1428
1 files changed, 1428 insertions, 0 deletions
diff --git a/mate-panel/panel-addto.c b/mate-panel/panel-addto.c
new file mode 100644
index 00000000..150d83de
--- /dev/null
+++ b/mate-panel/panel-addto.c
@@ -0,0 +1,1428 @@
+/*
+ * panel-addto.c:
+ *
+ * Copyright (C) 2004 Vincent Untz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 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 <matemenu-tree.h>
+
+#include <libpanel-util/panel-glib.h>
+#include <libpanel-util/panel-show.h>
+
+#include "launcher.h"
+#include "panel.h"
+#include "drawer.h"
+#include "mate-panel-applets-manager.h"
+#include "mate-panel-applet-frame.h"
+#include "panel-action-button.h"
+#include "panel-menu-bar.h"
+#include "panel-separator.h"
+#include "panel-toplevel.h"
+#include "panel-menu-button.h"
+#include "panel-globals.h"
+#include "panel-lockdown.h"
+#include "panel-util.h"
+#include "panel-profile.h"
+#include "panel-addto.h"
+#include "panel-icon-names.h"
+
+typedef struct {
+ PanelWidget *panel_widget;
+
+ GtkWidget *addto_dialog;
+ GtkWidget *label;
+ GtkWidget *search_entry;
+ GtkWidget *back_button;
+ GtkWidget *add_button;
+ GtkWidget *tree_view;
+ GtkTreeModel *applet_model;
+ GtkTreeModel *filter_applet_model;
+ GtkTreeModel *application_model;
+ GtkTreeModel *filter_application_model;
+
+ MateMenuTree *menu_tree;
+
+ GSList *applet_list;
+ GSList *application_list;
+ GSList *settings_list;
+
+ gchar *search_text;
+ gchar *applet_search_text;
+
+ guint name_notify;
+
+ int insertion_position;
+} PanelAddtoDialog;
+
+static GQuark panel_addto_dialog_quark = 0;
+
+typedef enum {
+ PANEL_ADDTO_APPLET,
+ PANEL_ADDTO_ACTION,
+ PANEL_ADDTO_LAUNCHER_MENU,
+ PANEL_ADDTO_LAUNCHER,
+ PANEL_ADDTO_LAUNCHER_NEW,
+ PANEL_ADDTO_MENU,
+ PANEL_ADDTO_MENUBAR,
+ PANEL_ADDTO_SEPARATOR,
+ PANEL_ADDTO_DRAWER
+} PanelAddtoItemType;
+
+typedef struct {
+ PanelAddtoItemType type;
+ char *name;
+ char *description;
+ char *icon;
+ PanelActionButtonType action_type;
+ char *launcher_path;
+ char *menu_filename;
+ char *menu_path;
+ char *iid;
+ gboolean static_data;
+} PanelAddtoItemInfo;
+
+typedef struct {
+ GSList *children;
+ PanelAddtoItemInfo item_info;
+} PanelAddtoAppList;
+
+static PanelAddtoItemInfo special_addto_items [] = {
+
+ { PANEL_ADDTO_LAUNCHER_NEW,
+ N_("Custom Application Launcher"),
+ N_("Create a new launcher"),
+ PANEL_ICON_LAUNCHER,
+ PANEL_ACTION_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "LAUNCHER:ASK",
+ TRUE },
+
+ { PANEL_ADDTO_LAUNCHER_MENU,
+ N_("Application Launcher..."),
+ N_("Copy a launcher from the applications menu"),
+ PANEL_ICON_LAUNCHER,
+ PANEL_ACTION_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "LAUNCHER:MENU",
+ TRUE }
+
+};
+
+static PanelAddtoItemInfo internal_addto_items [] = {
+
+ { PANEL_ADDTO_MENU,
+ N_("Main Menu"),
+ N_("The main MATE menu"),
+ PANEL_ICON_MAIN_MENU,
+ PANEL_ACTION_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "MENU:MAIN",
+ TRUE },
+
+ { PANEL_ADDTO_MENUBAR,
+ N_("Menu Bar"),
+ N_("A custom menu bar"),
+ PANEL_ICON_MAIN_MENU,
+ PANEL_ACTION_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "MENUBAR:NEW",
+ TRUE },
+
+ { PANEL_ADDTO_SEPARATOR,
+ N_("Separator"),
+ N_("A separator to organize the panel items"),
+ PANEL_ICON_SEPARATOR,
+ PANEL_ACTION_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "SEPARATOR:NEW",
+ TRUE },
+
+ { PANEL_ADDTO_DRAWER,
+ N_("Drawer"),
+ N_("A pop out drawer to store other items in"),
+ PANEL_ICON_DRAWER,
+ PANEL_ACTION_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "DRAWER:NEW",
+ TRUE }
+};
+
+enum {
+ COLUMN_ICON,
+ COLUMN_TEXT,
+ COLUMN_DATA,
+ COLUMN_SEARCH,
+ NUMBER_COLUMNS
+};
+
+enum {
+ PANEL_ADDTO_RESPONSE_BACK,
+ PANEL_ADDTO_RESPONSE_ADD
+};
+
+static void panel_addto_present_applications (PanelAddtoDialog *dialog);
+static void panel_addto_present_applets (PanelAddtoDialog *dialog);
+static gboolean panel_addto_filter_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data);
+
+static int
+panel_addto_applet_info_sort_func (PanelAddtoItemInfo *a,
+ PanelAddtoItemInfo *b)
+{
+ return g_utf8_collate (a->name, b->name);
+}
+
+static GSList *
+panel_addto_prepend_internal_applets (GSList *list)
+{
+ static gboolean translated = FALSE;
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (internal_addto_items); i++) {
+ if (!translated) {
+ internal_addto_items [i].name = _(internal_addto_items [i].name);
+ internal_addto_items [i].description = _(internal_addto_items [i].description);
+ }
+
+ list = g_slist_prepend (list, &internal_addto_items [i]);
+ }
+
+ translated = TRUE;
+
+ for (i = PANEL_ACTION_LOCK; i < PANEL_ACTION_LAST; i++) {
+ PanelAddtoItemInfo *info;
+
+ if (panel_action_get_is_disabled (i))
+ continue;
+
+ info = g_new0 (PanelAddtoItemInfo, 1);
+ info->type = PANEL_ADDTO_ACTION;
+ info->action_type = i;
+ info->name = g_strdup (panel_action_get_text (i));
+ info->description = g_strdup (panel_action_get_tooltip (i));
+ info->icon = g_strdup (panel_action_get_icon_name (i));
+ info->iid = g_strdup (panel_action_get_drag_id (i));
+ info->static_data = FALSE;
+
+ list = g_slist_prepend (list, info);
+ }
+
+ return list;
+}
+
+static char *
+panel_addto_make_text (const char *name,
+ const char *desc)
+{
+ const char *real_name;
+ char *result;
+
+ real_name = name ? name : _("(empty)");
+
+ if (!PANEL_GLIB_STR_EMPTY (desc)) {
+ result = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>\n%s",
+ real_name, desc);
+ } else {
+ result = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>",
+ real_name);
+ }
+
+ return result;
+}
+
+#define ICON_SIZE 32
+
+static GdkPixbuf *
+panel_addto_make_pixbuf (const char *filename)
+{
+ //FIXME: size shouldn't be fixed but should depend on the font size
+ return panel_load_icon (gtk_icon_theme_get_default (),
+ filename,
+ ICON_SIZE, ICON_SIZE, ICON_SIZE,
+ NULL);
+}
+
+static void
+panel_addto_drag_data_get_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *selection_data,
+ guint info,
+ guint time,
+ const char *string)
+{
+ gtk_selection_data_set (selection_data,
+ gtk_selection_data_get_target (selection_data), 8,
+ (guchar *) string, strlen (string));
+}
+
+static void
+panel_addto_drag_begin_cb (GtkWidget *widget,
+ GdkDragContext *context,
+ gpointer data)
+{
+ GtkTreeModel *filter_model;
+ GtkTreeModel *child_model;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ GtkTreeIter filter_iter;
+ GdkPixbuf *pixbuf;
+
+ filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget));
+
+ gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &path, NULL);
+ gtk_tree_model_get_iter (filter_model, &filter_iter, path);
+ gtk_tree_path_free (path);
+ gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter_model),
+ &iter, &filter_iter);
+
+ child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model));
+ gtk_tree_model_get (child_model, &iter,
+ COLUMN_ICON, &pixbuf,
+ -1);
+
+ gtk_drag_set_icon_pixbuf (context, pixbuf, 0, 0);
+ g_object_unref (pixbuf);
+}
+
+static void
+panel_addto_setup_drag (GtkTreeView *tree_view,
+ const GtkTargetEntry *target,
+ const char *text)
+{
+ if (!text || panel_lockdown_get_locked_down ())
+ return;
+
+ gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (tree_view),
+ GDK_BUTTON1_MASK|GDK_BUTTON2_MASK,
+ target, 1, GDK_ACTION_COPY);
+
+ g_signal_connect_data (G_OBJECT (tree_view), "drag_data_get",
+ G_CALLBACK (panel_addto_drag_data_get_cb),
+ g_strdup (text),
+ (GClosureNotify) g_free,
+ 0 /* connect_flags */);
+ g_signal_connect_after (G_OBJECT (tree_view), "drag-begin",
+ G_CALLBACK (panel_addto_drag_begin_cb),
+ NULL);
+}
+
+static void
+panel_addto_setup_launcher_drag (GtkTreeView *tree_view,
+ const char *path)
+{
+ static GtkTargetEntry target[] = {
+ { "text/uri-list", 0, 0 }
+ };
+ char *uri;
+ char *uri_list;
+
+ uri = g_filename_to_uri (path, NULL, NULL);
+ uri_list = g_strconcat (uri, "\r\n", NULL);
+ panel_addto_setup_drag (tree_view, target, uri_list);
+ g_free (uri_list);
+ g_free (uri);
+}
+
+static void
+panel_addto_setup_applet_drag (GtkTreeView *tree_view,
+ const char *iid)
+{
+ static GtkTargetEntry target[] = {
+ { "application/x-mate-panel-applet-iid", 0, 0 }
+ };
+
+ panel_addto_setup_drag (tree_view, target, iid);
+}
+
+static void
+panel_addto_setup_internal_applet_drag (GtkTreeView *tree_view,
+ const char *applet_type)
+{
+ static GtkTargetEntry target[] = {
+ { "application/x-mate-panel-applet-internal", 0, 0 }
+ };
+
+ panel_addto_setup_drag (tree_view, target, applet_type);
+}
+
+static GSList *
+panel_addto_query_applets (GSList *list)
+{
+ GList *applet_list, *l;
+
+ applet_list = mate_panel_applets_manager_get_applets ();
+
+ for (l = applet_list; l; l = g_list_next (l)) {
+ MatePanelAppletInfo *info;
+ const char *iid, *name, *description, *icon;
+ PanelAddtoItemInfo *applet;
+
+ info = (MatePanelAppletInfo *)l->data;
+
+ iid = mate_panel_applet_info_get_iid (info);
+ name = mate_panel_applet_info_get_name (info);
+ description = mate_panel_applet_info_get_description (info);
+ icon = mate_panel_applet_info_get_icon (info);
+
+ if (!name || panel_lockdown_is_applet_disabled (iid)) {
+ continue;
+ }
+
+ applet = g_new0 (PanelAddtoItemInfo, 1);
+ applet->type = PANEL_ADDTO_APPLET;
+ applet->name = g_strdup (name);
+ applet->description = g_strdup (description);
+ applet->icon = g_strdup (icon);
+ applet->iid = g_strdup (iid);
+ applet->static_data = FALSE;
+
+ list = g_slist_prepend (list, applet);
+ }
+
+ g_list_free (applet_list);
+
+ return list;
+}
+
+static void
+panel_addto_append_item (PanelAddtoDialog *dialog,
+ GtkListStore *model,
+ PanelAddtoItemInfo *applet)
+{
+ char *text;
+ GdkPixbuf *pixbuf;
+ GtkTreeIter iter;
+
+ if (applet == NULL) {
+ gtk_list_store_append (model, &iter);
+ gtk_list_store_set (model, &iter,
+ COLUMN_ICON, NULL,
+ COLUMN_TEXT, NULL,
+ COLUMN_DATA, NULL,
+ COLUMN_SEARCH, NULL,
+ -1);
+ } else {
+ pixbuf = NULL;
+
+ if (applet->icon != NULL) {
+ pixbuf = panel_addto_make_pixbuf (applet->icon);
+ }
+
+ gtk_list_store_append (model, &iter);
+
+ text = panel_addto_make_text (applet->name,
+ applet->description);
+
+ gtk_list_store_set (model, &iter,
+ COLUMN_ICON, pixbuf,
+ COLUMN_TEXT, text,
+ COLUMN_DATA, applet,
+ COLUMN_SEARCH, applet->name,
+ -1);
+
+ if (pixbuf)
+ g_object_unref (pixbuf);
+
+ g_free (text);
+ }
+}
+
+static void
+panel_addto_append_special_applets (PanelAddtoDialog *dialog,
+ GtkListStore *model)
+{
+ static gboolean translated = FALSE;
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (special_addto_items); i++) {
+ if (!translated) {
+ special_addto_items [i].name = _(special_addto_items [i].name);
+ special_addto_items [i].description = _(special_addto_items [i].description);
+ }
+
+ if (special_addto_items [i].type == PANEL_ADDTO_LAUNCHER_NEW
+ && panel_lockdown_get_disable_command_line ())
+ continue;
+
+ panel_addto_append_item (dialog, model, &special_addto_items [i]);
+ }
+
+ translated = TRUE;
+}
+
+static void
+panel_addto_make_applet_model (PanelAddtoDialog *dialog)
+{
+ GtkListStore *model;
+ GSList *l;
+
+ if (dialog->filter_applet_model != NULL)
+ return;
+
+ if (panel_profile_id_lists_are_writable ()) {
+ dialog->applet_list = panel_addto_query_applets (dialog->applet_list);
+ dialog->applet_list = panel_addto_prepend_internal_applets (dialog->applet_list);
+ }
+
+ dialog->applet_list = g_slist_sort (dialog->applet_list,
+ (GCompareFunc) panel_addto_applet_info_sort_func);
+
+ model = gtk_list_store_new (NUMBER_COLUMNS,
+ GDK_TYPE_PIXBUF,
+ G_TYPE_STRING,
+ G_TYPE_POINTER,
+ G_TYPE_STRING);
+
+ if (panel_profile_id_lists_are_writable ()) {
+ panel_addto_append_special_applets (dialog, model);
+ if (dialog->applet_list)
+ panel_addto_append_item (dialog, model, NULL);
+ }
+
+ for (l = dialog->applet_list; l; l = l->next)
+ panel_addto_append_item (dialog, model, l->data);
+
+ dialog->applet_model = GTK_TREE_MODEL (model);
+ dialog->filter_applet_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (dialog->applet_model),
+ NULL);
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (dialog->filter_applet_model),
+ panel_addto_filter_func,
+ dialog, NULL);
+}
+
+static void panel_addto_make_application_list (GSList **parent_list,
+ MateMenuTreeDirectory *directory,
+ const char *filename);
+
+static void
+panel_addto_prepend_directory (GSList **parent_list,
+ MateMenuTreeDirectory *directory,
+ const char *filename)
+{
+ PanelAddtoAppList *data;
+
+ data = g_new0 (PanelAddtoAppList, 1);
+
+ data->item_info.type = PANEL_ADDTO_MENU;
+ data->item_info.name = g_strdup (matemenu_tree_directory_get_name (directory));
+ data->item_info.description = g_strdup (matemenu_tree_directory_get_comment (directory));
+ data->item_info.icon = g_strdup (matemenu_tree_directory_get_icon (directory));
+ data->item_info.menu_filename = g_strdup (filename);
+ data->item_info.menu_path = matemenu_tree_directory_make_path (directory, NULL);
+ data->item_info.static_data = FALSE;
+
+ /* We should set the iid here to something and do
+ * iid = g_strdup_printf ("MENU:%s", tfr->name)
+ * but this means we'd have to free the iid later
+ * and this would complexify too much the free
+ * function.
+ * So the iid is built when we select the row.
+ */
+
+ *parent_list = g_slist_prepend (*parent_list, data);
+
+ panel_addto_make_application_list (&data->children, directory, filename);
+}
+
+static void
+panel_addto_prepend_entry (GSList **parent_list,
+ MateMenuTreeEntry *entry,
+ const char *filename)
+{
+ PanelAddtoAppList *data;
+
+ data = g_new0 (PanelAddtoAppList, 1);
+
+ data->item_info.type = PANEL_ADDTO_LAUNCHER;
+ data->item_info.name = g_strdup (matemenu_tree_entry_get_display_name (entry));
+ data->item_info.description = g_strdup (matemenu_tree_entry_get_comment (entry));
+ data->item_info.icon = g_strdup (matemenu_tree_entry_get_icon (entry));
+ data->item_info.launcher_path = g_strdup (matemenu_tree_entry_get_desktop_file_path (entry));
+ data->item_info.static_data = FALSE;
+
+ *parent_list = g_slist_prepend (*parent_list, data);
+}
+
+static void
+panel_addto_prepend_alias (GSList **parent_list,
+ MateMenuTreeAlias *alias,
+ const char *filename)
+{
+ MateMenuTreeItem *aliased_item;
+
+ aliased_item = matemenu_tree_alias_get_item (alias);
+
+ switch (matemenu_tree_item_get_type (aliased_item)) {
+ case MATEMENU_TREE_ITEM_DIRECTORY:
+ panel_addto_prepend_directory (parent_list,
+ MATEMENU_TREE_DIRECTORY (aliased_item),
+ filename);
+ break;
+
+ case MATEMENU_TREE_ITEM_ENTRY:
+ panel_addto_prepend_entry (parent_list,
+ MATEMENU_TREE_ENTRY (aliased_item),
+ filename);
+ break;
+
+ default:
+ break;
+ }
+
+ matemenu_tree_item_unref (aliased_item);
+}
+
+static void
+panel_addto_make_application_list (GSList **parent_list,
+ MateMenuTreeDirectory *directory,
+ const char *filename)
+{
+ GSList *items;
+ GSList *l;
+
+ items = matemenu_tree_directory_get_contents (directory);
+
+ for (l = items; l; l = l->next) {
+ switch (matemenu_tree_item_get_type (l->data)) {
+ case MATEMENU_TREE_ITEM_DIRECTORY:
+ panel_addto_prepend_directory (parent_list, l->data, filename);
+ break;
+
+ case MATEMENU_TREE_ITEM_ENTRY:
+ panel_addto_prepend_entry (parent_list, l->data, filename);
+ break;
+
+ case MATEMENU_TREE_ITEM_ALIAS:
+ panel_addto_prepend_alias (parent_list, l->data, filename);
+ break;
+
+ default:
+ break;
+ }
+
+ matemenu_tree_item_unref (l->data);
+ }
+
+ g_slist_free (items);
+
+ *parent_list = g_slist_reverse (*parent_list);
+}
+
+static void
+panel_addto_populate_application_model (GtkTreeStore *store,
+ GtkTreeIter *parent,
+ GSList *app_list)
+{
+ PanelAddtoAppList *data;
+ GtkTreeIter iter;
+ char *text;
+ GdkPixbuf *pixbuf;
+ GSList *app;
+
+ for (app = app_list; app != NULL; app = app->next) {
+ data = app->data;
+ gtk_tree_store_append (store, &iter, parent);
+
+ text = panel_addto_make_text (data->item_info.name,
+ data->item_info.description);
+ pixbuf = panel_addto_make_pixbuf (data->item_info.icon);
+ gtk_tree_store_set (store, &iter,
+ COLUMN_ICON, pixbuf,
+ COLUMN_TEXT, text,
+ COLUMN_DATA, &(data->item_info),
+ COLUMN_SEARCH, data->item_info.name,
+ -1);
+
+ if (pixbuf)
+ g_object_unref (pixbuf);
+
+ g_free (text);
+
+ if (data->children != NULL)
+ panel_addto_populate_application_model (store,
+ &iter,
+ data->children);
+ }
+}
+
+static void panel_addto_make_application_model(PanelAddtoDialog* dialog)
+{
+ GtkTreeStore* store;
+ MateMenuTree* tree;
+ MateMenuTreeDirectory* root;
+
+ if (dialog->filter_application_model != NULL)
+ return;
+
+ store = gtk_tree_store_new(NUMBER_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING);
+
+ tree = matemenu_tree_lookup("mate-applications.menu", MATEMENU_TREE_FLAGS_NONE);
+ matemenu_tree_set_sort_key(tree, MATEMENU_TREE_SORT_DISPLAY_NAME);
+
+ if ((root = matemenu_tree_get_root_directory (tree)))
+ {
+ panel_addto_make_application_list(&dialog->application_list, root, "mate-applications.menu");
+ panel_addto_populate_application_model(store, NULL, dialog->application_list);
+
+ matemenu_tree_item_unref(root);
+ }
+
+ matemenu_tree_unref(tree);
+
+ tree = matemenu_tree_lookup("mate-settings.menu", MATEMENU_TREE_FLAGS_NONE);
+ matemenu_tree_set_sort_key(tree, MATEMENU_TREE_SORT_DISPLAY_NAME);
+
+ if ((root = matemenu_tree_get_root_directory(tree)))
+ {
+ GtkTreeIter iter;
+
+ gtk_tree_store_append(store, &iter, NULL);
+ gtk_tree_store_set(store, &iter, COLUMN_ICON, NULL, COLUMN_TEXT, NULL, COLUMN_DATA, NULL, COLUMN_SEARCH, NULL, -1);
+
+ panel_addto_make_application_list(&dialog->settings_list, root, "mate-settings.menu");
+ panel_addto_populate_application_model(store, NULL, dialog->settings_list);
+
+ matemenu_tree_item_unref(root);
+ }
+
+ matemenu_tree_unref(tree);
+
+ dialog->application_model = GTK_TREE_MODEL(store);
+ dialog->filter_application_model = gtk_tree_model_filter_new(GTK_TREE_MODEL(dialog->application_model), NULL);
+ gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(dialog->filter_application_model), panel_addto_filter_func, dialog, NULL);
+}
+
+static void
+panel_addto_add_item (PanelAddtoDialog *dialog,
+ PanelAddtoItemInfo *item_info)
+{
+ g_assert (item_info != NULL);
+
+ switch (item_info->type) {
+ case PANEL_ADDTO_APPLET:
+ mate_panel_applet_frame_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position,
+ item_info->iid);
+ break;
+ case PANEL_ADDTO_ACTION:
+ panel_action_button_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position,
+ item_info->action_type);
+ break;
+ case PANEL_ADDTO_LAUNCHER_MENU:
+ panel_addto_present_applications (dialog);
+ break;
+ case PANEL_ADDTO_LAUNCHER:
+ panel_launcher_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position,
+ item_info->launcher_path);
+ break;
+ case PANEL_ADDTO_LAUNCHER_NEW:
+ ask_about_launcher (NULL, dialog->panel_widget,
+ dialog->insertion_position, FALSE);
+ break;
+ case PANEL_ADDTO_MENU:
+ panel_menu_button_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position,
+ item_info->menu_filename,
+ item_info->menu_path,
+ item_info->menu_path != NULL,
+ item_info->name);
+ break;
+ case PANEL_ADDTO_MENUBAR:
+ panel_menu_bar_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position);
+ break;
+ case PANEL_ADDTO_SEPARATOR:
+ panel_separator_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position);
+ break;
+ case PANEL_ADDTO_DRAWER:
+ panel_drawer_create (dialog->panel_widget->toplevel,
+ dialog->insertion_position,
+ NULL, FALSE, NULL);
+ break;
+ }
+}
+
+static void
+panel_addto_dialog_response (GtkWidget *widget_dialog,
+ guint response_id,
+ PanelAddtoDialog *dialog)
+{
+ GtkTreeSelection *selection;
+ GtkTreeModel *filter_model;
+ GtkTreeModel *child_model;
+ GtkTreeIter iter;
+ GtkTreeIter filter_iter;
+
+ switch (response_id) {
+ case GTK_RESPONSE_HELP:
+ panel_show_help (gtk_window_get_screen (GTK_WINDOW (dialog->addto_dialog)),
+ "user-guide", "gospanel-15", NULL);
+ break;
+
+ case PANEL_ADDTO_RESPONSE_ADD:
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tree_view));
+ if (gtk_tree_selection_get_selected (selection, &filter_model,
+ &filter_iter)) {
+ PanelAddtoItemInfo *data;
+
+ gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter_model),
+ &iter,
+ &filter_iter);
+ child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model));
+ gtk_tree_model_get (child_model, &iter,
+ COLUMN_DATA, &data, -1);
+
+ if (data != NULL)
+ panel_addto_add_item (dialog, data);
+ }
+ break;
+
+ case PANEL_ADDTO_RESPONSE_BACK:
+ /* This response only happens when we're showing the
+ * application list and the user wants to go back to the
+ * applet list. */
+ panel_addto_present_applets (dialog);
+ break;
+
+ case GTK_RESPONSE_CLOSE:
+ gtk_widget_destroy (widget_dialog);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+panel_addto_dialog_destroy (GtkWidget *widget_dialog,
+ PanelAddtoDialog *dialog)
+{
+ panel_toplevel_pop_autohide_disabler (PANEL_TOPLEVEL (dialog->panel_widget->toplevel));
+ g_object_set_qdata (G_OBJECT (dialog->panel_widget->toplevel),
+ panel_addto_dialog_quark,
+ NULL);
+}
+
+static void
+panel_addto_present_applications (PanelAddtoDialog *dialog)
+{
+ if (dialog->filter_application_model == NULL)
+ panel_addto_make_application_model (dialog);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->tree_view),
+ dialog->filter_application_model);
+ gtk_window_set_focus (GTK_WINDOW (dialog->addto_dialog),
+ dialog->search_entry);
+ gtk_widget_set_sensitive (dialog->back_button, TRUE);
+
+ if (dialog->applet_search_text)
+ g_free (dialog->applet_search_text);
+
+ dialog->applet_search_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->search_entry)));
+ /* show everything */
+ gtk_entry_set_text (GTK_ENTRY (dialog->search_entry), "");
+}
+
+static void
+panel_addto_present_applets (PanelAddtoDialog *dialog)
+{
+ if (dialog->filter_applet_model == NULL)
+ panel_addto_make_applet_model (dialog);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->tree_view),
+ dialog->filter_applet_model);
+ gtk_window_set_focus (GTK_WINDOW (dialog->addto_dialog),
+ dialog->search_entry);
+ gtk_widget_set_sensitive (dialog->back_button, FALSE);
+
+ if (dialog->applet_search_text) {
+ gtk_entry_set_text (GTK_ENTRY (dialog->search_entry),
+ dialog->applet_search_text);
+ gtk_editable_set_position (GTK_EDITABLE (dialog->search_entry),
+ -1);
+
+ g_free (dialog->applet_search_text);
+ dialog->applet_search_text = NULL;
+ }
+}
+
+static void
+panel_addto_dialog_free_item_info (PanelAddtoItemInfo *item_info)
+{
+ if (item_info == NULL || item_info->static_data)
+ return;
+
+ if (item_info->name != NULL)
+ g_free (item_info->name);
+ item_info->name = NULL;
+
+ if (item_info->description != NULL)
+ g_free (item_info->description);
+ item_info->description = NULL;
+
+ if (item_info->icon != NULL)
+ g_free (item_info->icon);
+ item_info->icon = NULL;
+
+ if (item_info->iid != NULL)
+ g_free (item_info->iid);
+ item_info->iid = NULL;
+
+ if (item_info->launcher_path != NULL)
+ g_free (item_info->launcher_path);
+ item_info->launcher_path = NULL;
+
+ if (item_info->menu_filename != NULL)
+ g_free (item_info->menu_filename);
+ item_info->menu_filename = NULL;
+
+ if (item_info->menu_path != NULL)
+ g_free (item_info->menu_path);
+ item_info->menu_path = NULL;
+}
+
+static void
+panel_addto_dialog_free_application_list (GSList *application_list)
+{
+ PanelAddtoAppList *data;
+ GSList *app;
+
+ if (application_list == NULL)
+ return;
+
+ for (app = application_list; app != NULL; app = app->next) {
+ data = app->data;
+ if (data->children) {
+ panel_addto_dialog_free_application_list (data->children);
+ }
+ panel_addto_dialog_free_item_info (&data->item_info);
+ g_free (data);
+ }
+ g_slist_free (application_list);
+}
+
+static void
+panel_addto_dialog_free (PanelAddtoDialog *dialog)
+{
+ MateConfClient *client;
+ GSList *item;
+
+ client = panel_mateconf_get_client ();
+
+ if (dialog->name_notify)
+ mateconf_client_notify_remove (client, dialog->name_notify);
+ dialog->name_notify = 0;
+
+ if (dialog->search_text)
+ g_free (dialog->search_text);
+ dialog->search_text = NULL;
+
+ if (dialog->applet_search_text)
+ g_free (dialog->applet_search_text);
+ dialog->applet_search_text = NULL;
+
+ if (dialog->addto_dialog)
+ gtk_widget_destroy (dialog->addto_dialog);
+ dialog->addto_dialog = NULL;
+
+ for (item = dialog->applet_list; item != NULL; item = item->next) {
+ PanelAddtoItemInfo *applet;
+
+ applet = (PanelAddtoItemInfo *) item->data;
+ if (!applet->static_data) {
+ panel_addto_dialog_free_item_info (applet);
+ g_free (applet);
+ }
+ }
+ g_slist_free (dialog->applet_list);
+
+ panel_addto_dialog_free_application_list (dialog->application_list);
+ panel_addto_dialog_free_application_list (dialog->settings_list);
+
+ if (dialog->filter_applet_model)
+ g_object_unref (dialog->filter_applet_model);
+ dialog->filter_applet_model = NULL;
+
+ if (dialog->applet_model)
+ g_object_unref (dialog->applet_model);
+ dialog->applet_model = NULL;
+
+ if (dialog->filter_application_model)
+ g_object_unref (dialog->filter_application_model);
+ dialog->filter_application_model = NULL;
+
+ if (dialog->application_model)
+ g_object_unref (dialog->application_model);
+ dialog->application_model = NULL;
+
+ if (dialog->menu_tree)
+ matemenu_tree_unref (dialog->menu_tree);
+ dialog->menu_tree = NULL;
+
+ g_free (dialog);
+}
+
+static void
+panel_addto_name_change (PanelAddtoDialog *dialog,
+ const char *name)
+{
+ char *title;
+ char *label;
+
+ label = NULL;
+
+ if (!PANEL_GLIB_STR_EMPTY (name))
+ label = g_strdup_printf (_("Find an _item to add to \"%s\":"),
+ name);
+
+ if (panel_toplevel_get_is_attached (dialog->panel_widget->toplevel)) {
+ title = g_strdup_printf (_("Add to Drawer"));
+ if (label == NULL)
+ label = g_strdup (_("Find an _item to add to the drawer:"));
+ } else {
+ title = g_strdup_printf (_("Add to Panel"));
+ if (label == NULL)
+ label = g_strdup (_("Find an _item to add to the panel:"));
+ }
+
+ gtk_window_set_title (GTK_WINDOW (dialog->addto_dialog), title);
+ g_free (title);
+
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (dialog->label), label);
+ g_free (label);
+}
+
+static void
+panel_addto_name_notify (MateConfClient *client,
+ guint cnxn_id,
+ MateConfEntry *entry,
+ PanelAddtoDialog *dialog)
+{
+ MateConfValue *value;
+ const char *key;
+ const char *text = NULL;
+
+ key = panel_mateconf_basename (mateconf_entry_get_key (entry));
+
+ if (strcmp (key, "name"))
+ return;
+
+ value = mateconf_entry_get_value (entry);
+
+ if (value && value->type == MATECONF_VALUE_STRING)
+ text = mateconf_value_get_string (value);
+
+ if (text)
+ panel_addto_name_change (dialog, text);
+}
+
+static gboolean
+panel_addto_filter_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer userdata)
+{
+ PanelAddtoDialog *dialog;
+ PanelAddtoItemInfo *data;
+
+ dialog = (PanelAddtoDialog *) userdata;
+
+ if (!dialog->search_text || !dialog->search_text[0])
+ return TRUE;
+
+ gtk_tree_model_get (model, iter, COLUMN_DATA, &data, -1);
+
+ if (data == NULL)
+ return FALSE;
+
+ /* This is more a workaround than anything else: show all the root
+ * items in a tree store */
+ if (GTK_IS_TREE_STORE (model) &&
+ gtk_tree_store_iter_depth (GTK_TREE_STORE (model), iter) == 0)
+ return TRUE;
+
+ return (panel_g_utf8_strstrcase (data->name,
+ dialog->search_text) != NULL ||
+ panel_g_utf8_strstrcase (data->description,
+ dialog->search_text) != NULL);
+}
+
+static void
+panel_addto_search_entry_changed (GtkWidget *entry,
+ PanelAddtoDialog *dialog)
+{
+ GtkTreeModel *model;
+ char *new_text;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ new_text = g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->search_entry)));
+ g_strchomp (new_text);
+
+ if (dialog->search_text &&
+ g_utf8_collate (new_text, dialog->search_text) == 0) {
+ g_free (new_text);
+ return;
+ }
+
+ if (dialog->search_text)
+ g_free (dialog->search_text);
+ dialog->search_text = new_text;
+
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->tree_view));
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (model));
+
+ path = gtk_tree_path_new_first ();
+ if (gtk_tree_model_get_iter (model, &iter, path)) {
+ GtkTreeSelection *selection;
+
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (dialog->tree_view),
+ path, NULL, FALSE, 0, 0);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tree_view));
+ gtk_tree_selection_select_path (selection, path);
+ }
+ gtk_tree_path_free (path);
+}
+
+static void
+panel_addto_search_entry_activated (GtkWidget *entry,
+ PanelAddtoDialog *dialog)
+{
+ gtk_dialog_response (GTK_DIALOG (dialog->addto_dialog),
+ PANEL_ADDTO_RESPONSE_ADD);
+}
+
+static void
+panel_addto_selection_changed (GtkTreeSelection *selection,
+ PanelAddtoDialog *dialog)
+{
+ GtkTreeModel *filter_model;
+ GtkTreeModel *child_model;
+ GtkTreeIter iter;
+ GtkTreeIter filter_iter;
+ PanelAddtoItemInfo *data;
+ char *iid;
+
+ if (!gtk_tree_selection_get_selected (selection,
+ &filter_model,
+ &filter_iter)) {
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->add_button),
+ FALSE);
+ return;
+ }
+
+ gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (filter_model),
+ &iter, &filter_iter);
+ child_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model));
+ gtk_tree_model_get (child_model, &iter, COLUMN_DATA, &data, -1);
+
+ if (!data) {
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->add_button),
+ FALSE);
+ return;
+ }
+
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->add_button), TRUE);
+
+ if (data->type == PANEL_ADDTO_LAUNCHER_MENU) {
+ gtk_button_set_label (GTK_BUTTON (dialog->add_button),
+ GTK_STOCK_GO_FORWARD);
+ } else {
+ gtk_button_set_label (GTK_BUTTON (dialog->add_button),
+ GTK_STOCK_ADD);
+ }
+ gtk_button_set_use_stock (GTK_BUTTON (dialog->add_button),
+ TRUE);
+
+ /* only allow dragging applets if we can add applets */
+ if (panel_profile_id_lists_are_writable ()) {
+ switch (data->type) {
+ case PANEL_ADDTO_LAUNCHER:
+ panel_addto_setup_launcher_drag (GTK_TREE_VIEW (dialog->tree_view),
+ data->launcher_path);
+ break;
+ case PANEL_ADDTO_APPLET:
+ panel_addto_setup_applet_drag (GTK_TREE_VIEW (dialog->tree_view),
+ data->iid);
+ break;
+ case PANEL_ADDTO_LAUNCHER_MENU:
+ gtk_tree_view_unset_rows_drag_source (GTK_TREE_VIEW (dialog->tree_view));
+ break;
+ case PANEL_ADDTO_MENU:
+ /* build the iid for menus other than the main menu */
+ if (data->iid == NULL) {
+ iid = g_strdup_printf ("MENU:%s/%s",
+ data->menu_filename,
+ data->menu_path);
+ } else {
+ iid = g_strdup (data->iid);
+ }
+ panel_addto_setup_internal_applet_drag (GTK_TREE_VIEW (dialog->tree_view),
+ iid);
+ g_free (iid);
+ break;
+ default:
+ panel_addto_setup_internal_applet_drag (GTK_TREE_VIEW (dialog->tree_view),
+ data->iid);
+ break;
+ }
+ }
+}
+
+static void
+panel_addto_selection_activated (GtkTreeView *view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ PanelAddtoDialog *dialog)
+{
+ gtk_dialog_response (GTK_DIALOG (dialog->addto_dialog),
+ PANEL_ADDTO_RESPONSE_ADD);
+}
+
+static gboolean
+panel_addto_separator_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ int column = GPOINTER_TO_INT (data);
+ char *text;
+
+ gtk_tree_model_get (model, iter, column, &text, -1);
+
+ if (!text)
+ return TRUE;
+
+ g_free(text);
+ return FALSE;
+}
+
+static PanelAddtoDialog *
+panel_addto_dialog_new (PanelWidget *panel_widget)
+{
+ PanelAddtoDialog *dialog;
+ GtkWidget *dialog_vbox;
+ GtkWidget *vbox;
+ GtkWidget *inner_vbox;
+ GtkWidget *find_hbox;
+ GtkWidget *sw;
+ GtkCellRenderer *renderer;
+ GtkTreeSelection *selection;
+ GtkTreeViewColumn *column;
+
+ dialog = g_new0 (PanelAddtoDialog, 1);
+
+ g_object_set_qdata_full (G_OBJECT (panel_widget->toplevel),
+ panel_addto_dialog_quark,
+ dialog,
+ (GDestroyNotify) panel_addto_dialog_free);
+
+ dialog->panel_widget = panel_widget;
+ dialog->name_notify =
+ panel_profile_toplevel_notify_add (
+ dialog->panel_widget->toplevel,
+ "name",
+ (MateConfClientNotifyFunc) panel_addto_name_notify,
+ dialog);
+
+
+ dialog->addto_dialog = gtk_dialog_new ();
+ gtk_dialog_add_button (GTK_DIALOG (dialog->addto_dialog),
+ GTK_STOCK_HELP, GTK_RESPONSE_HELP);
+ dialog->back_button = gtk_dialog_add_button (GTK_DIALOG (dialog->addto_dialog),
+ GTK_STOCK_GO_BACK,
+ PANEL_ADDTO_RESPONSE_BACK);
+ dialog->add_button = gtk_dialog_add_button (GTK_DIALOG (dialog->addto_dialog),
+ GTK_STOCK_ADD,
+ PANEL_ADDTO_RESPONSE_ADD);
+ gtk_dialog_add_button (GTK_DIALOG (dialog->addto_dialog),
+ GTK_STOCK_CLOSE,
+ GTK_RESPONSE_CLOSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (dialog->add_button), FALSE);
+ gtk_dialog_set_has_separator (GTK_DIALOG (dialog->addto_dialog),
+ FALSE);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog->addto_dialog),
+ PANEL_ADDTO_RESPONSE_ADD);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog->addto_dialog), 5);
+
+ dialog_vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog->addto_dialog));
+ gtk_box_set_spacing (GTK_BOX (dialog_vbox), 2);
+
+ g_signal_connect (G_OBJECT (dialog->addto_dialog), "response",
+ G_CALLBACK (panel_addto_dialog_response), dialog);
+ g_signal_connect (dialog->addto_dialog, "destroy",
+ G_CALLBACK (panel_addto_dialog_destroy), dialog);
+
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+ gtk_container_add (GTK_CONTAINER (dialog_vbox), vbox);
+
+ inner_vbox = gtk_vbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (vbox), inner_vbox, TRUE, TRUE, 0);
+
+ find_hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (inner_vbox), find_hbox, FALSE, FALSE, 0);
+
+ dialog->label = gtk_label_new_with_mnemonic ("");
+ gtk_misc_set_alignment (GTK_MISC (dialog->label), 0.0, 0.5);
+ gtk_label_set_use_markup (GTK_LABEL (dialog->label), TRUE);
+
+ gtk_box_pack_start (GTK_BOX (find_hbox), dialog->label,
+ FALSE, FALSE, 0);
+
+ dialog->search_entry = gtk_entry_new ();
+ g_signal_connect (G_OBJECT (dialog->search_entry), "changed",
+ G_CALLBACK (panel_addto_search_entry_changed), dialog);
+ g_signal_connect (G_OBJECT (dialog->search_entry), "activate",
+ G_CALLBACK (panel_addto_search_entry_activated), dialog);
+
+ gtk_box_pack_end (GTK_BOX (find_hbox), dialog->search_entry,
+ TRUE, TRUE, 0);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (dialog->label),
+ dialog->search_entry);
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+ GTK_SHADOW_IN);
+ gtk_box_pack_start (GTK_BOX (inner_vbox), sw, TRUE, TRUE, 0);
+
+ dialog->tree_view = gtk_tree_view_new ();
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dialog->tree_view),
+ FALSE);
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (dialog->tree_view));
+
+ renderer = g_object_new (GTK_TYPE_CELL_RENDERER_PIXBUF,
+ "xpad", 4,
+ "ypad", 4,
+ NULL);
+
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (dialog->tree_view),
+ -1, NULL,
+ renderer,
+ "pixbuf", COLUMN_ICON,
+ NULL);
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (dialog->tree_view),
+ -1, NULL,
+ renderer,
+ "markup", COLUMN_TEXT,
+ NULL);
+
+ //FIXME use the same search than the one for the search entry?
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (dialog->tree_view),
+ COLUMN_SEARCH);
+
+ gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (dialog->tree_view),
+ panel_addto_separator_func,
+ GINT_TO_POINTER (COLUMN_TEXT),
+ NULL);
+
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->tree_view));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->tree_view),
+ COLUMN_TEXT);
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (panel_addto_selection_changed),
+ dialog);
+
+ g_signal_connect (dialog->tree_view, "row-activated",
+ G_CALLBACK (panel_addto_selection_activated),
+ dialog);
+
+ gtk_container_add (GTK_CONTAINER (sw), dialog->tree_view);
+
+ gtk_widget_show_all (vbox);
+
+ panel_toplevel_push_autohide_disabler (dialog->panel_widget->toplevel);
+ panel_widget_register_open_dialog (panel_widget,
+ dialog->addto_dialog);
+
+ panel_addto_name_change (dialog,
+ panel_toplevel_get_name (dialog->panel_widget->toplevel));
+
+ return dialog;
+}
+
+#define MAX_ADDTOPANEL_HEIGHT 490
+
+void
+panel_addto_present (GtkMenuItem *item,
+ PanelWidget *panel_widget)
+{
+ PanelAddtoDialog *dialog;
+ PanelToplevel *toplevel;
+ PanelData *pd;
+ GdkScreen *screen;
+ gint screen_height;
+ gint height;
+
+ toplevel = panel_widget->toplevel;
+ pd = g_object_get_data (G_OBJECT (toplevel), "PanelData");
+
+ if (!panel_addto_dialog_quark)
+ panel_addto_dialog_quark =
+ g_quark_from_static_string ("panel-addto-dialog");
+
+ dialog = g_object_get_qdata (G_OBJECT (toplevel),
+ panel_addto_dialog_quark);
+
+ screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
+ screen_height = gdk_screen_get_height (screen);
+ height = MIN (MAX_ADDTOPANEL_HEIGHT, 3 * (screen_height / 4));
+
+ if (!dialog) {
+ dialog = panel_addto_dialog_new (panel_widget);
+ panel_addto_present_applets (dialog);
+ }
+
+ dialog->insertion_position = pd ? pd->insertion_pos : -1;
+ gtk_window_set_screen (GTK_WINDOW (dialog->addto_dialog), screen);
+ gtk_window_set_default_size (GTK_WINDOW (dialog->addto_dialog),
+ height * 8 / 7, height);
+ gtk_window_present (GTK_WINDOW (dialog->addto_dialog));
+}